1268899Sbapt/* $Id: reader.c,v 1.47 2014/04/09 21:09:27 tom Exp $ */ 2234949Sbapt 3234949Sbapt#include "defs.h" 4234949Sbapt 5234949Sbapt/* The line size must be a positive integer. One hundred was chosen */ 6234949Sbapt/* because few lines in Yacc input grammars exceed 100 characters. */ 7234949Sbapt/* Note that if a line exceeds LINESIZE characters, the line buffer */ 8234949Sbapt/* will be expanded to accomodate it. */ 9234949Sbapt 10234949Sbapt#define LINESIZE 100 11234949Sbapt 12268899Sbapt#define L_CURL '{' 13268899Sbapt#define R_CURL '}' 14268899Sbapt#define L_PAREN '(' 15268899Sbapt#define R_PAREN ')' 16268899Sbapt#define L_BRAC '[' 17268899Sbapt#define R_BRAC ']' 18234949Sbapt 19268899Sbapt/* the maximum number of arguments (inherited attributes) to a non-terminal */ 20268899Sbapt/* this is a hard limit, but seems more than adequate */ 21268899Sbapt#define MAXARGS 20 22268899Sbapt 23234949Sbaptstatic void start_rule(bucket *bp, int s_lineno); 24268899Sbapt#if defined(YYBTYACC) 25268899Sbaptstatic void copy_destructor(void); 26268899Sbaptstatic char *process_destructor_XX(char *code, char *tag); 27268899Sbapt#endif 28234949Sbapt 29234949Sbaptstatic char *cache; 30234949Sbaptstatic int cinc, cache_size; 31234949Sbapt 32234949Sbaptint ntags; 33268899Sbaptstatic int tagmax, havetags; 34234949Sbaptstatic char **tag_table; 35234949Sbapt 36234949Sbaptstatic char saw_eof; 37234949Sbaptchar unionized; 38234949Sbaptchar *cptr, *line; 39234949Sbaptstatic int linesize; 40234949Sbapt 41234949Sbaptstatic bucket *goal; 42234949Sbaptstatic Value_t prec; 43234949Sbaptstatic int gensym; 44234949Sbaptstatic char last_was_action; 45234949Sbapt 46234949Sbaptstatic int maxitems; 47234949Sbaptstatic bucket **pitem; 48234949Sbapt 49234949Sbaptstatic int maxrules; 50234949Sbaptstatic bucket **plhs; 51234949Sbapt 52234949Sbaptstatic size_t name_pool_size; 53234949Sbaptstatic char *name_pool; 54234949Sbapt 55234949Sbaptchar line_format[] = "#line %d \"%s\"\n"; 56234949Sbapt 57234949Sbaptparam *lex_param; 58234949Sbaptparam *parse_param; 59234949Sbapt 60268899Sbapt#if defined(YYBTYACC) 61268899Sbaptint destructor = 0; /* =1 if at least one %destructor */ 62268899Sbapt 63268899Sbaptstatic bucket *default_destructor[3] = 64268899Sbapt{0, 0, 0}; 65268899Sbapt 66268899Sbapt#define UNTYPED_DEFAULT 0 67268899Sbapt#define TYPED_DEFAULT 1 68268899Sbapt#define TYPE_SPECIFIED 2 69268899Sbapt 70268899Sbaptstatic bucket * 71268899Sbaptlookup_type_destructor(char *tag) 72268899Sbapt{ 73268899Sbapt char name[1024] = "\0"; 74268899Sbapt bucket *bp, **bpp = &default_destructor[TYPE_SPECIFIED]; 75268899Sbapt 76268899Sbapt while ((bp = *bpp) != NULL) 77268899Sbapt { 78268899Sbapt if (bp->tag == tag) 79268899Sbapt return (bp); 80268899Sbapt bpp = &bp->link; 81268899Sbapt } 82268899Sbapt 83268899Sbapt *bpp = bp = make_bucket(strcat(strcpy(name, tag), " destructor")); 84268899Sbapt bp->tag = tag; 85268899Sbapt 86268899Sbapt return (bp); 87268899Sbapt} 88268899Sbapt#endif /* defined(YYBTYACC) */ 89268899Sbapt 90234949Sbaptstatic void 91234949Sbaptcachec(int c) 92234949Sbapt{ 93234949Sbapt assert(cinc >= 0); 94234949Sbapt if (cinc >= cache_size) 95234949Sbapt { 96234949Sbapt cache_size += 256; 97240517Sbapt cache = TREALLOC(char, cache, cache_size); 98234949Sbapt NO_SPACE(cache); 99234949Sbapt } 100234949Sbapt cache[cinc] = (char)c; 101234949Sbapt ++cinc; 102234949Sbapt} 103234949Sbapt 104234949Sbaptstatic void 105234949Sbaptget_line(void) 106234949Sbapt{ 107234949Sbapt FILE *f = input_file; 108234949Sbapt int c; 109234949Sbapt int i; 110234949Sbapt 111234949Sbapt if (saw_eof || (c = getc(f)) == EOF) 112234949Sbapt { 113234949Sbapt if (line) 114234949Sbapt { 115234949Sbapt FREE(line); 116234949Sbapt line = 0; 117234949Sbapt } 118234949Sbapt cptr = 0; 119234949Sbapt saw_eof = 1; 120234949Sbapt return; 121234949Sbapt } 122234949Sbapt 123234949Sbapt if (line == 0 || linesize != (LINESIZE + 1)) 124234949Sbapt { 125234949Sbapt if (line) 126234949Sbapt FREE(line); 127234949Sbapt linesize = LINESIZE + 1; 128240517Sbapt line = TMALLOC(char, linesize); 129234949Sbapt NO_SPACE(line); 130234949Sbapt } 131234949Sbapt 132234949Sbapt i = 0; 133234949Sbapt ++lineno; 134234949Sbapt for (;;) 135234949Sbapt { 136234949Sbapt line[i] = (char)c; 137234949Sbapt if (c == '\n') 138268899Sbapt break; 139234949Sbapt if (++i >= linesize) 140234949Sbapt { 141234949Sbapt linesize += LINESIZE; 142240517Sbapt line = TREALLOC(char, line, linesize); 143234949Sbapt NO_SPACE(line); 144234949Sbapt } 145234949Sbapt c = getc(f); 146234949Sbapt if (c == EOF) 147234949Sbapt { 148234949Sbapt line[i] = '\n'; 149234949Sbapt saw_eof = 1; 150268899Sbapt break; 151234949Sbapt } 152234949Sbapt } 153268899Sbapt cptr = line; 154268899Sbapt return; 155234949Sbapt} 156234949Sbapt 157234949Sbaptstatic char * 158234949Sbaptdup_line(void) 159234949Sbapt{ 160234949Sbapt char *p, *s, *t; 161234949Sbapt 162234949Sbapt if (line == 0) 163234949Sbapt return (0); 164234949Sbapt s = line; 165234949Sbapt while (*s != '\n') 166234949Sbapt ++s; 167240517Sbapt p = TMALLOC(char, s - line + 1); 168234949Sbapt NO_SPACE(p); 169234949Sbapt 170234949Sbapt s = line; 171234949Sbapt t = p; 172234949Sbapt while ((*t++ = *s++) != '\n') 173234949Sbapt continue; 174234949Sbapt return (p); 175234949Sbapt} 176234949Sbapt 177234949Sbaptstatic void 178234949Sbaptskip_comment(void) 179234949Sbapt{ 180234949Sbapt char *s; 181234949Sbapt 182234949Sbapt int st_lineno = lineno; 183234949Sbapt char *st_line = dup_line(); 184234949Sbapt char *st_cptr = st_line + (cptr - line); 185234949Sbapt 186234949Sbapt s = cptr + 2; 187234949Sbapt for (;;) 188234949Sbapt { 189234949Sbapt if (*s == '*' && s[1] == '/') 190234949Sbapt { 191234949Sbapt cptr = s + 2; 192234949Sbapt FREE(st_line); 193234949Sbapt return; 194234949Sbapt } 195234949Sbapt if (*s == '\n') 196234949Sbapt { 197234949Sbapt get_line(); 198234949Sbapt if (line == 0) 199234949Sbapt unterminated_comment(st_lineno, st_line, st_cptr); 200234949Sbapt s = cptr; 201234949Sbapt } 202234949Sbapt else 203234949Sbapt ++s; 204234949Sbapt } 205234949Sbapt} 206234949Sbapt 207234949Sbaptstatic int 208234949Sbaptnextc(void) 209234949Sbapt{ 210234949Sbapt char *s; 211234949Sbapt 212234949Sbapt if (line == 0) 213234949Sbapt { 214234949Sbapt get_line(); 215234949Sbapt if (line == 0) 216234949Sbapt return (EOF); 217234949Sbapt } 218234949Sbapt 219234949Sbapt s = cptr; 220234949Sbapt for (;;) 221234949Sbapt { 222234949Sbapt switch (*s) 223234949Sbapt { 224234949Sbapt case '\n': 225234949Sbapt get_line(); 226234949Sbapt if (line == 0) 227234949Sbapt return (EOF); 228234949Sbapt s = cptr; 229234949Sbapt break; 230234949Sbapt 231234949Sbapt case ' ': 232234949Sbapt case '\t': 233234949Sbapt case '\f': 234234949Sbapt case '\r': 235234949Sbapt case '\v': 236234949Sbapt case ',': 237234949Sbapt case ';': 238234949Sbapt ++s; 239234949Sbapt break; 240234949Sbapt 241234949Sbapt case '\\': 242234949Sbapt cptr = s; 243234949Sbapt return ('%'); 244234949Sbapt 245234949Sbapt case '/': 246234949Sbapt if (s[1] == '*') 247234949Sbapt { 248234949Sbapt cptr = s; 249234949Sbapt skip_comment(); 250234949Sbapt s = cptr; 251234949Sbapt break; 252234949Sbapt } 253234949Sbapt else if (s[1] == '/') 254234949Sbapt { 255234949Sbapt get_line(); 256234949Sbapt if (line == 0) 257234949Sbapt return (EOF); 258234949Sbapt s = cptr; 259234949Sbapt break; 260234949Sbapt } 261234949Sbapt /* FALLTHRU */ 262234949Sbapt 263234949Sbapt default: 264234949Sbapt cptr = s; 265234949Sbapt return (*s); 266234949Sbapt } 267234949Sbapt } 268234949Sbapt} 269268899Sbapt/* *INDENT-OFF* */ 270268899Sbaptstatic struct keyword 271268899Sbapt{ 272268899Sbapt char name[13]; 273268899Sbapt int token; 274268899Sbapt} 275268899Sbaptkeywords[] = { 276268899Sbapt { "binary", NONASSOC }, 277268899Sbapt#if defined(YYBTYACC) 278268899Sbapt { "destructor", DESTRUCTOR }, 279268899Sbapt#endif 280268899Sbapt { "expect", EXPECT }, 281268899Sbapt { "expect-rr", EXPECT_RR }, 282268899Sbapt { "ident", IDENT }, 283268899Sbapt { "left", LEFT }, 284268899Sbapt { "lex-param", LEX_PARAM }, 285268899Sbapt#if defined(YYBTYACC) 286268899Sbapt { "locations", LOCATIONS }, 287268899Sbapt#endif 288268899Sbapt { "nonassoc", NONASSOC }, 289268899Sbapt { "parse-param", PARSE_PARAM }, 290268899Sbapt { "pure-parser", PURE_PARSER }, 291268899Sbapt { "right", RIGHT }, 292268899Sbapt { "start", START }, 293268899Sbapt { "term", TOKEN }, 294268899Sbapt { "token", TOKEN }, 295268899Sbapt { "token-table", TOKEN_TABLE }, 296268899Sbapt { "type", TYPE }, 297268899Sbapt { "union", UNION }, 298268899Sbapt { "yacc", POSIX_YACC }, 299268899Sbapt}; 300268899Sbapt/* *INDENT-ON* */ 301234949Sbapt 302234949Sbaptstatic int 303268899Sbaptcompare_keys(const void *a, const void *b) 304234949Sbapt{ 305268899Sbapt const struct keyword *p = (const struct keyword *)a; 306268899Sbapt const struct keyword *q = (const struct keyword *)b; 307268899Sbapt return strcmp(p->name, q->name); 308234949Sbapt} 309234949Sbapt 310234949Sbaptstatic int 311234949Sbaptkeyword(void) 312234949Sbapt{ 313234949Sbapt int c; 314234949Sbapt char *t_cptr = cptr; 315268899Sbapt struct keyword *key; 316234949Sbapt 317234949Sbapt c = *++cptr; 318234949Sbapt if (isalpha(c)) 319234949Sbapt { 320234949Sbapt cinc = 0; 321234949Sbapt for (;;) 322234949Sbapt { 323234949Sbapt if (isalpha(c)) 324234949Sbapt { 325234949Sbapt if (isupper(c)) 326234949Sbapt c = tolower(c); 327234949Sbapt cachec(c); 328234949Sbapt } 329234949Sbapt else if (isdigit(c) 330234949Sbapt || c == '-' 331234949Sbapt || c == '.' 332234949Sbapt || c == '$') 333234949Sbapt { 334234949Sbapt cachec(c); 335234949Sbapt } 336268899Sbapt else if (c == '_') 337268899Sbapt { 338268899Sbapt /* treat keywords spelled with '_' as if it were '-' */ 339268899Sbapt cachec('-'); 340268899Sbapt } 341234949Sbapt else 342234949Sbapt { 343234949Sbapt break; 344234949Sbapt } 345234949Sbapt c = *++cptr; 346234949Sbapt } 347234949Sbapt cachec(NUL); 348234949Sbapt 349268899Sbapt if ((key = bsearch(cache, keywords, 350268899Sbapt sizeof(keywords) / sizeof(*key), 351268899Sbapt sizeof(*key), compare_keys))) 352268899Sbapt return key->token; 353234949Sbapt } 354234949Sbapt else 355234949Sbapt { 356234949Sbapt ++cptr; 357234949Sbapt if (c == L_CURL) 358234949Sbapt return (TEXT); 359234949Sbapt if (c == '%' || c == '\\') 360234949Sbapt return (MARK); 361234949Sbapt if (c == '<') 362234949Sbapt return (LEFT); 363234949Sbapt if (c == '>') 364234949Sbapt return (RIGHT); 365234949Sbapt if (c == '0') 366234949Sbapt return (TOKEN); 367234949Sbapt if (c == '2') 368234949Sbapt return (NONASSOC); 369234949Sbapt } 370234949Sbapt syntax_error(lineno, line, t_cptr); 371235723Sbapt return (-1); 372234949Sbapt} 373234949Sbapt 374234949Sbaptstatic void 375234949Sbaptcopy_ident(void) 376234949Sbapt{ 377234949Sbapt int c; 378234949Sbapt FILE *f = output_file; 379234949Sbapt 380234949Sbapt c = nextc(); 381234949Sbapt if (c == EOF) 382234949Sbapt unexpected_EOF(); 383234949Sbapt if (c != '"') 384234949Sbapt syntax_error(lineno, line, cptr); 385234949Sbapt ++outline; 386234949Sbapt fprintf(f, "#ident \""); 387234949Sbapt for (;;) 388234949Sbapt { 389234949Sbapt c = *++cptr; 390234949Sbapt if (c == '\n') 391234949Sbapt { 392234949Sbapt fprintf(f, "\"\n"); 393234949Sbapt return; 394234949Sbapt } 395234949Sbapt putc(c, f); 396234949Sbapt if (c == '"') 397234949Sbapt { 398234949Sbapt putc('\n', f); 399234949Sbapt ++cptr; 400234949Sbapt return; 401234949Sbapt } 402234949Sbapt } 403234949Sbapt} 404234949Sbapt 405268899Sbaptstatic char * 406268899Sbaptcopy_string(int quote) 407268899Sbapt{ 408268899Sbapt struct mstring *temp = msnew(); 409268899Sbapt int c; 410268899Sbapt int s_lineno = lineno; 411268899Sbapt char *s_line = dup_line(); 412268899Sbapt char *s_cptr = s_line + (cptr - line - 1); 413268899Sbapt 414268899Sbapt for (;;) 415268899Sbapt { 416268899Sbapt c = *cptr++; 417268899Sbapt mputc(temp, c); 418268899Sbapt if (c == quote) 419268899Sbapt { 420268899Sbapt FREE(s_line); 421268899Sbapt return msdone(temp); 422268899Sbapt } 423268899Sbapt if (c == '\n') 424268899Sbapt unterminated_string(s_lineno, s_line, s_cptr); 425268899Sbapt if (c == '\\') 426268899Sbapt { 427268899Sbapt c = *cptr++; 428268899Sbapt mputc(temp, c); 429268899Sbapt if (c == '\n') 430268899Sbapt { 431268899Sbapt get_line(); 432268899Sbapt if (line == 0) 433268899Sbapt unterminated_string(s_lineno, s_line, s_cptr); 434268899Sbapt } 435268899Sbapt } 436268899Sbapt } 437268899Sbapt} 438268899Sbapt 439268899Sbaptstatic char * 440268899Sbaptcopy_comment(void) 441268899Sbapt{ 442268899Sbapt struct mstring *temp = msnew(); 443268899Sbapt int c; 444268899Sbapt 445268899Sbapt c = *cptr; 446268899Sbapt if (c == '/') 447268899Sbapt { 448268899Sbapt mputc(temp, '*'); 449268899Sbapt while ((c = *++cptr) != '\n') 450268899Sbapt { 451268899Sbapt mputc(temp, c); 452268899Sbapt if (c == '*' && cptr[1] == '/') 453268899Sbapt mputc(temp, ' '); 454268899Sbapt } 455268899Sbapt mputc(temp, '*'); 456268899Sbapt mputc(temp, '/'); 457268899Sbapt } 458268899Sbapt else if (c == '*') 459268899Sbapt { 460268899Sbapt int c_lineno = lineno; 461268899Sbapt char *c_line = dup_line(); 462268899Sbapt char *c_cptr = c_line + (cptr - line - 1); 463268899Sbapt 464268899Sbapt mputc(temp, c); 465268899Sbapt ++cptr; 466268899Sbapt for (;;) 467268899Sbapt { 468268899Sbapt c = *cptr++; 469268899Sbapt mputc(temp, c); 470268899Sbapt if (c == '*' && *cptr == '/') 471268899Sbapt { 472268899Sbapt mputc(temp, '/'); 473268899Sbapt ++cptr; 474268899Sbapt FREE(c_line); 475268899Sbapt return msdone(temp); 476268899Sbapt } 477268899Sbapt if (c == '\n') 478268899Sbapt { 479268899Sbapt get_line(); 480268899Sbapt if (line == 0) 481268899Sbapt unterminated_comment(c_lineno, c_line, c_cptr); 482268899Sbapt } 483268899Sbapt } 484268899Sbapt } 485268899Sbapt return msdone(temp); 486268899Sbapt} 487268899Sbapt 488234949Sbaptstatic void 489234949Sbaptcopy_text(void) 490234949Sbapt{ 491234949Sbapt int c; 492234949Sbapt FILE *f = text_file; 493234949Sbapt int need_newline = 0; 494234949Sbapt int t_lineno = lineno; 495234949Sbapt char *t_line = dup_line(); 496234949Sbapt char *t_cptr = t_line + (cptr - line - 2); 497234949Sbapt 498234949Sbapt if (*cptr == '\n') 499234949Sbapt { 500234949Sbapt get_line(); 501234949Sbapt if (line == 0) 502234949Sbapt unterminated_text(t_lineno, t_line, t_cptr); 503234949Sbapt } 504234949Sbapt if (!lflag) 505234949Sbapt fprintf(f, line_format, lineno, input_file_name); 506234949Sbapt 507234949Sbapt loop: 508234949Sbapt c = *cptr++; 509234949Sbapt switch (c) 510234949Sbapt { 511234949Sbapt case '\n': 512234949Sbapt putc('\n', f); 513234949Sbapt need_newline = 0; 514234949Sbapt get_line(); 515234949Sbapt if (line) 516234949Sbapt goto loop; 517234949Sbapt unterminated_text(t_lineno, t_line, t_cptr); 518234949Sbapt 519234949Sbapt case '\'': 520234949Sbapt case '"': 521268899Sbapt putc(c, f); 522234949Sbapt { 523268899Sbapt char *s = copy_string(c); 524268899Sbapt fputs(s, f); 525268899Sbapt free(s); 526234949Sbapt } 527268899Sbapt need_newline = 1; 528268899Sbapt goto loop; 529234949Sbapt 530234949Sbapt case '/': 531234949Sbapt putc(c, f); 532234949Sbapt { 533268899Sbapt char *s = copy_comment(); 534268899Sbapt fputs(s, f); 535268899Sbapt free(s); 536234949Sbapt } 537234949Sbapt need_newline = 1; 538234949Sbapt goto loop; 539234949Sbapt 540234949Sbapt case '%': 541234949Sbapt case '\\': 542234949Sbapt if (*cptr == R_CURL) 543234949Sbapt { 544234949Sbapt if (need_newline) 545234949Sbapt putc('\n', f); 546234949Sbapt ++cptr; 547234949Sbapt FREE(t_line); 548234949Sbapt return; 549234949Sbapt } 550234949Sbapt /* FALLTHRU */ 551234949Sbapt 552234949Sbapt default: 553234949Sbapt putc(c, f); 554234949Sbapt need_newline = 1; 555234949Sbapt goto loop; 556234949Sbapt } 557234949Sbapt} 558234949Sbapt 559234949Sbaptstatic void 560234949Sbaptputs_both(const char *s) 561234949Sbapt{ 562234949Sbapt fputs(s, text_file); 563234949Sbapt if (dflag) 564234949Sbapt fputs(s, union_file); 565234949Sbapt} 566234949Sbapt 567234949Sbaptstatic void 568234949Sbaptputc_both(int c) 569234949Sbapt{ 570234949Sbapt putc(c, text_file); 571234949Sbapt if (dflag) 572234949Sbapt putc(c, union_file); 573234949Sbapt} 574234949Sbapt 575234949Sbaptstatic void 576234949Sbaptcopy_union(void) 577234949Sbapt{ 578234949Sbapt int c; 579234949Sbapt int depth; 580234949Sbapt int u_lineno = lineno; 581234949Sbapt char *u_line = dup_line(); 582234949Sbapt char *u_cptr = u_line + (cptr - line - 6); 583234949Sbapt 584234949Sbapt if (unionized) 585234949Sbapt over_unionized(cptr - 6); 586234949Sbapt unionized = 1; 587234949Sbapt 588234949Sbapt if (!lflag) 589234949Sbapt fprintf(text_file, line_format, lineno, input_file_name); 590234949Sbapt 591234949Sbapt puts_both("#ifdef YYSTYPE\n"); 592234949Sbapt puts_both("#undef YYSTYPE_IS_DECLARED\n"); 593234949Sbapt puts_both("#define YYSTYPE_IS_DECLARED 1\n"); 594234949Sbapt puts_both("#endif\n"); 595234949Sbapt puts_both("#ifndef YYSTYPE_IS_DECLARED\n"); 596234949Sbapt puts_both("#define YYSTYPE_IS_DECLARED 1\n"); 597234949Sbapt puts_both("typedef union"); 598234949Sbapt 599234949Sbapt depth = 0; 600234949Sbapt loop: 601234949Sbapt c = *cptr++; 602234949Sbapt putc_both(c); 603234949Sbapt switch (c) 604234949Sbapt { 605234949Sbapt case '\n': 606234949Sbapt get_line(); 607234949Sbapt if (line == 0) 608234949Sbapt unterminated_union(u_lineno, u_line, u_cptr); 609234949Sbapt goto loop; 610234949Sbapt 611234949Sbapt case L_CURL: 612234949Sbapt ++depth; 613234949Sbapt goto loop; 614234949Sbapt 615234949Sbapt case R_CURL: 616234949Sbapt if (--depth == 0) 617234949Sbapt { 618234949Sbapt puts_both(" YYSTYPE;\n"); 619234949Sbapt puts_both("#endif /* !YYSTYPE_IS_DECLARED */\n"); 620234949Sbapt FREE(u_line); 621234949Sbapt return; 622234949Sbapt } 623234949Sbapt goto loop; 624234949Sbapt 625234949Sbapt case '\'': 626234949Sbapt case '"': 627234949Sbapt { 628268899Sbapt char *s = copy_string(c); 629268899Sbapt puts_both(s); 630268899Sbapt free(s); 631234949Sbapt } 632268899Sbapt goto loop; 633234949Sbapt 634234949Sbapt case '/': 635234949Sbapt { 636268899Sbapt char *s = copy_comment(); 637268899Sbapt puts_both(s); 638268899Sbapt free(s); 639234949Sbapt } 640234949Sbapt goto loop; 641234949Sbapt 642234949Sbapt default: 643234949Sbapt goto loop; 644234949Sbapt } 645234949Sbapt} 646234949Sbapt 647234949Sbapt/* 648234949Sbapt * Keep a linked list of parameters 649234949Sbapt */ 650234949Sbaptstatic void 651234949Sbaptcopy_param(int k) 652234949Sbapt{ 653234949Sbapt char *buf; 654234949Sbapt int c; 655234949Sbapt param *head, *p; 656234949Sbapt int i; 657234949Sbapt int name, type2; 658234949Sbapt 659234949Sbapt c = nextc(); 660234949Sbapt if (c == EOF) 661234949Sbapt unexpected_EOF(); 662268899Sbapt if (c != L_CURL) 663234949Sbapt goto out; 664234949Sbapt cptr++; 665234949Sbapt 666234949Sbapt c = nextc(); 667234949Sbapt if (c == EOF) 668234949Sbapt unexpected_EOF(); 669268899Sbapt if (c == R_CURL) 670234949Sbapt goto out; 671234949Sbapt 672240517Sbapt buf = TMALLOC(char, linesize); 673234949Sbapt NO_SPACE(buf); 674234949Sbapt 675268899Sbapt for (i = 0; (c = *cptr++) != R_CURL; i++) 676234949Sbapt { 677234949Sbapt if (c == '\0') 678234949Sbapt missing_brace(); 679234949Sbapt if (c == EOF) 680234949Sbapt unexpected_EOF(); 681234949Sbapt buf[i] = (char)c; 682234949Sbapt } 683234949Sbapt 684234949Sbapt if (i == 0) 685234949Sbapt goto out; 686234949Sbapt 687234949Sbapt buf[i--] = '\0'; 688268899Sbapt while (i > 0 && isspace(UCH(buf[i]))) 689234949Sbapt buf[i--] = '\0'; 690234949Sbapt 691234949Sbapt if (buf[i] == ']') 692234949Sbapt { 693234949Sbapt int level = 1; 694234949Sbapt while (i >= 0 && level > 0 && buf[i] != '[') 695234949Sbapt { 696234949Sbapt if (buf[i] == ']') 697234949Sbapt ++level; 698234949Sbapt else if (buf[i] == '[') 699234949Sbapt --level; 700234949Sbapt i--; 701234949Sbapt } 702234949Sbapt if (i <= 0) 703234949Sbapt unexpected_EOF(); 704234949Sbapt type2 = i--; 705234949Sbapt } 706234949Sbapt else 707234949Sbapt { 708234949Sbapt type2 = i + 1; 709234949Sbapt } 710234949Sbapt 711268899Sbapt while (i > 0 && (isalnum(UCH(buf[i])) || 712268899Sbapt UCH(buf[i]) == '_')) 713234949Sbapt i--; 714234949Sbapt 715234949Sbapt if (!isspace(UCH(buf[i])) && buf[i] != '*') 716234949Sbapt goto out; 717234949Sbapt 718234949Sbapt name = i + 1; 719234949Sbapt 720240517Sbapt p = TMALLOC(param, 1); 721234949Sbapt NO_SPACE(p); 722234949Sbapt 723234949Sbapt p->type2 = strdup(buf + type2); 724234949Sbapt NO_SPACE(p->type2); 725234949Sbapt 726234949Sbapt buf[type2] = '\0'; 727234949Sbapt 728234949Sbapt p->name = strdup(buf + name); 729234949Sbapt NO_SPACE(p->name); 730234949Sbapt 731234949Sbapt buf[name] = '\0'; 732234949Sbapt p->type = buf; 733234949Sbapt 734234949Sbapt if (k == LEX_PARAM) 735234949Sbapt head = lex_param; 736234949Sbapt else 737234949Sbapt head = parse_param; 738234949Sbapt 739234949Sbapt if (head != NULL) 740234949Sbapt { 741234949Sbapt while (head->next) 742234949Sbapt head = head->next; 743234949Sbapt head->next = p; 744234949Sbapt } 745234949Sbapt else 746234949Sbapt { 747234949Sbapt if (k == LEX_PARAM) 748234949Sbapt lex_param = p; 749234949Sbapt else 750234949Sbapt parse_param = p; 751234949Sbapt } 752234949Sbapt p->next = NULL; 753234949Sbapt return; 754234949Sbapt 755234949Sbapt out: 756234949Sbapt syntax_error(lineno, line, cptr); 757234949Sbapt} 758234949Sbapt 759234949Sbaptstatic int 760234949Sbapthexval(int c) 761234949Sbapt{ 762234949Sbapt if (c >= '0' && c <= '9') 763234949Sbapt return (c - '0'); 764234949Sbapt if (c >= 'A' && c <= 'F') 765234949Sbapt return (c - 'A' + 10); 766234949Sbapt if (c >= 'a' && c <= 'f') 767234949Sbapt return (c - 'a' + 10); 768234949Sbapt return (-1); 769234949Sbapt} 770234949Sbapt 771234949Sbaptstatic bucket * 772234949Sbaptget_literal(void) 773234949Sbapt{ 774234949Sbapt int c, quote; 775234949Sbapt int i; 776234949Sbapt int n; 777234949Sbapt char *s; 778234949Sbapt bucket *bp; 779234949Sbapt int s_lineno = lineno; 780234949Sbapt char *s_line = dup_line(); 781234949Sbapt char *s_cptr = s_line + (cptr - line); 782234949Sbapt 783234949Sbapt quote = *cptr++; 784234949Sbapt cinc = 0; 785234949Sbapt for (;;) 786234949Sbapt { 787234949Sbapt c = *cptr++; 788234949Sbapt if (c == quote) 789234949Sbapt break; 790234949Sbapt if (c == '\n') 791234949Sbapt unterminated_string(s_lineno, s_line, s_cptr); 792234949Sbapt if (c == '\\') 793234949Sbapt { 794234949Sbapt char *c_cptr = cptr - 1; 795234949Sbapt 796234949Sbapt c = *cptr++; 797234949Sbapt switch (c) 798234949Sbapt { 799234949Sbapt case '\n': 800234949Sbapt get_line(); 801234949Sbapt if (line == 0) 802234949Sbapt unterminated_string(s_lineno, s_line, s_cptr); 803234949Sbapt continue; 804234949Sbapt 805234949Sbapt case '0': 806234949Sbapt case '1': 807234949Sbapt case '2': 808234949Sbapt case '3': 809234949Sbapt case '4': 810234949Sbapt case '5': 811234949Sbapt case '6': 812234949Sbapt case '7': 813234949Sbapt n = c - '0'; 814234949Sbapt c = *cptr; 815234949Sbapt if (IS_OCTAL(c)) 816234949Sbapt { 817234949Sbapt n = (n << 3) + (c - '0'); 818234949Sbapt c = *++cptr; 819234949Sbapt if (IS_OCTAL(c)) 820234949Sbapt { 821234949Sbapt n = (n << 3) + (c - '0'); 822234949Sbapt ++cptr; 823234949Sbapt } 824234949Sbapt } 825234949Sbapt if (n > MAXCHAR) 826234949Sbapt illegal_character(c_cptr); 827234949Sbapt c = n; 828234949Sbapt break; 829234949Sbapt 830234949Sbapt case 'x': 831234949Sbapt c = *cptr++; 832234949Sbapt n = hexval(c); 833234949Sbapt if (n < 0 || n >= 16) 834234949Sbapt illegal_character(c_cptr); 835234949Sbapt for (;;) 836234949Sbapt { 837234949Sbapt c = *cptr; 838234949Sbapt i = hexval(c); 839234949Sbapt if (i < 0 || i >= 16) 840234949Sbapt break; 841234949Sbapt ++cptr; 842234949Sbapt n = (n << 4) + i; 843234949Sbapt if (n > MAXCHAR) 844234949Sbapt illegal_character(c_cptr); 845234949Sbapt } 846234949Sbapt c = n; 847234949Sbapt break; 848234949Sbapt 849234949Sbapt case 'a': 850234949Sbapt c = 7; 851234949Sbapt break; 852234949Sbapt case 'b': 853234949Sbapt c = '\b'; 854234949Sbapt break; 855234949Sbapt case 'f': 856234949Sbapt c = '\f'; 857234949Sbapt break; 858234949Sbapt case 'n': 859234949Sbapt c = '\n'; 860234949Sbapt break; 861234949Sbapt case 'r': 862234949Sbapt c = '\r'; 863234949Sbapt break; 864234949Sbapt case 't': 865234949Sbapt c = '\t'; 866234949Sbapt break; 867234949Sbapt case 'v': 868234949Sbapt c = '\v'; 869234949Sbapt break; 870234949Sbapt } 871234949Sbapt } 872234949Sbapt cachec(c); 873234949Sbapt } 874234949Sbapt FREE(s_line); 875234949Sbapt 876234949Sbapt n = cinc; 877240517Sbapt s = TMALLOC(char, n); 878234949Sbapt NO_SPACE(s); 879234949Sbapt 880234949Sbapt for (i = 0; i < n; ++i) 881234949Sbapt s[i] = cache[i]; 882234949Sbapt 883234949Sbapt cinc = 0; 884234949Sbapt if (n == 1) 885234949Sbapt cachec('\''); 886234949Sbapt else 887234949Sbapt cachec('"'); 888234949Sbapt 889234949Sbapt for (i = 0; i < n; ++i) 890234949Sbapt { 891234949Sbapt c = UCH(s[i]); 892234949Sbapt if (c == '\\' || c == cache[0]) 893234949Sbapt { 894234949Sbapt cachec('\\'); 895234949Sbapt cachec(c); 896234949Sbapt } 897234949Sbapt else if (isprint(c)) 898234949Sbapt cachec(c); 899234949Sbapt else 900234949Sbapt { 901234949Sbapt cachec('\\'); 902234949Sbapt switch (c) 903234949Sbapt { 904234949Sbapt case 7: 905234949Sbapt cachec('a'); 906234949Sbapt break; 907234949Sbapt case '\b': 908234949Sbapt cachec('b'); 909234949Sbapt break; 910234949Sbapt case '\f': 911234949Sbapt cachec('f'); 912234949Sbapt break; 913234949Sbapt case '\n': 914234949Sbapt cachec('n'); 915234949Sbapt break; 916234949Sbapt case '\r': 917234949Sbapt cachec('r'); 918234949Sbapt break; 919234949Sbapt case '\t': 920234949Sbapt cachec('t'); 921234949Sbapt break; 922234949Sbapt case '\v': 923234949Sbapt cachec('v'); 924234949Sbapt break; 925234949Sbapt default: 926234949Sbapt cachec(((c >> 6) & 7) + '0'); 927234949Sbapt cachec(((c >> 3) & 7) + '0'); 928234949Sbapt cachec((c & 7) + '0'); 929234949Sbapt break; 930234949Sbapt } 931234949Sbapt } 932234949Sbapt } 933234949Sbapt 934234949Sbapt if (n == 1) 935234949Sbapt cachec('\''); 936234949Sbapt else 937234949Sbapt cachec('"'); 938234949Sbapt 939234949Sbapt cachec(NUL); 940234949Sbapt bp = lookup(cache); 941234949Sbapt bp->class = TERM; 942234949Sbapt if (n == 1 && bp->value == UNDEFINED) 943234949Sbapt bp->value = UCH(*s); 944234949Sbapt FREE(s); 945234949Sbapt 946234949Sbapt return (bp); 947234949Sbapt} 948234949Sbapt 949234949Sbaptstatic int 950234949Sbaptis_reserved(char *name) 951234949Sbapt{ 952234949Sbapt char *s; 953234949Sbapt 954234949Sbapt if (strcmp(name, ".") == 0 || 955234949Sbapt strcmp(name, "$accept") == 0 || 956234949Sbapt strcmp(name, "$end") == 0) 957234949Sbapt return (1); 958234949Sbapt 959234949Sbapt if (name[0] == '$' && name[1] == '$' && isdigit(UCH(name[2]))) 960234949Sbapt { 961234949Sbapt s = name + 3; 962234949Sbapt while (isdigit(UCH(*s))) 963234949Sbapt ++s; 964234949Sbapt if (*s == NUL) 965234949Sbapt return (1); 966234949Sbapt } 967234949Sbapt 968234949Sbapt return (0); 969234949Sbapt} 970234949Sbapt 971234949Sbaptstatic bucket * 972234949Sbaptget_name(void) 973234949Sbapt{ 974234949Sbapt int c; 975234949Sbapt 976234949Sbapt cinc = 0; 977234949Sbapt for (c = *cptr; IS_IDENT(c); c = *++cptr) 978234949Sbapt cachec(c); 979234949Sbapt cachec(NUL); 980234949Sbapt 981234949Sbapt if (is_reserved(cache)) 982234949Sbapt used_reserved(cache); 983234949Sbapt 984234949Sbapt return (lookup(cache)); 985234949Sbapt} 986234949Sbapt 987234949Sbaptstatic Value_t 988234949Sbaptget_number(void) 989234949Sbapt{ 990234949Sbapt int c; 991234949Sbapt Value_t n; 992234949Sbapt 993234949Sbapt n = 0; 994234949Sbapt for (c = *cptr; isdigit(c); c = *++cptr) 995234949Sbapt n = (Value_t) (10 * n + (c - '0')); 996234949Sbapt 997234949Sbapt return (n); 998234949Sbapt} 999234949Sbapt 1000234949Sbaptstatic char * 1001268899Sbaptcache_tag(char *tag, size_t len) 1002268899Sbapt{ 1003268899Sbapt int i; 1004268899Sbapt char *s; 1005268899Sbapt 1006268899Sbapt for (i = 0; i < ntags; ++i) 1007268899Sbapt { 1008268899Sbapt if (strncmp(tag, tag_table[i], len) == 0 && 1009268899Sbapt tag_table[i][len] == NUL) 1010268899Sbapt return (tag_table[i]); 1011268899Sbapt } 1012268899Sbapt 1013268899Sbapt if (ntags >= tagmax) 1014268899Sbapt { 1015268899Sbapt tagmax += 16; 1016268899Sbapt tag_table = 1017268899Sbapt (tag_table 1018268899Sbapt ? TREALLOC(char *, tag_table, tagmax) 1019268899Sbapt : TMALLOC(char *, tagmax)); 1020268899Sbapt NO_SPACE(tag_table); 1021268899Sbapt } 1022268899Sbapt 1023268899Sbapt s = TMALLOC(char, len + 1); 1024268899Sbapt NO_SPACE(s); 1025268899Sbapt 1026268899Sbapt strncpy(s, tag, len); 1027268899Sbapt s[len] = 0; 1028268899Sbapt tag_table[ntags++] = s; 1029268899Sbapt return s; 1030268899Sbapt} 1031268899Sbapt 1032268899Sbaptstatic char * 1033234949Sbaptget_tag(void) 1034234949Sbapt{ 1035234949Sbapt int c; 1036234949Sbapt int t_lineno = lineno; 1037234949Sbapt char *t_line = dup_line(); 1038234949Sbapt char *t_cptr = t_line + (cptr - line); 1039234949Sbapt 1040234949Sbapt ++cptr; 1041234949Sbapt c = nextc(); 1042234949Sbapt if (c == EOF) 1043234949Sbapt unexpected_EOF(); 1044234949Sbapt if (!isalpha(c) && c != '_' && c != '$') 1045234949Sbapt illegal_tag(t_lineno, t_line, t_cptr); 1046234949Sbapt 1047234949Sbapt cinc = 0; 1048234949Sbapt do 1049234949Sbapt { 1050234949Sbapt cachec(c); 1051234949Sbapt c = *++cptr; 1052234949Sbapt } 1053234949Sbapt while (IS_IDENT(c)); 1054234949Sbapt cachec(NUL); 1055234949Sbapt 1056234949Sbapt c = nextc(); 1057234949Sbapt if (c == EOF) 1058234949Sbapt unexpected_EOF(); 1059234949Sbapt if (c != '>') 1060234949Sbapt illegal_tag(t_lineno, t_line, t_cptr); 1061234949Sbapt ++cptr; 1062234949Sbapt 1063268899Sbapt FREE(t_line); 1064268899Sbapt havetags = 1; 1065268899Sbapt return cache_tag(cache, (size_t) cinc); 1066268899Sbapt} 1067234949Sbapt 1068268899Sbapt#if defined(YYBTYACC) 1069268899Sbaptstatic char * 1070268899Sbaptscan_id(void) 1071268899Sbapt{ 1072268899Sbapt char *b = cptr; 1073234949Sbapt 1074268899Sbapt while (isalnum(*cptr) || *cptr == '_' || *cptr == '$') 1075268899Sbapt cptr++; 1076268899Sbapt return cache_tag(b, (size_t) (cptr - b)); 1077234949Sbapt} 1078268899Sbapt#endif 1079234949Sbapt 1080234949Sbaptstatic void 1081234949Sbaptdeclare_tokens(int assoc) 1082234949Sbapt{ 1083234949Sbapt int c; 1084234949Sbapt bucket *bp; 1085234949Sbapt Value_t value; 1086234949Sbapt char *tag = 0; 1087234949Sbapt 1088234949Sbapt if (assoc != TOKEN) 1089234949Sbapt ++prec; 1090234949Sbapt 1091234949Sbapt c = nextc(); 1092234949Sbapt if (c == EOF) 1093234949Sbapt unexpected_EOF(); 1094234949Sbapt if (c == '<') 1095234949Sbapt { 1096234949Sbapt tag = get_tag(); 1097234949Sbapt c = nextc(); 1098234949Sbapt if (c == EOF) 1099234949Sbapt unexpected_EOF(); 1100234949Sbapt } 1101234949Sbapt 1102234949Sbapt for (;;) 1103234949Sbapt { 1104234949Sbapt if (isalpha(c) || c == '_' || c == '.' || c == '$') 1105234949Sbapt bp = get_name(); 1106234949Sbapt else if (c == '\'' || c == '"') 1107234949Sbapt bp = get_literal(); 1108234949Sbapt else 1109234949Sbapt return; 1110234949Sbapt 1111234949Sbapt if (bp == goal) 1112234949Sbapt tokenized_start(bp->name); 1113234949Sbapt bp->class = TERM; 1114234949Sbapt 1115234949Sbapt if (tag) 1116234949Sbapt { 1117234949Sbapt if (bp->tag && tag != bp->tag) 1118234949Sbapt retyped_warning(bp->name); 1119234949Sbapt bp->tag = tag; 1120234949Sbapt } 1121234949Sbapt 1122234949Sbapt if (assoc != TOKEN) 1123234949Sbapt { 1124234949Sbapt if (bp->prec && prec != bp->prec) 1125234949Sbapt reprec_warning(bp->name); 1126234949Sbapt bp->assoc = (Assoc_t) assoc; 1127234949Sbapt bp->prec = prec; 1128234949Sbapt } 1129234949Sbapt 1130234949Sbapt c = nextc(); 1131234949Sbapt if (c == EOF) 1132234949Sbapt unexpected_EOF(); 1133234949Sbapt 1134234949Sbapt if (isdigit(c)) 1135234949Sbapt { 1136234949Sbapt value = get_number(); 1137234949Sbapt if (bp->value != UNDEFINED && value != bp->value) 1138234949Sbapt revalued_warning(bp->name); 1139234949Sbapt bp->value = value; 1140234949Sbapt c = nextc(); 1141234949Sbapt if (c == EOF) 1142234949Sbapt unexpected_EOF(); 1143234949Sbapt } 1144234949Sbapt } 1145234949Sbapt} 1146234949Sbapt 1147234949Sbapt/* 1148234949Sbapt * %expect requires special handling 1149234949Sbapt * as it really isn't part of the yacc 1150234949Sbapt * grammar only a flag for yacc proper. 1151234949Sbapt */ 1152234949Sbaptstatic void 1153234949Sbaptdeclare_expect(int assoc) 1154234949Sbapt{ 1155234949Sbapt int c; 1156234949Sbapt 1157234949Sbapt if (assoc != EXPECT && assoc != EXPECT_RR) 1158234949Sbapt ++prec; 1159234949Sbapt 1160234949Sbapt /* 1161234949Sbapt * Stay away from nextc - doesn't 1162234949Sbapt * detect EOL and will read to EOF. 1163234949Sbapt */ 1164234949Sbapt c = *++cptr; 1165234949Sbapt if (c == EOF) 1166234949Sbapt unexpected_EOF(); 1167234949Sbapt 1168234949Sbapt for (;;) 1169234949Sbapt { 1170234949Sbapt if (isdigit(c)) 1171234949Sbapt { 1172234949Sbapt if (assoc == EXPECT) 1173234949Sbapt SRexpect = get_number(); 1174234949Sbapt else 1175234949Sbapt RRexpect = get_number(); 1176234949Sbapt break; 1177234949Sbapt } 1178234949Sbapt /* 1179234949Sbapt * Looking for number before EOL. 1180234949Sbapt * Spaces, tabs, and numbers are ok, 1181234949Sbapt * words, punc., etc. are syntax errors. 1182234949Sbapt */ 1183234949Sbapt else if (c == '\n' || isalpha(c) || !isspace(c)) 1184234949Sbapt { 1185234949Sbapt syntax_error(lineno, line, cptr); 1186234949Sbapt } 1187234949Sbapt else 1188234949Sbapt { 1189234949Sbapt c = *++cptr; 1190234949Sbapt if (c == EOF) 1191234949Sbapt unexpected_EOF(); 1192234949Sbapt } 1193234949Sbapt } 1194234949Sbapt} 1195234949Sbapt 1196268899Sbapt#if defined(YYBTYACC) 1197234949Sbaptstatic void 1198268899Sbaptdeclare_argtypes(bucket *bp) 1199268899Sbapt{ 1200268899Sbapt char *tags[MAXARGS]; 1201268899Sbapt int args = 0, c; 1202268899Sbapt 1203268899Sbapt if (bp->args >= 0) 1204268899Sbapt retyped_warning(bp->name); 1205268899Sbapt cptr++; /* skip open paren */ 1206268899Sbapt for (;;) 1207268899Sbapt { 1208268899Sbapt c = nextc(); 1209268899Sbapt if (c == EOF) 1210268899Sbapt unexpected_EOF(); 1211268899Sbapt if (c != '<') 1212268899Sbapt syntax_error(lineno, line, cptr); 1213268899Sbapt tags[args++] = get_tag(); 1214268899Sbapt c = nextc(); 1215268899Sbapt if (c == R_PAREN) 1216268899Sbapt break; 1217268899Sbapt if (c == EOF) 1218268899Sbapt unexpected_EOF(); 1219268899Sbapt } 1220268899Sbapt cptr++; /* skip close paren */ 1221268899Sbapt bp->args = args; 1222268899Sbapt bp->argnames = TMALLOC(char *, args); 1223268899Sbapt NO_SPACE(bp->argnames); 1224268899Sbapt bp->argtags = CALLOC(sizeof(char *), args + 1); 1225268899Sbapt NO_SPACE(bp->argtags); 1226268899Sbapt while (--args >= 0) 1227268899Sbapt { 1228268899Sbapt bp->argtags[args] = tags[args]; 1229268899Sbapt bp->argnames[args] = NULL; 1230268899Sbapt } 1231268899Sbapt} 1232268899Sbapt#endif 1233268899Sbapt 1234268899Sbaptstatic void 1235234949Sbaptdeclare_types(void) 1236234949Sbapt{ 1237234949Sbapt int c; 1238234949Sbapt bucket *bp; 1239268899Sbapt char *tag = NULL; 1240234949Sbapt 1241234949Sbapt c = nextc(); 1242234949Sbapt if (c == EOF) 1243234949Sbapt unexpected_EOF(); 1244268899Sbapt if (c == '<') 1245268899Sbapt tag = get_tag(); 1246234949Sbapt 1247234949Sbapt for (;;) 1248234949Sbapt { 1249234949Sbapt c = nextc(); 1250268899Sbapt if (c == EOF) 1251268899Sbapt unexpected_EOF(); 1252234949Sbapt if (isalpha(c) || c == '_' || c == '.' || c == '$') 1253268899Sbapt { 1254234949Sbapt bp = get_name(); 1255268899Sbapt#if defined(YYBTYACC) 1256268899Sbapt if (nextc() == L_PAREN) 1257268899Sbapt declare_argtypes(bp); 1258268899Sbapt else 1259268899Sbapt bp->args = 0; 1260268899Sbapt#endif 1261268899Sbapt } 1262234949Sbapt else if (c == '\'' || c == '"') 1263268899Sbapt { 1264234949Sbapt bp = get_literal(); 1265268899Sbapt#if defined(YYBTYACC) 1266268899Sbapt bp->args = 0; 1267268899Sbapt#endif 1268268899Sbapt } 1269234949Sbapt else 1270234949Sbapt return; 1271234949Sbapt 1272268899Sbapt if (tag) 1273268899Sbapt { 1274268899Sbapt if (bp->tag && tag != bp->tag) 1275268899Sbapt retyped_warning(bp->name); 1276268899Sbapt bp->tag = tag; 1277268899Sbapt } 1278234949Sbapt } 1279234949Sbapt} 1280234949Sbapt 1281234949Sbaptstatic void 1282234949Sbaptdeclare_start(void) 1283234949Sbapt{ 1284234949Sbapt int c; 1285234949Sbapt bucket *bp; 1286234949Sbapt 1287234949Sbapt c = nextc(); 1288234949Sbapt if (c == EOF) 1289234949Sbapt unexpected_EOF(); 1290234949Sbapt if (!isalpha(c) && c != '_' && c != '.' && c != '$') 1291234949Sbapt syntax_error(lineno, line, cptr); 1292234949Sbapt bp = get_name(); 1293234949Sbapt if (bp->class == TERM) 1294234949Sbapt terminal_start(bp->name); 1295234949Sbapt if (goal && goal != bp) 1296234949Sbapt restarted_warning(); 1297234949Sbapt goal = bp; 1298234949Sbapt} 1299234949Sbapt 1300234949Sbaptstatic void 1301234949Sbaptread_declarations(void) 1302234949Sbapt{ 1303234949Sbapt int c, k; 1304234949Sbapt 1305234949Sbapt cache_size = 256; 1306240517Sbapt cache = TMALLOC(char, cache_size); 1307234949Sbapt NO_SPACE(cache); 1308234949Sbapt 1309234949Sbapt for (;;) 1310234949Sbapt { 1311234949Sbapt c = nextc(); 1312234949Sbapt if (c == EOF) 1313234949Sbapt unexpected_EOF(); 1314234949Sbapt if (c != '%') 1315234949Sbapt syntax_error(lineno, line, cptr); 1316234949Sbapt switch (k = keyword()) 1317234949Sbapt { 1318234949Sbapt case MARK: 1319234949Sbapt return; 1320234949Sbapt 1321234949Sbapt case IDENT: 1322234949Sbapt copy_ident(); 1323234949Sbapt break; 1324234949Sbapt 1325234949Sbapt case TEXT: 1326234949Sbapt copy_text(); 1327234949Sbapt break; 1328234949Sbapt 1329234949Sbapt case UNION: 1330234949Sbapt copy_union(); 1331234949Sbapt break; 1332234949Sbapt 1333234949Sbapt case TOKEN: 1334234949Sbapt case LEFT: 1335234949Sbapt case RIGHT: 1336234949Sbapt case NONASSOC: 1337234949Sbapt declare_tokens(k); 1338234949Sbapt break; 1339234949Sbapt 1340234949Sbapt case EXPECT: 1341234949Sbapt case EXPECT_RR: 1342234949Sbapt declare_expect(k); 1343234949Sbapt break; 1344234949Sbapt 1345234949Sbapt case TYPE: 1346234949Sbapt declare_types(); 1347234949Sbapt break; 1348234949Sbapt 1349234949Sbapt case START: 1350234949Sbapt declare_start(); 1351234949Sbapt break; 1352234949Sbapt 1353234949Sbapt case PURE_PARSER: 1354234949Sbapt pure_parser = 1; 1355234949Sbapt break; 1356234949Sbapt 1357234949Sbapt case PARSE_PARAM: 1358234949Sbapt case LEX_PARAM: 1359234949Sbapt copy_param(k); 1360234949Sbapt break; 1361234949Sbapt 1362268899Sbapt case TOKEN_TABLE: 1363268899Sbapt token_table = 1; 1364268899Sbapt break; 1365268899Sbapt 1366268899Sbapt#if defined(YYBTYACC) 1367268899Sbapt case LOCATIONS: 1368268899Sbapt locations = 1; 1369268899Sbapt break; 1370268899Sbapt 1371268899Sbapt case DESTRUCTOR: 1372268899Sbapt destructor = 1; 1373268899Sbapt copy_destructor(); 1374268899Sbapt break; 1375268899Sbapt#endif 1376268899Sbapt 1377234949Sbapt case POSIX_YACC: 1378234949Sbapt /* noop for bison compatibility. byacc is already designed to be posix 1379234949Sbapt * yacc compatible. */ 1380234949Sbapt break; 1381234949Sbapt } 1382234949Sbapt } 1383234949Sbapt} 1384234949Sbapt 1385234949Sbaptstatic void 1386234949Sbaptinitialize_grammar(void) 1387234949Sbapt{ 1388234949Sbapt nitems = 4; 1389234949Sbapt maxitems = 300; 1390234949Sbapt 1391240517Sbapt pitem = TMALLOC(bucket *, maxitems); 1392234949Sbapt NO_SPACE(pitem); 1393234949Sbapt 1394234949Sbapt pitem[0] = 0; 1395234949Sbapt pitem[1] = 0; 1396234949Sbapt pitem[2] = 0; 1397234949Sbapt pitem[3] = 0; 1398234949Sbapt 1399234949Sbapt nrules = 3; 1400234949Sbapt maxrules = 100; 1401234949Sbapt 1402240517Sbapt plhs = TMALLOC(bucket *, maxrules); 1403234949Sbapt NO_SPACE(plhs); 1404234949Sbapt 1405234949Sbapt plhs[0] = 0; 1406234949Sbapt plhs[1] = 0; 1407234949Sbapt plhs[2] = 0; 1408234949Sbapt 1409240517Sbapt rprec = TMALLOC(Value_t, maxrules); 1410234949Sbapt NO_SPACE(rprec); 1411234949Sbapt 1412234949Sbapt rprec[0] = 0; 1413234949Sbapt rprec[1] = 0; 1414234949Sbapt rprec[2] = 0; 1415234949Sbapt 1416240517Sbapt rassoc = TMALLOC(Assoc_t, maxrules); 1417234949Sbapt NO_SPACE(rassoc); 1418234949Sbapt 1419234949Sbapt rassoc[0] = TOKEN; 1420234949Sbapt rassoc[1] = TOKEN; 1421234949Sbapt rassoc[2] = TOKEN; 1422234949Sbapt} 1423234949Sbapt 1424234949Sbaptstatic void 1425234949Sbaptexpand_items(void) 1426234949Sbapt{ 1427234949Sbapt maxitems += 300; 1428240517Sbapt pitem = TREALLOC(bucket *, pitem, maxitems); 1429234949Sbapt NO_SPACE(pitem); 1430234949Sbapt} 1431234949Sbapt 1432234949Sbaptstatic void 1433234949Sbaptexpand_rules(void) 1434234949Sbapt{ 1435234949Sbapt maxrules += 100; 1436234949Sbapt 1437240517Sbapt plhs = TREALLOC(bucket *, plhs, maxrules); 1438234949Sbapt NO_SPACE(plhs); 1439234949Sbapt 1440240517Sbapt rprec = TREALLOC(Value_t, rprec, maxrules); 1441234949Sbapt NO_SPACE(rprec); 1442234949Sbapt 1443240517Sbapt rassoc = TREALLOC(Assoc_t, rassoc, maxrules); 1444234949Sbapt NO_SPACE(rassoc); 1445234949Sbapt} 1446234949Sbapt 1447268899Sbapt/* set immediately prior to where copy_args() could be called, and incremented by 1448268899Sbapt the various routines that will rescan the argument list as appropriate */ 1449268899Sbaptstatic int rescan_lineno; 1450268899Sbapt#if defined(YYBTYACC) 1451268899Sbapt 1452268899Sbaptstatic char * 1453268899Sbaptcopy_args(int *alen) 1454268899Sbapt{ 1455268899Sbapt struct mstring *s = msnew(); 1456268899Sbapt int depth = 0, len = 1; 1457268899Sbapt char c, quote = 0; 1458268899Sbapt int a_lineno = lineno; 1459268899Sbapt char *a_line = dup_line(); 1460268899Sbapt char *a_cptr = a_line + (cptr - line - 1); 1461268899Sbapt 1462268899Sbapt while ((c = *cptr++) != R_PAREN || depth || quote) 1463268899Sbapt { 1464268899Sbapt if (c == ',' && !quote && !depth) 1465268899Sbapt { 1466268899Sbapt len++; 1467268899Sbapt mputc(s, 0); 1468268899Sbapt continue; 1469268899Sbapt } 1470268899Sbapt mputc(s, c); 1471268899Sbapt if (c == '\n') 1472268899Sbapt { 1473268899Sbapt get_line(); 1474268899Sbapt if (!line) 1475268899Sbapt { 1476268899Sbapt if (quote) 1477268899Sbapt unterminated_string(a_lineno, a_line, a_cptr); 1478268899Sbapt else 1479268899Sbapt unterminated_arglist(a_lineno, a_line, a_cptr); 1480268899Sbapt } 1481268899Sbapt } 1482268899Sbapt else if (quote) 1483268899Sbapt { 1484268899Sbapt if (c == quote) 1485268899Sbapt quote = 0; 1486268899Sbapt else if (c == '\\') 1487268899Sbapt { 1488268899Sbapt if (*cptr != '\n') 1489268899Sbapt mputc(s, *cptr++); 1490268899Sbapt } 1491268899Sbapt } 1492268899Sbapt else 1493268899Sbapt { 1494268899Sbapt if (c == L_PAREN) 1495268899Sbapt depth++; 1496268899Sbapt else if (c == R_PAREN) 1497268899Sbapt depth--; 1498268899Sbapt else if (c == '\"' || c == '\'') 1499268899Sbapt quote = c; 1500268899Sbapt } 1501268899Sbapt } 1502268899Sbapt if (alen) 1503268899Sbapt *alen = len; 1504268899Sbapt FREE(a_line); 1505268899Sbapt return msdone(s); 1506268899Sbapt} 1507268899Sbapt 1508268899Sbaptstatic char * 1509268899Sbaptparse_id(char *p, char **save) 1510268899Sbapt{ 1511268899Sbapt char *b; 1512268899Sbapt 1513268899Sbapt while (isspace(*p)) 1514268899Sbapt if (*p++ == '\n') 1515268899Sbapt rescan_lineno++; 1516268899Sbapt if (!isalpha(*p) && *p != '_') 1517268899Sbapt return NULL; 1518268899Sbapt b = p; 1519268899Sbapt while (isalnum(*p) || *p == '_' || *p == '$') 1520268899Sbapt p++; 1521268899Sbapt if (save) 1522268899Sbapt { 1523268899Sbapt *save = cache_tag(b, (size_t) (p - b)); 1524268899Sbapt } 1525268899Sbapt return p; 1526268899Sbapt} 1527268899Sbapt 1528268899Sbaptstatic char * 1529268899Sbaptparse_int(char *p, int *save) 1530268899Sbapt{ 1531268899Sbapt int neg = 0, val = 0; 1532268899Sbapt 1533268899Sbapt while (isspace(*p)) 1534268899Sbapt if (*p++ == '\n') 1535268899Sbapt rescan_lineno++; 1536268899Sbapt if (*p == '-') 1537268899Sbapt { 1538268899Sbapt neg = 1; 1539268899Sbapt p++; 1540268899Sbapt } 1541268899Sbapt if (!isdigit(*p)) 1542268899Sbapt return NULL; 1543268899Sbapt while (isdigit(*p)) 1544268899Sbapt val = val * 10 + *p++ - '0'; 1545268899Sbapt if (neg) 1546268899Sbapt val = -val; 1547268899Sbapt if (save) 1548268899Sbapt *save = val; 1549268899Sbapt return p; 1550268899Sbapt} 1551268899Sbapt 1552234949Sbaptstatic void 1553268899Sbaptparse_arginfo(bucket *a, char *args, int argslen) 1554268899Sbapt{ 1555268899Sbapt char *p = args, *tmp; 1556268899Sbapt int i, redec = 0; 1557268899Sbapt 1558268899Sbapt if (a->args > 0) 1559268899Sbapt { 1560268899Sbapt if (a->args != argslen) 1561268899Sbapt arg_number_disagree_warning(rescan_lineno, a->name); 1562268899Sbapt redec = 1; 1563268899Sbapt } 1564268899Sbapt else 1565268899Sbapt { 1566268899Sbapt if ((a->args = argslen) == 0) 1567268899Sbapt return; 1568268899Sbapt a->argnames = TMALLOC(char *, argslen); 1569268899Sbapt NO_SPACE(a->argnames); 1570268899Sbapt a->argtags = TMALLOC(char *, argslen); 1571268899Sbapt NO_SPACE(a->argtags); 1572268899Sbapt } 1573268899Sbapt if (!args) 1574268899Sbapt return; 1575268899Sbapt for (i = 0; i < argslen; i++) 1576268899Sbapt { 1577268899Sbapt while (isspace(*p)) 1578268899Sbapt if (*p++ == '\n') 1579268899Sbapt rescan_lineno++; 1580268899Sbapt if (*p++ != '$') 1581268899Sbapt bad_formals(); 1582268899Sbapt while (isspace(*p)) 1583268899Sbapt if (*p++ == '\n') 1584268899Sbapt rescan_lineno++; 1585268899Sbapt if (*p == '<') 1586268899Sbapt { 1587268899Sbapt havetags = 1; 1588268899Sbapt if (!(p = parse_id(p + 1, &tmp))) 1589268899Sbapt bad_formals(); 1590268899Sbapt while (isspace(*p)) 1591268899Sbapt if (*p++ == '\n') 1592268899Sbapt rescan_lineno++; 1593268899Sbapt if (*p++ != '>') 1594268899Sbapt bad_formals(); 1595268899Sbapt if (redec) 1596268899Sbapt { 1597268899Sbapt if (a->argtags[i] != tmp) 1598268899Sbapt arg_type_disagree_warning(rescan_lineno, i + 1, a->name); 1599268899Sbapt } 1600268899Sbapt else 1601268899Sbapt a->argtags[i] = tmp; 1602268899Sbapt } 1603268899Sbapt else if (!redec) 1604268899Sbapt a->argtags[i] = NULL; 1605268899Sbapt if (!(p = parse_id(p, &a->argnames[i]))) 1606268899Sbapt bad_formals(); 1607268899Sbapt while (isspace(*p)) 1608268899Sbapt if (*p++ == '\n') 1609268899Sbapt rescan_lineno++; 1610268899Sbapt if (*p++) 1611268899Sbapt bad_formals(); 1612268899Sbapt } 1613268899Sbapt free(args); 1614268899Sbapt} 1615268899Sbapt 1616268899Sbaptstatic char * 1617268899Sbaptcompile_arg(char **theptr, char *yyvaltag) 1618268899Sbapt{ 1619268899Sbapt char *p = *theptr; 1620268899Sbapt struct mstring *c = msnew(); 1621268899Sbapt int i, j, n; 1622268899Sbapt Value_t *offsets = NULL, maxoffset; 1623268899Sbapt bucket **rhs; 1624268899Sbapt 1625268899Sbapt maxoffset = 0; 1626268899Sbapt n = 0; 1627268899Sbapt for (i = nitems - 1; pitem[i]; --i) 1628268899Sbapt { 1629268899Sbapt n++; 1630268899Sbapt if (pitem[i]->class != ARGUMENT) 1631268899Sbapt maxoffset++; 1632268899Sbapt } 1633268899Sbapt if (maxoffset > 0) 1634268899Sbapt { 1635268899Sbapt offsets = TMALLOC(Value_t, maxoffset + 1); 1636268899Sbapt NO_SPACE(offsets); 1637268899Sbapt } 1638268899Sbapt for (j = 0, i++; i < nitems; i++) 1639268899Sbapt if (pitem[i]->class != ARGUMENT) 1640268899Sbapt offsets[++j] = (Value_t) (i - nitems + 1); 1641268899Sbapt rhs = pitem + nitems - 1; 1642268899Sbapt 1643268899Sbapt if (yyvaltag) 1644268899Sbapt msprintf(c, "yyval.%s = ", yyvaltag); 1645268899Sbapt else 1646268899Sbapt msprintf(c, "yyval = "); 1647268899Sbapt while (*p) 1648268899Sbapt { 1649268899Sbapt if (*p == '$') 1650268899Sbapt { 1651268899Sbapt char *tag = NULL; 1652268899Sbapt if (*++p == '<') 1653268899Sbapt if (!(p = parse_id(++p, &tag)) || *p++ != '>') 1654268899Sbapt illegal_tag(rescan_lineno, NULL, NULL); 1655268899Sbapt if (isdigit(*p) || *p == '-') 1656268899Sbapt { 1657268899Sbapt int val; 1658268899Sbapt if (!(p = parse_int(p, &val))) 1659268899Sbapt dollar_error(rescan_lineno, NULL, NULL); 1660268899Sbapt if (val <= 0) 1661268899Sbapt i = val - n; 1662268899Sbapt else if (val > maxoffset) 1663268899Sbapt { 1664268899Sbapt dollar_warning(rescan_lineno, val); 1665268899Sbapt i = val - maxoffset; 1666268899Sbapt } 1667268899Sbapt else 1668268899Sbapt { 1669268899Sbapt i = offsets[val]; 1670268899Sbapt if (!tag && !(tag = rhs[i]->tag) && havetags) 1671268899Sbapt untyped_rhs(val, rhs[i]->name); 1672268899Sbapt } 1673268899Sbapt msprintf(c, "yystack.l_mark[%d]", i); 1674268899Sbapt if (tag) 1675268899Sbapt msprintf(c, ".%s", tag); 1676268899Sbapt else if (havetags) 1677268899Sbapt unknown_rhs(val); 1678268899Sbapt } 1679268899Sbapt else if (isalpha(*p) || *p == '_') 1680268899Sbapt { 1681268899Sbapt char *arg; 1682268899Sbapt if (!(p = parse_id(p, &arg))) 1683268899Sbapt dollar_error(rescan_lineno, NULL, NULL); 1684268899Sbapt for (i = plhs[nrules]->args - 1; i >= 0; i--) 1685268899Sbapt if (arg == plhs[nrules]->argnames[i]) 1686268899Sbapt break; 1687268899Sbapt if (i < 0) 1688268899Sbapt unknown_arg_warning(rescan_lineno, "$", arg, NULL, NULL); 1689268899Sbapt else if (!tag) 1690268899Sbapt tag = plhs[nrules]->argtags[i]; 1691268899Sbapt msprintf(c, "yystack.l_mark[%d]", i - plhs[nrules]->args + 1 1692268899Sbapt - n); 1693268899Sbapt if (tag) 1694268899Sbapt msprintf(c, ".%s", tag); 1695268899Sbapt else if (havetags) 1696268899Sbapt untyped_arg_warning(rescan_lineno, "$", arg); 1697268899Sbapt } 1698268899Sbapt else 1699268899Sbapt dollar_error(rescan_lineno, NULL, NULL); 1700268899Sbapt } 1701268899Sbapt else if (*p == '@') 1702268899Sbapt { 1703268899Sbapt at_error(rescan_lineno, NULL, NULL); 1704268899Sbapt } 1705268899Sbapt else 1706268899Sbapt { 1707268899Sbapt if (*p == '\n') 1708268899Sbapt rescan_lineno++; 1709268899Sbapt mputc(c, *p++); 1710268899Sbapt } 1711268899Sbapt } 1712268899Sbapt *theptr = p; 1713268899Sbapt if (maxoffset > 0) 1714268899Sbapt FREE(offsets); 1715268899Sbapt return msdone(c); 1716268899Sbapt} 1717268899Sbapt 1718268899Sbapt#define ARG_CACHE_SIZE 1024 1719268899Sbaptstatic struct arg_cache 1720268899Sbapt{ 1721268899Sbapt struct arg_cache *next; 1722268899Sbapt char *code; 1723268899Sbapt int rule; 1724268899Sbapt} 1725268899Sbapt *arg_cache[ARG_CACHE_SIZE]; 1726268899Sbapt 1727268899Sbaptstatic int 1728268899Sbaptlookup_arg_cache(char *code) 1729268899Sbapt{ 1730268899Sbapt struct arg_cache *entry; 1731268899Sbapt 1732268899Sbapt entry = arg_cache[strnshash(code) % ARG_CACHE_SIZE]; 1733268899Sbapt while (entry) 1734268899Sbapt { 1735268899Sbapt if (!strnscmp(entry->code, code)) 1736268899Sbapt return entry->rule; 1737268899Sbapt entry = entry->next; 1738268899Sbapt } 1739268899Sbapt return -1; 1740268899Sbapt} 1741268899Sbapt 1742268899Sbaptstatic void 1743268899Sbaptinsert_arg_cache(char *code, int rule) 1744268899Sbapt{ 1745268899Sbapt struct arg_cache *entry = NEW(struct arg_cache); 1746268899Sbapt int i; 1747268899Sbapt 1748268899Sbapt NO_SPACE(entry); 1749268899Sbapt i = strnshash(code) % ARG_CACHE_SIZE; 1750268899Sbapt entry->code = code; 1751268899Sbapt entry->rule = rule; 1752268899Sbapt entry->next = arg_cache[i]; 1753268899Sbapt arg_cache[i] = entry; 1754268899Sbapt} 1755268899Sbapt 1756268899Sbaptstatic void 1757268899Sbaptclean_arg_cache(void) 1758268899Sbapt{ 1759268899Sbapt struct arg_cache *e, *t; 1760268899Sbapt int i; 1761268899Sbapt 1762268899Sbapt for (i = 0; i < ARG_CACHE_SIZE; i++) 1763268899Sbapt { 1764268899Sbapt for (e = arg_cache[i]; (t = e); e = e->next, FREE(t)) 1765268899Sbapt free(e->code); 1766268899Sbapt arg_cache[i] = NULL; 1767268899Sbapt } 1768268899Sbapt} 1769268899Sbapt#endif 1770268899Sbapt 1771268899Sbaptstatic void 1772234949Sbaptadvance_to_start(void) 1773234949Sbapt{ 1774234949Sbapt int c; 1775234949Sbapt bucket *bp; 1776234949Sbapt char *s_cptr; 1777234949Sbapt int s_lineno; 1778268899Sbapt#if defined(YYBTYACC) 1779268899Sbapt char *args = NULL; 1780268899Sbapt int argslen = 0; 1781268899Sbapt#endif 1782234949Sbapt 1783234949Sbapt for (;;) 1784234949Sbapt { 1785234949Sbapt c = nextc(); 1786234949Sbapt if (c != '%') 1787234949Sbapt break; 1788234949Sbapt s_cptr = cptr; 1789234949Sbapt switch (keyword()) 1790234949Sbapt { 1791234949Sbapt case MARK: 1792234949Sbapt no_grammar(); 1793234949Sbapt 1794234949Sbapt case TEXT: 1795234949Sbapt copy_text(); 1796234949Sbapt break; 1797234949Sbapt 1798234949Sbapt case START: 1799234949Sbapt declare_start(); 1800234949Sbapt break; 1801234949Sbapt 1802234949Sbapt default: 1803234949Sbapt syntax_error(lineno, line, s_cptr); 1804234949Sbapt } 1805234949Sbapt } 1806234949Sbapt 1807234949Sbapt c = nextc(); 1808234949Sbapt if (!isalpha(c) && c != '_' && c != '.' && c != '_') 1809234949Sbapt syntax_error(lineno, line, cptr); 1810234949Sbapt bp = get_name(); 1811234949Sbapt if (goal == 0) 1812234949Sbapt { 1813234949Sbapt if (bp->class == TERM) 1814234949Sbapt terminal_start(bp->name); 1815234949Sbapt goal = bp; 1816234949Sbapt } 1817234949Sbapt 1818234949Sbapt s_lineno = lineno; 1819234949Sbapt c = nextc(); 1820234949Sbapt if (c == EOF) 1821234949Sbapt unexpected_EOF(); 1822268899Sbapt rescan_lineno = lineno; /* line# for possible inherited args rescan */ 1823268899Sbapt#if defined(YYBTYACC) 1824268899Sbapt if (c == L_PAREN) 1825268899Sbapt { 1826268899Sbapt ++cptr; 1827268899Sbapt args = copy_args(&argslen); 1828268899Sbapt NO_SPACE(args); 1829268899Sbapt c = nextc(); 1830268899Sbapt } 1831268899Sbapt#endif 1832234949Sbapt if (c != ':') 1833234949Sbapt syntax_error(lineno, line, cptr); 1834234949Sbapt start_rule(bp, s_lineno); 1835268899Sbapt#if defined(YYBTYACC) 1836268899Sbapt parse_arginfo(bp, args, argslen); 1837268899Sbapt#endif 1838234949Sbapt ++cptr; 1839234949Sbapt} 1840234949Sbapt 1841234949Sbaptstatic void 1842234949Sbaptstart_rule(bucket *bp, int s_lineno) 1843234949Sbapt{ 1844234949Sbapt if (bp->class == TERM) 1845234949Sbapt terminal_lhs(s_lineno); 1846234949Sbapt bp->class = NONTERM; 1847268899Sbapt if (!bp->index) 1848268899Sbapt bp->index = nrules; 1849234949Sbapt if (nrules >= maxrules) 1850234949Sbapt expand_rules(); 1851234949Sbapt plhs[nrules] = bp; 1852234949Sbapt rprec[nrules] = UNDEFINED; 1853234949Sbapt rassoc[nrules] = TOKEN; 1854234949Sbapt} 1855234949Sbapt 1856234949Sbaptstatic void 1857234949Sbaptend_rule(void) 1858234949Sbapt{ 1859234949Sbapt int i; 1860234949Sbapt 1861234949Sbapt if (!last_was_action && plhs[nrules]->tag) 1862234949Sbapt { 1863234949Sbapt if (pitem[nitems - 1]) 1864234949Sbapt { 1865234949Sbapt for (i = nitems - 1; (i > 0) && pitem[i]; --i) 1866234949Sbapt continue; 1867234949Sbapt if (pitem[i + 1] == 0 || pitem[i + 1]->tag != plhs[nrules]->tag) 1868234949Sbapt default_action_warning(); 1869234949Sbapt } 1870234949Sbapt else 1871234949Sbapt { 1872234949Sbapt default_action_warning(); 1873234949Sbapt } 1874234949Sbapt } 1875234949Sbapt 1876234949Sbapt last_was_action = 0; 1877234949Sbapt if (nitems >= maxitems) 1878234949Sbapt expand_items(); 1879234949Sbapt pitem[nitems] = 0; 1880234949Sbapt ++nitems; 1881234949Sbapt ++nrules; 1882234949Sbapt} 1883234949Sbapt 1884234949Sbaptstatic void 1885234949Sbaptinsert_empty_rule(void) 1886234949Sbapt{ 1887234949Sbapt bucket *bp, **bpp; 1888234949Sbapt 1889234949Sbapt assert(cache); 1890234949Sbapt sprintf(cache, "$$%d", ++gensym); 1891234949Sbapt bp = make_bucket(cache); 1892234949Sbapt last_symbol->next = bp; 1893234949Sbapt last_symbol = bp; 1894234949Sbapt bp->tag = plhs[nrules]->tag; 1895268899Sbapt bp->class = ACTION; 1896268899Sbapt#if defined(YYBTYACC) 1897268899Sbapt bp->args = 0; 1898268899Sbapt#endif 1899234949Sbapt 1900268899Sbapt nitems = (Value_t) (nitems + 2); 1901268899Sbapt if (nitems > maxitems) 1902234949Sbapt expand_items(); 1903234949Sbapt bpp = pitem + nitems - 1; 1904234949Sbapt *bpp-- = bp; 1905234949Sbapt while ((bpp[0] = bpp[-1]) != 0) 1906234949Sbapt --bpp; 1907234949Sbapt 1908234949Sbapt if (++nrules >= maxrules) 1909234949Sbapt expand_rules(); 1910234949Sbapt plhs[nrules] = plhs[nrules - 1]; 1911234949Sbapt plhs[nrules - 1] = bp; 1912234949Sbapt rprec[nrules] = rprec[nrules - 1]; 1913234949Sbapt rprec[nrules - 1] = 0; 1914234949Sbapt rassoc[nrules] = rassoc[nrules - 1]; 1915234949Sbapt rassoc[nrules - 1] = TOKEN; 1916234949Sbapt} 1917234949Sbapt 1918268899Sbapt#if defined(YYBTYACC) 1919268899Sbaptstatic char * 1920268899Sbaptinsert_arg_rule(char *arg, char *tag) 1921268899Sbapt{ 1922268899Sbapt int line_number = rescan_lineno; 1923268899Sbapt char *code = compile_arg(&arg, tag); 1924268899Sbapt int rule = lookup_arg_cache(code); 1925268899Sbapt FILE *f = action_file; 1926268899Sbapt 1927268899Sbapt if (rule < 0) 1928268899Sbapt { 1929268899Sbapt rule = nrules; 1930268899Sbapt insert_arg_cache(code, rule); 1931268899Sbapt fprintf(f, "case %d:\n", rule - 2); 1932268899Sbapt if (!lflag) 1933268899Sbapt fprintf(f, line_format, line_number, input_file_name); 1934268899Sbapt fprintf(f, "%s;\n", code); 1935268899Sbapt fprintf(f, "break;\n"); 1936268899Sbapt insert_empty_rule(); 1937268899Sbapt plhs[rule]->tag = tag; 1938268899Sbapt plhs[rule]->class = ARGUMENT; 1939268899Sbapt } 1940268899Sbapt else 1941268899Sbapt { 1942268899Sbapt if (++nitems > maxitems) 1943268899Sbapt expand_items(); 1944268899Sbapt pitem[nitems - 1] = plhs[rule]; 1945268899Sbapt free(code); 1946268899Sbapt } 1947268899Sbapt return arg + 1; 1948268899Sbapt} 1949268899Sbapt#endif 1950268899Sbapt 1951234949Sbaptstatic void 1952234949Sbaptadd_symbol(void) 1953234949Sbapt{ 1954234949Sbapt int c; 1955234949Sbapt bucket *bp; 1956234949Sbapt int s_lineno = lineno; 1957268899Sbapt#if defined(YYBTYACC) 1958268899Sbapt char *args = NULL; 1959268899Sbapt int argslen = 0; 1960268899Sbapt#endif 1961234949Sbapt 1962234949Sbapt c = *cptr; 1963234949Sbapt if (c == '\'' || c == '"') 1964234949Sbapt bp = get_literal(); 1965234949Sbapt else 1966234949Sbapt bp = get_name(); 1967234949Sbapt 1968234949Sbapt c = nextc(); 1969268899Sbapt rescan_lineno = lineno; /* line# for possible inherited args rescan */ 1970268899Sbapt#if defined(YYBTYACC) 1971268899Sbapt if (c == L_PAREN) 1972268899Sbapt { 1973268899Sbapt ++cptr; 1974268899Sbapt args = copy_args(&argslen); 1975268899Sbapt NO_SPACE(args); 1976268899Sbapt c = nextc(); 1977268899Sbapt } 1978268899Sbapt#endif 1979234949Sbapt if (c == ':') 1980234949Sbapt { 1981234949Sbapt end_rule(); 1982234949Sbapt start_rule(bp, s_lineno); 1983268899Sbapt#if defined(YYBTYACC) 1984268899Sbapt parse_arginfo(bp, args, argslen); 1985268899Sbapt#endif 1986234949Sbapt ++cptr; 1987234949Sbapt return; 1988234949Sbapt } 1989234949Sbapt 1990234949Sbapt if (last_was_action) 1991234949Sbapt insert_empty_rule(); 1992234949Sbapt last_was_action = 0; 1993234949Sbapt 1994268899Sbapt#if defined(YYBTYACC) 1995268899Sbapt if (bp->args < 0) 1996268899Sbapt bp->args = argslen; 1997268899Sbapt if (argslen == 0 && bp->args > 0 && pitem[nitems - 1] == NULL) 1998268899Sbapt { 1999268899Sbapt int i; 2000268899Sbapt if (plhs[nrules]->args != bp->args) 2001268899Sbapt wrong_number_args_warning("default ", bp->name); 2002268899Sbapt for (i = bp->args - 1; i >= 0; i--) 2003268899Sbapt if (plhs[nrules]->argtags[i] != bp->argtags[i]) 2004268899Sbapt wrong_type_for_arg_warning(i + 1, bp->name); 2005268899Sbapt } 2006268899Sbapt else if (bp->args != argslen) 2007268899Sbapt wrong_number_args_warning("", bp->name); 2008268899Sbapt if (bp->args > 0 && argslen > 0) 2009268899Sbapt { 2010268899Sbapt char *ap; 2011268899Sbapt int i; 2012268899Sbapt for (ap = args, i = 0; i < argslen; i++) 2013268899Sbapt ap = insert_arg_rule(ap, bp->argtags[i]); 2014268899Sbapt free(args); 2015268899Sbapt } 2016268899Sbapt#endif /* defined(YYBTYACC) */ 2017268899Sbapt 2018234949Sbapt if (++nitems > maxitems) 2019234949Sbapt expand_items(); 2020234949Sbapt pitem[nitems - 1] = bp; 2021234949Sbapt} 2022234949Sbapt 2023234949Sbaptstatic char * 2024234949Sbaptafter_blanks(char *s) 2025234949Sbapt{ 2026234949Sbapt while (*s != '\0' && isspace(UCH(*s))) 2027234949Sbapt ++s; 2028234949Sbapt return s; 2029234949Sbapt} 2030234949Sbapt 2031234949Sbaptstatic void 2032234949Sbaptcopy_action(void) 2033234949Sbapt{ 2034234949Sbapt int c; 2035268899Sbapt int i, j, n; 2036234949Sbapt int depth; 2037268899Sbapt#if defined(YYBTYACC) 2038268899Sbapt int trialaction = 0; 2039268899Sbapt int haveyyval = 0; 2040268899Sbapt#endif 2041234949Sbapt char *tag; 2042234949Sbapt FILE *f = action_file; 2043234949Sbapt int a_lineno = lineno; 2044234949Sbapt char *a_line = dup_line(); 2045234949Sbapt char *a_cptr = a_line + (cptr - line); 2046268899Sbapt Value_t *offsets = NULL, maxoffset; 2047268899Sbapt bucket **rhs; 2048234949Sbapt 2049234949Sbapt if (last_was_action) 2050234949Sbapt insert_empty_rule(); 2051234949Sbapt last_was_action = 1; 2052234949Sbapt 2053234949Sbapt fprintf(f, "case %d:\n", nrules - 2); 2054268899Sbapt#if defined(YYBTYACC) 2055268899Sbapt if (backtrack) 2056268899Sbapt { 2057268899Sbapt if (*cptr != L_BRAC) 2058268899Sbapt fprintf(f, " if (!yytrial)\n"); 2059268899Sbapt else 2060268899Sbapt trialaction = 1; 2061268899Sbapt } 2062268899Sbapt#endif 2063234949Sbapt if (!lflag) 2064234949Sbapt fprintf(f, line_format, lineno, input_file_name); 2065234949Sbapt if (*cptr == '=') 2066234949Sbapt ++cptr; 2067234949Sbapt 2068234949Sbapt /* avoid putting curly-braces in first column, to ease editing */ 2069234949Sbapt if (*after_blanks(cptr) == L_CURL) 2070234949Sbapt { 2071234949Sbapt putc('\t', f); 2072234949Sbapt cptr = after_blanks(cptr); 2073234949Sbapt } 2074234949Sbapt 2075268899Sbapt maxoffset = 0; 2076234949Sbapt n = 0; 2077234949Sbapt for (i = nitems - 1; pitem[i]; --i) 2078268899Sbapt { 2079234949Sbapt ++n; 2080268899Sbapt if (pitem[i]->class != ARGUMENT) 2081268899Sbapt maxoffset++; 2082268899Sbapt } 2083268899Sbapt if (maxoffset > 0) 2084268899Sbapt { 2085268899Sbapt offsets = TMALLOC(Value_t, maxoffset + 1); 2086268899Sbapt NO_SPACE(offsets); 2087268899Sbapt } 2088268899Sbapt for (j = 0, i++; i < nitems; i++) 2089268899Sbapt { 2090268899Sbapt if (pitem[i]->class != ARGUMENT) 2091268899Sbapt { 2092268899Sbapt offsets[++j] = (Value_t) (i - nitems + 1); 2093268899Sbapt } 2094268899Sbapt } 2095268899Sbapt rhs = pitem + nitems - 1; 2096234949Sbapt 2097234949Sbapt depth = 0; 2098234949Sbapt loop: 2099234949Sbapt c = *cptr; 2100234949Sbapt if (c == '$') 2101234949Sbapt { 2102234949Sbapt if (cptr[1] == '<') 2103234949Sbapt { 2104234949Sbapt int d_lineno = lineno; 2105234949Sbapt char *d_line = dup_line(); 2106234949Sbapt char *d_cptr = d_line + (cptr - line); 2107234949Sbapt 2108234949Sbapt ++cptr; 2109234949Sbapt tag = get_tag(); 2110234949Sbapt c = *cptr; 2111234949Sbapt if (c == '$') 2112234949Sbapt { 2113234949Sbapt fprintf(f, "yyval.%s", tag); 2114234949Sbapt ++cptr; 2115234949Sbapt FREE(d_line); 2116234949Sbapt goto loop; 2117234949Sbapt } 2118234949Sbapt else if (isdigit(c)) 2119234949Sbapt { 2120234949Sbapt i = get_number(); 2121268899Sbapt if (i == 0) 2122268899Sbapt fprintf(f, "yystack.l_mark[%d].%s", -n, tag); 2123268899Sbapt else if (i > maxoffset) 2124268899Sbapt { 2125234949Sbapt dollar_warning(d_lineno, i); 2126268899Sbapt fprintf(f, "yystack.l_mark[%d].%s", i - maxoffset, tag); 2127268899Sbapt } 2128268899Sbapt else if (offsets) 2129268899Sbapt fprintf(f, "yystack.l_mark[%d].%s", offsets[i], tag); 2130234949Sbapt FREE(d_line); 2131234949Sbapt goto loop; 2132234949Sbapt } 2133234949Sbapt else if (c == '-' && isdigit(UCH(cptr[1]))) 2134234949Sbapt { 2135234949Sbapt ++cptr; 2136234949Sbapt i = -get_number() - n; 2137234949Sbapt fprintf(f, "yystack.l_mark[%d].%s", i, tag); 2138234949Sbapt FREE(d_line); 2139234949Sbapt goto loop; 2140234949Sbapt } 2141268899Sbapt#if defined(YYBTYACC) 2142268899Sbapt else if (isalpha(c) || c == '_') 2143268899Sbapt { 2144268899Sbapt char *arg = scan_id(); 2145268899Sbapt for (i = plhs[nrules]->args - 1; i >= 0; i--) 2146268899Sbapt if (arg == plhs[nrules]->argnames[i]) 2147268899Sbapt break; 2148268899Sbapt if (i < 0) 2149268899Sbapt unknown_arg_warning(d_lineno, "$", arg, d_line, d_cptr); 2150268899Sbapt fprintf(f, "yystack.l_mark[%d].%s", i - plhs[nrules]->args + 2151268899Sbapt 1 - n, tag); 2152268899Sbapt FREE(d_line); 2153268899Sbapt goto loop; 2154268899Sbapt } 2155268899Sbapt#endif 2156234949Sbapt else 2157234949Sbapt dollar_error(d_lineno, d_line, d_cptr); 2158234949Sbapt } 2159234949Sbapt else if (cptr[1] == '$') 2160234949Sbapt { 2161268899Sbapt if (havetags) 2162234949Sbapt { 2163234949Sbapt tag = plhs[nrules]->tag; 2164234949Sbapt if (tag == 0) 2165234949Sbapt untyped_lhs(); 2166234949Sbapt fprintf(f, "yyval.%s", tag); 2167234949Sbapt } 2168234949Sbapt else 2169234949Sbapt fprintf(f, "yyval"); 2170234949Sbapt cptr += 2; 2171268899Sbapt#if defined(YYBTYACC) 2172268899Sbapt haveyyval = 1; 2173268899Sbapt#endif 2174234949Sbapt goto loop; 2175234949Sbapt } 2176234949Sbapt else if (isdigit(UCH(cptr[1]))) 2177234949Sbapt { 2178234949Sbapt ++cptr; 2179234949Sbapt i = get_number(); 2180268899Sbapt if (havetags) 2181234949Sbapt { 2182268899Sbapt if (i <= 0 || i > maxoffset) 2183234949Sbapt unknown_rhs(i); 2184268899Sbapt tag = rhs[offsets[i]]->tag; 2185234949Sbapt if (tag == 0) 2186268899Sbapt untyped_rhs(i, rhs[offsets[i]]->name); 2187268899Sbapt fprintf(f, "yystack.l_mark[%d].%s", offsets[i], tag); 2188234949Sbapt } 2189234949Sbapt else 2190234949Sbapt { 2191268899Sbapt if (i == 0) 2192268899Sbapt fprintf(f, "yystack.l_mark[%d]", -n); 2193268899Sbapt else if (i > maxoffset) 2194268899Sbapt { 2195234949Sbapt dollar_warning(lineno, i); 2196268899Sbapt fprintf(f, "yystack.l_mark[%d]", i - maxoffset); 2197268899Sbapt } 2198268899Sbapt else if (offsets) 2199268899Sbapt fprintf(f, "yystack.l_mark[%d]", offsets[i]); 2200234949Sbapt } 2201234949Sbapt goto loop; 2202234949Sbapt } 2203234949Sbapt else if (cptr[1] == '-') 2204234949Sbapt { 2205234949Sbapt cptr += 2; 2206234949Sbapt i = get_number(); 2207268899Sbapt if (havetags) 2208234949Sbapt unknown_rhs(-i); 2209234949Sbapt fprintf(f, "yystack.l_mark[%d]", -i - n); 2210234949Sbapt goto loop; 2211234949Sbapt } 2212268899Sbapt#if defined(YYBTYACC) 2213268899Sbapt else if (isalpha(cptr[1]) || cptr[1] == '_') 2214268899Sbapt { 2215268899Sbapt char *arg; 2216268899Sbapt ++cptr; 2217268899Sbapt arg = scan_id(); 2218268899Sbapt for (i = plhs[nrules]->args - 1; i >= 0; i--) 2219268899Sbapt if (arg == plhs[nrules]->argnames[i]) 2220268899Sbapt break; 2221268899Sbapt if (i < 0) 2222268899Sbapt unknown_arg_warning(lineno, "$", arg, line, cptr); 2223268899Sbapt tag = (i < 0 ? NULL : plhs[nrules]->argtags[i]); 2224268899Sbapt fprintf(f, "yystack.l_mark[%d]", i - plhs[nrules]->args + 1 - n); 2225268899Sbapt if (tag) 2226268899Sbapt fprintf(f, ".%s", tag); 2227268899Sbapt else if (havetags) 2228268899Sbapt untyped_arg_warning(lineno, "$", arg); 2229268899Sbapt goto loop; 2230268899Sbapt } 2231268899Sbapt#endif 2232234949Sbapt } 2233268899Sbapt#if defined(YYBTYACC) 2234268899Sbapt if (c == '@') 2235268899Sbapt { 2236268899Sbapt if (!locations) 2237268899Sbapt { 2238268899Sbapt int l_lineno = lineno; 2239268899Sbapt char *l_line = dup_line(); 2240268899Sbapt char *l_cptr = l_line + (cptr - line); 2241268899Sbapt syntax_error(l_lineno, l_line, l_cptr); 2242268899Sbapt } 2243268899Sbapt if (cptr[1] == '$') 2244268899Sbapt { 2245268899Sbapt fprintf(f, "yyloc"); 2246268899Sbapt cptr += 2; 2247268899Sbapt goto loop; 2248268899Sbapt } 2249268899Sbapt else if (isdigit(UCH(cptr[1]))) 2250268899Sbapt { 2251268899Sbapt ++cptr; 2252268899Sbapt i = get_number(); 2253268899Sbapt if (i == 0) 2254268899Sbapt fprintf(f, "yystack.p_mark[%d]", -n); 2255268899Sbapt else if (i > maxoffset) 2256268899Sbapt { 2257268899Sbapt at_warning(lineno, i); 2258268899Sbapt fprintf(f, "yystack.p_mark[%d]", i - maxoffset); 2259268899Sbapt } 2260268899Sbapt else if (offsets) 2261268899Sbapt fprintf(f, "yystack.p_mark[%d]", offsets[i]); 2262268899Sbapt goto loop; 2263268899Sbapt } 2264268899Sbapt } 2265268899Sbapt#endif 2266234949Sbapt if (isalpha(c) || c == '_' || c == '$') 2267234949Sbapt { 2268234949Sbapt do 2269234949Sbapt { 2270234949Sbapt putc(c, f); 2271234949Sbapt c = *++cptr; 2272234949Sbapt } 2273234949Sbapt while (isalnum(c) || c == '_' || c == '$'); 2274234949Sbapt goto loop; 2275234949Sbapt } 2276268899Sbapt ++cptr; 2277268899Sbapt#if defined(YYBTYACC) 2278268899Sbapt if (backtrack) 2279268899Sbapt { 2280268899Sbapt if (trialaction && c == L_BRAC && depth == 0) 2281268899Sbapt { 2282268899Sbapt ++depth; 2283268899Sbapt putc(L_CURL, f); 2284268899Sbapt goto loop; 2285268899Sbapt } 2286268899Sbapt if (trialaction && c == R_BRAC && depth == 1) 2287268899Sbapt { 2288268899Sbapt --depth; 2289268899Sbapt putc(R_CURL, f); 2290268899Sbapt c = nextc(); 2291268899Sbapt if (c == L_BRAC && !haveyyval) 2292268899Sbapt { 2293268899Sbapt goto loop; 2294268899Sbapt } 2295268899Sbapt if (c == L_CURL && !haveyyval) 2296268899Sbapt { 2297268899Sbapt fprintf(f, " if (!yytrial)\n"); 2298268899Sbapt if (!lflag) 2299268899Sbapt fprintf(f, line_format, lineno, input_file_name); 2300268899Sbapt trialaction = 0; 2301268899Sbapt goto loop; 2302268899Sbapt } 2303268899Sbapt fprintf(f, "\nbreak;\n"); 2304268899Sbapt FREE(a_line); 2305268899Sbapt if (maxoffset > 0) 2306268899Sbapt FREE(offsets); 2307268899Sbapt return; 2308268899Sbapt } 2309268899Sbapt } 2310268899Sbapt#endif 2311234949Sbapt putc(c, f); 2312234949Sbapt switch (c) 2313234949Sbapt { 2314234949Sbapt case '\n': 2315234949Sbapt get_line(); 2316234949Sbapt if (line) 2317234949Sbapt goto loop; 2318234949Sbapt unterminated_action(a_lineno, a_line, a_cptr); 2319234949Sbapt 2320234949Sbapt case ';': 2321234949Sbapt if (depth > 0) 2322234949Sbapt goto loop; 2323234949Sbapt fprintf(f, "\nbreak;\n"); 2324234949Sbapt free(a_line); 2325268899Sbapt if (maxoffset > 0) 2326268899Sbapt FREE(offsets); 2327234949Sbapt return; 2328234949Sbapt 2329268899Sbapt#if defined(YYBTYACC) 2330268899Sbapt case L_BRAC: 2331268899Sbapt if (backtrack) 2332268899Sbapt ++depth; 2333268899Sbapt goto loop; 2334268899Sbapt 2335268899Sbapt case R_BRAC: 2336268899Sbapt if (backtrack) 2337268899Sbapt --depth; 2338268899Sbapt goto loop; 2339268899Sbapt#endif 2340268899Sbapt 2341234949Sbapt case L_CURL: 2342234949Sbapt ++depth; 2343234949Sbapt goto loop; 2344234949Sbapt 2345234949Sbapt case R_CURL: 2346234949Sbapt if (--depth > 0) 2347234949Sbapt goto loop; 2348268899Sbapt#if defined(YYBTYACC) 2349268899Sbapt if (backtrack) 2350268899Sbapt { 2351268899Sbapt c = nextc(); 2352268899Sbapt if (c == L_BRAC && !haveyyval) 2353268899Sbapt { 2354268899Sbapt trialaction = 1; 2355268899Sbapt goto loop; 2356268899Sbapt } 2357268899Sbapt if (c == L_CURL && !haveyyval) 2358268899Sbapt { 2359268899Sbapt fprintf(f, " if (!yytrial)\n"); 2360268899Sbapt if (!lflag) 2361268899Sbapt fprintf(f, line_format, lineno, input_file_name); 2362268899Sbapt goto loop; 2363268899Sbapt } 2364268899Sbapt } 2365268899Sbapt#endif 2366234949Sbapt fprintf(f, "\nbreak;\n"); 2367234949Sbapt free(a_line); 2368268899Sbapt if (maxoffset > 0) 2369268899Sbapt FREE(offsets); 2370234949Sbapt return; 2371234949Sbapt 2372234949Sbapt case '\'': 2373234949Sbapt case '"': 2374234949Sbapt { 2375268899Sbapt char *s = copy_string(c); 2376268899Sbapt fputs(s, f); 2377268899Sbapt free(s); 2378268899Sbapt } 2379268899Sbapt goto loop; 2380234949Sbapt 2381268899Sbapt case '/': 2382268899Sbapt { 2383268899Sbapt char *s = copy_comment(); 2384268899Sbapt fputs(s, f); 2385268899Sbapt free(s); 2386268899Sbapt } 2387268899Sbapt goto loop; 2388268899Sbapt 2389268899Sbapt default: 2390268899Sbapt goto loop; 2391268899Sbapt } 2392268899Sbapt} 2393268899Sbapt 2394268899Sbapt#if defined(YYBTYACC) 2395268899Sbaptstatic void 2396268899Sbaptcopy_destructor(void) 2397268899Sbapt{ 2398268899Sbapt int c; 2399268899Sbapt int depth; 2400268899Sbapt char *tag; 2401268899Sbapt bucket *bp; 2402268899Sbapt struct mstring *destructor_text = msnew(); 2403268899Sbapt char *code_text; 2404268899Sbapt int a_lineno; 2405268899Sbapt char *a_line; 2406268899Sbapt char *a_cptr; 2407268899Sbapt 2408268899Sbapt if (!lflag) 2409268899Sbapt msprintf(destructor_text, line_format, lineno, input_file_name); 2410268899Sbapt 2411268899Sbapt cptr = after_blanks(cptr); 2412268899Sbapt if (*cptr == L_CURL) 2413268899Sbapt /* avoid putting curly-braces in first column, to ease editing */ 2414268899Sbapt mputc(destructor_text, '\t'); 2415268899Sbapt else 2416268899Sbapt syntax_error(lineno, line, cptr); 2417268899Sbapt 2418268899Sbapt a_lineno = lineno; 2419268899Sbapt a_line = dup_line(); 2420268899Sbapt a_cptr = a_line + (cptr - line); 2421268899Sbapt 2422268899Sbapt depth = 0; 2423268899Sbapt loop: 2424268899Sbapt c = *cptr; 2425268899Sbapt if (c == '$') 2426268899Sbapt { 2427268899Sbapt if (cptr[1] == '<') 2428268899Sbapt { 2429268899Sbapt int d_lineno = lineno; 2430268899Sbapt char *d_line = dup_line(); 2431268899Sbapt char *d_cptr = d_line + (cptr - line); 2432268899Sbapt 2433268899Sbapt ++cptr; 2434268899Sbapt tag = get_tag(); 2435268899Sbapt c = *cptr; 2436268899Sbapt if (c == '$') 2437234949Sbapt { 2438268899Sbapt msprintf(destructor_text, "(*val).%s", tag); 2439268899Sbapt ++cptr; 2440268899Sbapt FREE(d_line); 2441268899Sbapt goto loop; 2442268899Sbapt } 2443268899Sbapt else 2444268899Sbapt dollar_error(d_lineno, d_line, d_cptr); 2445268899Sbapt } 2446268899Sbapt else if (cptr[1] == '$') 2447268899Sbapt { 2448268899Sbapt /* process '$$' later; replacement is context dependent */ 2449268899Sbapt msprintf(destructor_text, "$$"); 2450268899Sbapt cptr += 2; 2451268899Sbapt goto loop; 2452268899Sbapt } 2453268899Sbapt } 2454268899Sbapt if (c == '@' && cptr[1] == '$') 2455268899Sbapt { 2456268899Sbapt if (!locations) 2457268899Sbapt { 2458268899Sbapt int l_lineno = lineno; 2459268899Sbapt char *l_line = dup_line(); 2460268899Sbapt char *l_cptr = l_line + (cptr - line); 2461268899Sbapt syntax_error(l_lineno, l_line, l_cptr); 2462268899Sbapt } 2463268899Sbapt msprintf(destructor_text, "(*loc)"); 2464268899Sbapt cptr += 2; 2465268899Sbapt goto loop; 2466268899Sbapt } 2467268899Sbapt if (isalpha(c) || c == '_' || c == '$') 2468268899Sbapt { 2469268899Sbapt do 2470268899Sbapt { 2471268899Sbapt mputc(destructor_text, c); 2472268899Sbapt c = *++cptr; 2473268899Sbapt } 2474268899Sbapt while (isalnum(c) || c == '_' || c == '$'); 2475268899Sbapt goto loop; 2476268899Sbapt } 2477268899Sbapt ++cptr; 2478268899Sbapt mputc(destructor_text, c); 2479268899Sbapt switch (c) 2480268899Sbapt { 2481268899Sbapt case '\n': 2482268899Sbapt get_line(); 2483268899Sbapt if (line) 2484268899Sbapt goto loop; 2485268899Sbapt unterminated_action(a_lineno, a_line, a_cptr); 2486268899Sbapt 2487268899Sbapt case L_CURL: 2488268899Sbapt ++depth; 2489268899Sbapt goto loop; 2490268899Sbapt 2491268899Sbapt case R_CURL: 2492268899Sbapt if (--depth > 0) 2493268899Sbapt goto loop; 2494268899Sbapt goto process_symbols; 2495268899Sbapt 2496268899Sbapt case '\'': 2497268899Sbapt case '"': 2498268899Sbapt { 2499268899Sbapt char *s = copy_string(c); 2500268899Sbapt msprintf(destructor_text, "%s", s); 2501268899Sbapt free(s); 2502268899Sbapt } 2503268899Sbapt goto loop; 2504268899Sbapt 2505268899Sbapt case '/': 2506268899Sbapt { 2507268899Sbapt char *s = copy_comment(); 2508268899Sbapt msprintf(destructor_text, "%s", s); 2509268899Sbapt free(s); 2510268899Sbapt } 2511268899Sbapt goto loop; 2512268899Sbapt 2513268899Sbapt default: 2514268899Sbapt goto loop; 2515268899Sbapt } 2516268899Sbapt process_symbols: 2517268899Sbapt code_text = msdone(destructor_text); 2518268899Sbapt for (;;) 2519268899Sbapt { 2520268899Sbapt c = nextc(); 2521268899Sbapt if (c == EOF) 2522268899Sbapt unexpected_EOF(); 2523268899Sbapt if (c == '<') 2524268899Sbapt { 2525268899Sbapt if (cptr[1] == '>') 2526268899Sbapt { /* "no semantic type" default destructor */ 2527268899Sbapt cptr += 2; 2528268899Sbapt if ((bp = default_destructor[UNTYPED_DEFAULT]) == NULL) 2529234949Sbapt { 2530268899Sbapt static char untyped_default[] = "<>"; 2531268899Sbapt bp = make_bucket("untyped default"); 2532268899Sbapt bp->tag = untyped_default; 2533268899Sbapt default_destructor[UNTYPED_DEFAULT] = bp; 2534234949Sbapt } 2535268899Sbapt if (bp->destructor != NULL) 2536268899Sbapt destructor_redeclared_warning(a_lineno, a_line, a_cptr); 2537268899Sbapt else 2538268899Sbapt /* replace "$$" with "(*val)" in destructor code */ 2539268899Sbapt bp->destructor = process_destructor_XX(code_text, NULL); 2540268899Sbapt } 2541268899Sbapt else if (cptr[1] == '*' && cptr[2] == '>') 2542268899Sbapt { /* "no per-symbol or per-type" default destructor */ 2543268899Sbapt cptr += 3; 2544268899Sbapt if ((bp = default_destructor[TYPED_DEFAULT]) == NULL) 2545234949Sbapt { 2546268899Sbapt static char typed_default[] = "<*>"; 2547268899Sbapt bp = make_bucket("typed default"); 2548268899Sbapt bp->tag = typed_default; 2549268899Sbapt default_destructor[TYPED_DEFAULT] = bp; 2550234949Sbapt } 2551268899Sbapt if (bp->destructor != NULL) 2552268899Sbapt destructor_redeclared_warning(a_lineno, a_line, a_cptr); 2553268899Sbapt else 2554268899Sbapt { 2555268899Sbapt /* postpone re-processing destructor $$s until end of grammar spec */ 2556268899Sbapt bp->destructor = TMALLOC(char, strlen(code_text) + 1); 2557268899Sbapt NO_SPACE(bp->destructor); 2558268899Sbapt strcpy(bp->destructor, code_text); 2559268899Sbapt } 2560234949Sbapt } 2561268899Sbapt else 2562268899Sbapt { /* "semantic type" default destructor */ 2563268899Sbapt tag = get_tag(); 2564268899Sbapt bp = lookup_type_destructor(tag); 2565268899Sbapt if (bp->destructor != NULL) 2566268899Sbapt destructor_redeclared_warning(a_lineno, a_line, a_cptr); 2567268899Sbapt else 2568268899Sbapt /* replace "$$" with "(*val).tag" in destructor code */ 2569268899Sbapt bp->destructor = process_destructor_XX(code_text, tag); 2570268899Sbapt } 2571234949Sbapt } 2572268899Sbapt else if (isalpha(c) || c == '_' || c == '.' || c == '$') 2573268899Sbapt { /* "symbol" destructor */ 2574268899Sbapt bp = get_name(); 2575268899Sbapt if (bp->destructor != NULL) 2576268899Sbapt destructor_redeclared_warning(a_lineno, a_line, a_cptr); 2577268899Sbapt else 2578268899Sbapt { 2579268899Sbapt /* postpone re-processing destructor $$s until end of grammar spec */ 2580268899Sbapt bp->destructor = TMALLOC(char, strlen(code_text) + 1); 2581268899Sbapt NO_SPACE(bp->destructor); 2582268899Sbapt strcpy(bp->destructor, code_text); 2583268899Sbapt } 2584268899Sbapt } 2585268899Sbapt else 2586268899Sbapt break; 2587268899Sbapt } 2588268899Sbapt free(a_line); 2589268899Sbapt free(code_text); 2590268899Sbapt} 2591234949Sbapt 2592268899Sbaptstatic char * 2593268899Sbaptprocess_destructor_XX(char *code, char *tag) 2594268899Sbapt{ 2595268899Sbapt int c; 2596268899Sbapt int quote; 2597268899Sbapt int depth; 2598268899Sbapt struct mstring *new_code = msnew(); 2599268899Sbapt char *codeptr = code; 2600268899Sbapt 2601268899Sbapt depth = 0; 2602268899Sbapt loop: /* step thru code */ 2603268899Sbapt c = *codeptr; 2604268899Sbapt if (c == '$' && codeptr[1] == '$') 2605268899Sbapt { 2606268899Sbapt codeptr += 2; 2607268899Sbapt if (tag == NULL) 2608268899Sbapt msprintf(new_code, "(*val)"); 2609268899Sbapt else 2610268899Sbapt msprintf(new_code, "(*val).%s", tag); 2611268899Sbapt goto loop; 2612268899Sbapt } 2613268899Sbapt if (isalpha(c) || c == '_' || c == '$') 2614268899Sbapt { 2615268899Sbapt do 2616234949Sbapt { 2617268899Sbapt mputc(new_code, c); 2618268899Sbapt c = *++codeptr; 2619268899Sbapt } 2620268899Sbapt while (isalnum(c) || c == '_' || c == '$'); 2621268899Sbapt goto loop; 2622268899Sbapt } 2623268899Sbapt ++codeptr; 2624268899Sbapt mputc(new_code, c); 2625268899Sbapt switch (c) 2626268899Sbapt { 2627268899Sbapt case L_CURL: 2628268899Sbapt ++depth; 2629268899Sbapt goto loop; 2630268899Sbapt 2631268899Sbapt case R_CURL: 2632268899Sbapt if (--depth > 0) 2633268899Sbapt goto loop; 2634268899Sbapt return msdone(new_code); 2635268899Sbapt 2636268899Sbapt case '\'': 2637268899Sbapt case '"': 2638268899Sbapt quote = c; 2639268899Sbapt for (;;) 2640268899Sbapt { 2641268899Sbapt c = *codeptr++; 2642268899Sbapt mputc(new_code, c); 2643268899Sbapt if (c == quote) 2644268899Sbapt goto loop; 2645268899Sbapt if (c == '\\') 2646234949Sbapt { 2647268899Sbapt c = *codeptr++; 2648268899Sbapt mputc(new_code, c); 2649234949Sbapt } 2650234949Sbapt } 2651268899Sbapt 2652268899Sbapt case '/': 2653268899Sbapt c = *codeptr; 2654234949Sbapt if (c == '*') 2655234949Sbapt { 2656268899Sbapt mputc(new_code, c); 2657268899Sbapt ++codeptr; 2658234949Sbapt for (;;) 2659234949Sbapt { 2660268899Sbapt c = *codeptr++; 2661268899Sbapt mputc(new_code, c); 2662268899Sbapt if (c == '*' && *codeptr == '/') 2663234949Sbapt { 2664268899Sbapt mputc(new_code, '/'); 2665268899Sbapt ++codeptr; 2666234949Sbapt goto loop; 2667234949Sbapt } 2668234949Sbapt } 2669234949Sbapt } 2670234949Sbapt goto loop; 2671234949Sbapt 2672234949Sbapt default: 2673234949Sbapt goto loop; 2674234949Sbapt } 2675234949Sbapt} 2676268899Sbapt#endif /* defined(YYBTYACC) */ 2677234949Sbapt 2678234949Sbaptstatic int 2679234949Sbaptmark_symbol(void) 2680234949Sbapt{ 2681234949Sbapt int c; 2682240517Sbapt bucket *bp = NULL; 2683234949Sbapt 2684234949Sbapt c = cptr[1]; 2685234949Sbapt if (c == '%' || c == '\\') 2686234949Sbapt { 2687234949Sbapt cptr += 2; 2688234949Sbapt return (1); 2689234949Sbapt } 2690234949Sbapt 2691234949Sbapt if (c == '=') 2692234949Sbapt cptr += 2; 2693234949Sbapt else if ((c == 'p' || c == 'P') && 2694234949Sbapt ((c = cptr[2]) == 'r' || c == 'R') && 2695234949Sbapt ((c = cptr[3]) == 'e' || c == 'E') && 2696234949Sbapt ((c = cptr[4]) == 'c' || c == 'C') && 2697234949Sbapt ((c = cptr[5], !IS_IDENT(c)))) 2698234949Sbapt cptr += 5; 2699234949Sbapt else 2700234949Sbapt syntax_error(lineno, line, cptr); 2701234949Sbapt 2702234949Sbapt c = nextc(); 2703234949Sbapt if (isalpha(c) || c == '_' || c == '.' || c == '$') 2704234949Sbapt bp = get_name(); 2705234949Sbapt else if (c == '\'' || c == '"') 2706234949Sbapt bp = get_literal(); 2707234949Sbapt else 2708234949Sbapt { 2709234949Sbapt syntax_error(lineno, line, cptr); 2710234949Sbapt } 2711234949Sbapt 2712234949Sbapt if (rprec[nrules] != UNDEFINED && bp->prec != rprec[nrules]) 2713234949Sbapt prec_redeclared(); 2714234949Sbapt 2715234949Sbapt rprec[nrules] = bp->prec; 2716234949Sbapt rassoc[nrules] = bp->assoc; 2717234949Sbapt return (0); 2718234949Sbapt} 2719234949Sbapt 2720234949Sbaptstatic void 2721234949Sbaptread_grammar(void) 2722234949Sbapt{ 2723234949Sbapt int c; 2724234949Sbapt 2725234949Sbapt initialize_grammar(); 2726234949Sbapt advance_to_start(); 2727234949Sbapt 2728234949Sbapt for (;;) 2729234949Sbapt { 2730234949Sbapt c = nextc(); 2731234949Sbapt if (c == EOF) 2732234949Sbapt break; 2733234949Sbapt if (isalpha(c) 2734234949Sbapt || c == '_' 2735234949Sbapt || c == '.' 2736234949Sbapt || c == '$' 2737234949Sbapt || c == '\'' 2738234949Sbapt || c == '"') 2739234949Sbapt add_symbol(); 2740268899Sbapt#if defined(YYBTYACC) 2741268899Sbapt else if (c == L_CURL || c == '=' || (backtrack && c == L_BRAC)) 2742268899Sbapt#else 2743234949Sbapt else if (c == L_CURL || c == '=') 2744268899Sbapt#endif 2745234949Sbapt copy_action(); 2746234949Sbapt else if (c == '|') 2747234949Sbapt { 2748234949Sbapt end_rule(); 2749234949Sbapt start_rule(plhs[nrules - 1], 0); 2750234949Sbapt ++cptr; 2751234949Sbapt } 2752234949Sbapt else if (c == '%') 2753234949Sbapt { 2754234949Sbapt if (mark_symbol()) 2755234949Sbapt break; 2756234949Sbapt } 2757234949Sbapt else 2758234949Sbapt syntax_error(lineno, line, cptr); 2759234949Sbapt } 2760234949Sbapt end_rule(); 2761268899Sbapt#if defined(YYBTYACC) 2762268899Sbapt if (goal->args > 0) 2763268899Sbapt start_requires_args(goal->name); 2764268899Sbapt#endif 2765234949Sbapt} 2766234949Sbapt 2767234949Sbaptstatic void 2768234949Sbaptfree_tags(void) 2769234949Sbapt{ 2770234949Sbapt int i; 2771234949Sbapt 2772234949Sbapt if (tag_table == 0) 2773234949Sbapt return; 2774234949Sbapt 2775234949Sbapt for (i = 0; i < ntags; ++i) 2776234949Sbapt { 2777234949Sbapt assert(tag_table[i]); 2778234949Sbapt FREE(tag_table[i]); 2779234949Sbapt } 2780234949Sbapt FREE(tag_table); 2781234949Sbapt} 2782234949Sbapt 2783234949Sbaptstatic void 2784234949Sbaptpack_names(void) 2785234949Sbapt{ 2786234949Sbapt bucket *bp; 2787234949Sbapt char *p, *s, *t; 2788234949Sbapt 2789234949Sbapt name_pool_size = 13; /* 13 == sizeof("$end") + sizeof("$accept") */ 2790234949Sbapt for (bp = first_symbol; bp; bp = bp->next) 2791234949Sbapt name_pool_size += strlen(bp->name) + 1; 2792234949Sbapt 2793240517Sbapt name_pool = TMALLOC(char, name_pool_size); 2794234949Sbapt NO_SPACE(name_pool); 2795234949Sbapt 2796234949Sbapt strcpy(name_pool, "$accept"); 2797234949Sbapt strcpy(name_pool + 8, "$end"); 2798234949Sbapt t = name_pool + 13; 2799234949Sbapt for (bp = first_symbol; bp; bp = bp->next) 2800234949Sbapt { 2801234949Sbapt p = t; 2802234949Sbapt s = bp->name; 2803234949Sbapt while ((*t++ = *s++) != 0) 2804234949Sbapt continue; 2805234949Sbapt FREE(bp->name); 2806234949Sbapt bp->name = p; 2807234949Sbapt } 2808234949Sbapt} 2809234949Sbapt 2810234949Sbaptstatic void 2811234949Sbaptcheck_symbols(void) 2812234949Sbapt{ 2813234949Sbapt bucket *bp; 2814234949Sbapt 2815234949Sbapt if (goal->class == UNKNOWN) 2816234949Sbapt undefined_goal(goal->name); 2817234949Sbapt 2818234949Sbapt for (bp = first_symbol; bp; bp = bp->next) 2819234949Sbapt { 2820234949Sbapt if (bp->class == UNKNOWN) 2821234949Sbapt { 2822234949Sbapt undefined_symbol_warning(bp->name); 2823234949Sbapt bp->class = TERM; 2824234949Sbapt } 2825234949Sbapt } 2826234949Sbapt} 2827234949Sbapt 2828234949Sbaptstatic void 2829234949Sbaptprotect_string(char *src, char **des) 2830234949Sbapt{ 2831234949Sbapt unsigned len; 2832234949Sbapt char *s; 2833234949Sbapt char *d; 2834234949Sbapt 2835234949Sbapt *des = src; 2836234949Sbapt if (src) 2837234949Sbapt { 2838234949Sbapt len = 1; 2839234949Sbapt s = src; 2840234949Sbapt while (*s) 2841234949Sbapt { 2842234949Sbapt if ('\\' == *s || '"' == *s) 2843234949Sbapt len++; 2844234949Sbapt s++; 2845234949Sbapt len++; 2846234949Sbapt } 2847234949Sbapt 2848240517Sbapt *des = d = TMALLOC(char, len); 2849234949Sbapt NO_SPACE(d); 2850234949Sbapt 2851234949Sbapt s = src; 2852234949Sbapt while (*s) 2853234949Sbapt { 2854234949Sbapt if ('\\' == *s || '"' == *s) 2855234949Sbapt *d++ = '\\'; 2856234949Sbapt *d++ = *s++; 2857234949Sbapt } 2858234949Sbapt *d = '\0'; 2859234949Sbapt } 2860234949Sbapt} 2861234949Sbapt 2862234949Sbaptstatic void 2863234949Sbaptpack_symbols(void) 2864234949Sbapt{ 2865234949Sbapt bucket *bp; 2866234949Sbapt bucket **v; 2867234949Sbapt Value_t i, j, k, n; 2868268899Sbapt#if defined(YYBTYACC) 2869268899Sbapt Value_t max_tok_pval; 2870268899Sbapt#endif 2871234949Sbapt 2872234949Sbapt nsyms = 2; 2873234949Sbapt ntokens = 1; 2874234949Sbapt for (bp = first_symbol; bp; bp = bp->next) 2875234949Sbapt { 2876234949Sbapt ++nsyms; 2877234949Sbapt if (bp->class == TERM) 2878234949Sbapt ++ntokens; 2879234949Sbapt } 2880234949Sbapt start_symbol = (Value_t) ntokens; 2881268899Sbapt nvars = (Value_t) (nsyms - ntokens); 2882234949Sbapt 2883240517Sbapt symbol_name = TMALLOC(char *, nsyms); 2884234949Sbapt NO_SPACE(symbol_name); 2885234949Sbapt 2886240517Sbapt symbol_value = TMALLOC(Value_t, nsyms); 2887234949Sbapt NO_SPACE(symbol_value); 2888234949Sbapt 2889268899Sbapt symbol_prec = TMALLOC(Value_t, nsyms); 2890234949Sbapt NO_SPACE(symbol_prec); 2891234949Sbapt 2892240517Sbapt symbol_assoc = TMALLOC(char, nsyms); 2893234949Sbapt NO_SPACE(symbol_assoc); 2894234949Sbapt 2895268899Sbapt#if defined(YYBTYACC) 2896268899Sbapt symbol_pval = TMALLOC(Value_t, nsyms); 2897268899Sbapt NO_SPACE(symbol_pval); 2898268899Sbapt 2899268899Sbapt if (destructor) 2900268899Sbapt { 2901268899Sbapt symbol_destructor = CALLOC(sizeof(char *), nsyms); 2902268899Sbapt NO_SPACE(symbol_destructor); 2903268899Sbapt 2904268899Sbapt symbol_type_tag = CALLOC(sizeof(char *), nsyms); 2905268899Sbapt NO_SPACE(symbol_type_tag); 2906268899Sbapt } 2907268899Sbapt#endif 2908268899Sbapt 2909240517Sbapt v = TMALLOC(bucket *, nsyms); 2910234949Sbapt NO_SPACE(v); 2911234949Sbapt 2912234949Sbapt v[0] = 0; 2913234949Sbapt v[start_symbol] = 0; 2914234949Sbapt 2915234949Sbapt i = 1; 2916234949Sbapt j = (Value_t) (start_symbol + 1); 2917234949Sbapt for (bp = first_symbol; bp; bp = bp->next) 2918234949Sbapt { 2919234949Sbapt if (bp->class == TERM) 2920234949Sbapt v[i++] = bp; 2921234949Sbapt else 2922234949Sbapt v[j++] = bp; 2923234949Sbapt } 2924234949Sbapt assert(i == ntokens && j == nsyms); 2925234949Sbapt 2926234949Sbapt for (i = 1; i < ntokens; ++i) 2927234949Sbapt v[i]->index = i; 2928234949Sbapt 2929234949Sbapt goal->index = (Index_t) (start_symbol + 1); 2930234949Sbapt k = (Value_t) (start_symbol + 2); 2931234949Sbapt while (++i < nsyms) 2932234949Sbapt if (v[i] != goal) 2933234949Sbapt { 2934234949Sbapt v[i]->index = k; 2935234949Sbapt ++k; 2936234949Sbapt } 2937234949Sbapt 2938234949Sbapt goal->value = 0; 2939234949Sbapt k = 1; 2940234949Sbapt for (i = (Value_t) (start_symbol + 1); i < nsyms; ++i) 2941234949Sbapt { 2942234949Sbapt if (v[i] != goal) 2943234949Sbapt { 2944234949Sbapt v[i]->value = k; 2945234949Sbapt ++k; 2946234949Sbapt } 2947234949Sbapt } 2948234949Sbapt 2949234949Sbapt k = 0; 2950234949Sbapt for (i = 1; i < ntokens; ++i) 2951234949Sbapt { 2952234949Sbapt n = v[i]->value; 2953234949Sbapt if (n > 256) 2954234949Sbapt { 2955234949Sbapt for (j = k++; j > 0 && symbol_value[j - 1] > n; --j) 2956234949Sbapt symbol_value[j] = symbol_value[j - 1]; 2957234949Sbapt symbol_value[j] = n; 2958234949Sbapt } 2959234949Sbapt } 2960234949Sbapt 2961234949Sbapt assert(v[1] != 0); 2962234949Sbapt 2963234949Sbapt if (v[1]->value == UNDEFINED) 2964234949Sbapt v[1]->value = 256; 2965234949Sbapt 2966234949Sbapt j = 0; 2967234949Sbapt n = 257; 2968234949Sbapt for (i = 2; i < ntokens; ++i) 2969234949Sbapt { 2970234949Sbapt if (v[i]->value == UNDEFINED) 2971234949Sbapt { 2972234949Sbapt while (j < k && n == symbol_value[j]) 2973234949Sbapt { 2974234949Sbapt while (++j < k && n == symbol_value[j]) 2975234949Sbapt continue; 2976234949Sbapt ++n; 2977234949Sbapt } 2978234949Sbapt v[i]->value = n; 2979234949Sbapt ++n; 2980234949Sbapt } 2981234949Sbapt } 2982234949Sbapt 2983234949Sbapt symbol_name[0] = name_pool + 8; 2984234949Sbapt symbol_value[0] = 0; 2985234949Sbapt symbol_prec[0] = 0; 2986234949Sbapt symbol_assoc[0] = TOKEN; 2987268899Sbapt#if defined(YYBTYACC) 2988268899Sbapt symbol_pval[0] = 0; 2989268899Sbapt max_tok_pval = 0; 2990268899Sbapt#endif 2991234949Sbapt for (i = 1; i < ntokens; ++i) 2992234949Sbapt { 2993234949Sbapt symbol_name[i] = v[i]->name; 2994234949Sbapt symbol_value[i] = v[i]->value; 2995234949Sbapt symbol_prec[i] = v[i]->prec; 2996234949Sbapt symbol_assoc[i] = v[i]->assoc; 2997268899Sbapt#if defined(YYBTYACC) 2998268899Sbapt symbol_pval[i] = v[i]->value; 2999268899Sbapt if (symbol_pval[i] > max_tok_pval) 3000268899Sbapt max_tok_pval = symbol_pval[i]; 3001268899Sbapt if (destructor) 3002268899Sbapt { 3003268899Sbapt symbol_destructor[i] = v[i]->destructor; 3004268899Sbapt symbol_type_tag[i] = v[i]->tag; 3005268899Sbapt } 3006268899Sbapt#endif 3007234949Sbapt } 3008234949Sbapt symbol_name[start_symbol] = name_pool; 3009234949Sbapt symbol_value[start_symbol] = -1; 3010234949Sbapt symbol_prec[start_symbol] = 0; 3011234949Sbapt symbol_assoc[start_symbol] = TOKEN; 3012268899Sbapt#if defined(YYBTYACC) 3013268899Sbapt symbol_pval[start_symbol] = (Value_t) (max_tok_pval + 1); 3014268899Sbapt#endif 3015234949Sbapt for (++i; i < nsyms; ++i) 3016234949Sbapt { 3017234949Sbapt k = v[i]->index; 3018234949Sbapt symbol_name[k] = v[i]->name; 3019234949Sbapt symbol_value[k] = v[i]->value; 3020234949Sbapt symbol_prec[k] = v[i]->prec; 3021234949Sbapt symbol_assoc[k] = v[i]->assoc; 3022268899Sbapt#if defined(YYBTYACC) 3023268899Sbapt symbol_pval[k] = (Value_t) ((max_tok_pval + 1) + v[i]->value + 1); 3024268899Sbapt if (destructor) 3025268899Sbapt { 3026268899Sbapt symbol_destructor[k] = v[i]->destructor; 3027268899Sbapt symbol_type_tag[k] = v[i]->tag; 3028268899Sbapt } 3029268899Sbapt#endif 3030234949Sbapt } 3031234949Sbapt 3032234949Sbapt if (gflag) 3033234949Sbapt { 3034240517Sbapt symbol_pname = TMALLOC(char *, nsyms); 3035234949Sbapt NO_SPACE(symbol_pname); 3036234949Sbapt 3037234949Sbapt for (i = 0; i < nsyms; ++i) 3038234949Sbapt protect_string(symbol_name[i], &(symbol_pname[i])); 3039234949Sbapt } 3040234949Sbapt 3041234949Sbapt FREE(v); 3042234949Sbapt} 3043234949Sbapt 3044234949Sbaptstatic void 3045234949Sbaptpack_grammar(void) 3046234949Sbapt{ 3047234949Sbapt int i; 3048234949Sbapt Value_t j; 3049234949Sbapt Assoc_t assoc; 3050234949Sbapt Value_t prec2; 3051234949Sbapt 3052240517Sbapt ritem = TMALLOC(Value_t, nitems); 3053234949Sbapt NO_SPACE(ritem); 3054234949Sbapt 3055240517Sbapt rlhs = TMALLOC(Value_t, nrules); 3056234949Sbapt NO_SPACE(rlhs); 3057234949Sbapt 3058240517Sbapt rrhs = TMALLOC(Value_t, nrules + 1); 3059234949Sbapt NO_SPACE(rrhs); 3060234949Sbapt 3061240517Sbapt rprec = TREALLOC(Value_t, rprec, nrules); 3062234949Sbapt NO_SPACE(rprec); 3063234949Sbapt 3064240517Sbapt rassoc = TREALLOC(Assoc_t, rassoc, nrules); 3065234949Sbapt NO_SPACE(rassoc); 3066234949Sbapt 3067234949Sbapt ritem[0] = -1; 3068234949Sbapt ritem[1] = goal->index; 3069234949Sbapt ritem[2] = 0; 3070234949Sbapt ritem[3] = -2; 3071234949Sbapt rlhs[0] = 0; 3072234949Sbapt rlhs[1] = 0; 3073234949Sbapt rlhs[2] = start_symbol; 3074234949Sbapt rrhs[0] = 0; 3075234949Sbapt rrhs[1] = 0; 3076234949Sbapt rrhs[2] = 1; 3077234949Sbapt 3078234949Sbapt j = 4; 3079234949Sbapt for (i = 3; i < nrules; ++i) 3080234949Sbapt { 3081268899Sbapt#if defined(YYBTYACC) 3082268899Sbapt if (plhs[i]->args > 0) 3083268899Sbapt { 3084268899Sbapt if (plhs[i]->argnames) 3085268899Sbapt { 3086268899Sbapt FREE(plhs[i]->argnames); 3087268899Sbapt plhs[i]->argnames = NULL; 3088268899Sbapt } 3089268899Sbapt if (plhs[i]->argtags) 3090268899Sbapt { 3091268899Sbapt FREE(plhs[i]->argtags); 3092268899Sbapt plhs[i]->argtags = NULL; 3093268899Sbapt } 3094268899Sbapt } 3095268899Sbapt#endif /* defined(YYBTYACC) */ 3096234949Sbapt rlhs[i] = plhs[i]->index; 3097234949Sbapt rrhs[i] = j; 3098234949Sbapt assoc = TOKEN; 3099234949Sbapt prec2 = 0; 3100234949Sbapt while (pitem[j]) 3101234949Sbapt { 3102234949Sbapt ritem[j] = pitem[j]->index; 3103234949Sbapt if (pitem[j]->class == TERM) 3104234949Sbapt { 3105234949Sbapt prec2 = pitem[j]->prec; 3106234949Sbapt assoc = pitem[j]->assoc; 3107234949Sbapt } 3108234949Sbapt ++j; 3109234949Sbapt } 3110234949Sbapt ritem[j] = (Value_t) - i; 3111234949Sbapt ++j; 3112234949Sbapt if (rprec[i] == UNDEFINED) 3113234949Sbapt { 3114234949Sbapt rprec[i] = prec2; 3115234949Sbapt rassoc[i] = assoc; 3116234949Sbapt } 3117234949Sbapt } 3118234949Sbapt rrhs[i] = j; 3119234949Sbapt 3120234949Sbapt FREE(plhs); 3121234949Sbapt FREE(pitem); 3122268899Sbapt#if defined(YYBTYACC) 3123268899Sbapt clean_arg_cache(); 3124268899Sbapt#endif 3125234949Sbapt} 3126234949Sbapt 3127234949Sbaptstatic void 3128234949Sbaptprint_grammar(void) 3129234949Sbapt{ 3130234949Sbapt int i, k; 3131234949Sbapt size_t j, spacing = 0; 3132234949Sbapt FILE *f = verbose_file; 3133234949Sbapt 3134234949Sbapt if (!vflag) 3135234949Sbapt return; 3136234949Sbapt 3137234949Sbapt k = 1; 3138234949Sbapt for (i = 2; i < nrules; ++i) 3139234949Sbapt { 3140234949Sbapt if (rlhs[i] != rlhs[i - 1]) 3141234949Sbapt { 3142234949Sbapt if (i != 2) 3143234949Sbapt fprintf(f, "\n"); 3144234949Sbapt fprintf(f, "%4d %s :", i - 2, symbol_name[rlhs[i]]); 3145234949Sbapt spacing = strlen(symbol_name[rlhs[i]]) + 1; 3146234949Sbapt } 3147234949Sbapt else 3148234949Sbapt { 3149234949Sbapt fprintf(f, "%4d ", i - 2); 3150234949Sbapt j = spacing; 3151234949Sbapt while (j-- != 0) 3152234949Sbapt putc(' ', f); 3153234949Sbapt putc('|', f); 3154234949Sbapt } 3155234949Sbapt 3156234949Sbapt while (ritem[k] >= 0) 3157234949Sbapt { 3158234949Sbapt fprintf(f, " %s", symbol_name[ritem[k]]); 3159234949Sbapt ++k; 3160234949Sbapt } 3161234949Sbapt ++k; 3162234949Sbapt putc('\n', f); 3163234949Sbapt } 3164234949Sbapt} 3165234949Sbapt 3166268899Sbapt#if defined(YYBTYACC) 3167268899Sbaptstatic void 3168268899Sbaptfinalize_destructors(void) 3169268899Sbapt{ 3170268899Sbapt int i; 3171268899Sbapt bucket *bp; 3172268899Sbapt char *tag; 3173268899Sbapt 3174268899Sbapt for (i = 2; i < nsyms; ++i) 3175268899Sbapt { 3176268899Sbapt tag = symbol_type_tag[i]; 3177268899Sbapt if (symbol_destructor[i] == NULL) 3178268899Sbapt { 3179268899Sbapt if (tag == NULL) 3180268899Sbapt { /* use <> destructor, if there is one */ 3181268899Sbapt if ((bp = default_destructor[UNTYPED_DEFAULT]) != NULL) 3182268899Sbapt { 3183268899Sbapt symbol_destructor[i] = TMALLOC(char, 3184268899Sbapt strlen(bp->destructor) + 1); 3185268899Sbapt NO_SPACE(symbol_destructor[i]); 3186268899Sbapt strcpy(symbol_destructor[i], bp->destructor); 3187268899Sbapt } 3188268899Sbapt } 3189268899Sbapt else 3190268899Sbapt { /* use type destructor for this tag, if there is one */ 3191268899Sbapt bp = lookup_type_destructor(tag); 3192268899Sbapt if (bp->destructor != NULL) 3193268899Sbapt { 3194268899Sbapt symbol_destructor[i] = TMALLOC(char, 3195268899Sbapt strlen(bp->destructor) + 1); 3196268899Sbapt NO_SPACE(symbol_destructor[i]); 3197268899Sbapt strcpy(symbol_destructor[i], bp->destructor); 3198268899Sbapt } 3199268899Sbapt else 3200268899Sbapt { /* use <*> destructor, if there is one */ 3201268899Sbapt if ((bp = default_destructor[TYPED_DEFAULT]) != NULL) 3202268899Sbapt /* replace "$$" with "(*val).tag" in destructor code */ 3203268899Sbapt symbol_destructor[i] 3204268899Sbapt = process_destructor_XX(bp->destructor, tag); 3205268899Sbapt } 3206268899Sbapt } 3207268899Sbapt } 3208268899Sbapt else 3209268899Sbapt { /* replace "$$" with "(*val)[.tag]" in destructor code */ 3210268899Sbapt symbol_destructor[i] 3211268899Sbapt = process_destructor_XX(symbol_destructor[i], tag); 3212268899Sbapt } 3213268899Sbapt } 3214268899Sbapt /* 'symbol_type_tag[]' elements are freed by 'free_tags()' */ 3215268899Sbapt DO_FREE(symbol_type_tag); /* no longer needed */ 3216268899Sbapt if ((bp = default_destructor[UNTYPED_DEFAULT]) != NULL) 3217268899Sbapt { 3218268899Sbapt FREE(bp->name); 3219268899Sbapt /* 'bp->tag' is a static value, don't free */ 3220268899Sbapt FREE(bp->destructor); 3221268899Sbapt FREE(bp); 3222268899Sbapt } 3223268899Sbapt if ((bp = default_destructor[TYPED_DEFAULT]) != NULL) 3224268899Sbapt { 3225268899Sbapt FREE(bp->name); 3226268899Sbapt /* 'bp->tag' is a static value, don't free */ 3227268899Sbapt FREE(bp->destructor); 3228268899Sbapt FREE(bp); 3229268899Sbapt } 3230268899Sbapt if ((bp = default_destructor[TYPE_SPECIFIED]) != NULL) 3231268899Sbapt { 3232268899Sbapt bucket *p; 3233268899Sbapt for (; bp; bp = p) 3234268899Sbapt { 3235268899Sbapt p = bp->link; 3236268899Sbapt FREE(bp->name); 3237268899Sbapt /* 'bp->tag' freed by 'free_tags()' */ 3238268899Sbapt FREE(bp->destructor); 3239268899Sbapt FREE(bp); 3240268899Sbapt } 3241268899Sbapt } 3242268899Sbapt} 3243268899Sbapt#endif /* defined(YYBTYACC) */ 3244268899Sbapt 3245234949Sbaptvoid 3246234949Sbaptreader(void) 3247234949Sbapt{ 3248234949Sbapt write_section(code_file, banner); 3249234949Sbapt create_symbol_table(); 3250234949Sbapt read_declarations(); 3251234949Sbapt read_grammar(); 3252234949Sbapt free_symbol_table(); 3253234949Sbapt pack_names(); 3254234949Sbapt check_symbols(); 3255234949Sbapt pack_symbols(); 3256234949Sbapt pack_grammar(); 3257234949Sbapt free_symbols(); 3258234949Sbapt print_grammar(); 3259268899Sbapt#if defined(YYBTYACC) 3260268899Sbapt if (destructor) 3261268899Sbapt finalize_destructors(); 3262268899Sbapt#endif 3263268899Sbapt free_tags(); 3264234949Sbapt} 3265234949Sbapt 3266234949Sbapt#ifdef NO_LEAKS 3267234949Sbaptstatic param * 3268234949Sbaptfree_declarations(param * list) 3269234949Sbapt{ 3270234949Sbapt while (list != 0) 3271234949Sbapt { 3272234949Sbapt param *next = list->next; 3273234949Sbapt free(list->type); 3274234949Sbapt free(list->name); 3275234949Sbapt free(list->type2); 3276234949Sbapt free(list); 3277234949Sbapt list = next; 3278234949Sbapt } 3279234949Sbapt return list; 3280234949Sbapt} 3281234949Sbapt 3282234949Sbaptvoid 3283234949Sbaptreader_leaks(void) 3284234949Sbapt{ 3285234949Sbapt lex_param = free_declarations(lex_param); 3286234949Sbapt parse_param = free_declarations(parse_param); 3287234949Sbapt 3288234949Sbapt DO_FREE(line); 3289234949Sbapt DO_FREE(rrhs); 3290234949Sbapt DO_FREE(rlhs); 3291234949Sbapt DO_FREE(rprec); 3292234949Sbapt DO_FREE(ritem); 3293234949Sbapt DO_FREE(rassoc); 3294234949Sbapt DO_FREE(cache); 3295234949Sbapt DO_FREE(name_pool); 3296234949Sbapt DO_FREE(symbol_name); 3297234949Sbapt DO_FREE(symbol_prec); 3298234949Sbapt DO_FREE(symbol_assoc); 3299234949Sbapt DO_FREE(symbol_value); 3300268899Sbapt#if defined(YYBTYACC) 3301268899Sbapt DO_FREE(symbol_pval); 3302268899Sbapt DO_FREE(symbol_destructor); 3303268899Sbapt DO_FREE(symbol_type_tag); 3304268899Sbapt#endif 3305234949Sbapt} 3306234949Sbapt#endif 3307