reader.c revision 272957
1272957Srodrigc/* $Id: reader.c,v 1.58 2014/10/06 22:15:08 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{ 73272955Srodrigc const char fmt[] = "%.*s destructor"; 74268899Sbapt char name[1024] = "\0"; 75268899Sbapt bucket *bp, **bpp = &default_destructor[TYPE_SPECIFIED]; 76268899Sbapt 77268899Sbapt while ((bp = *bpp) != NULL) 78268899Sbapt { 79268899Sbapt if (bp->tag == tag) 80268899Sbapt return (bp); 81268899Sbapt bpp = &bp->link; 82268899Sbapt } 83268899Sbapt 84272955Srodrigc sprintf(name, fmt, (int)(sizeof(name) - sizeof(fmt)), tag); 85272955Srodrigc *bpp = bp = make_bucket(name); 86268899Sbapt bp->tag = tag; 87268899Sbapt 88268899Sbapt return (bp); 89268899Sbapt} 90268899Sbapt#endif /* defined(YYBTYACC) */ 91268899Sbapt 92234949Sbaptstatic void 93234949Sbaptcachec(int c) 94234949Sbapt{ 95234949Sbapt assert(cinc >= 0); 96234949Sbapt if (cinc >= cache_size) 97234949Sbapt { 98234949Sbapt cache_size += 256; 99240517Sbapt cache = TREALLOC(char, cache, cache_size); 100234949Sbapt NO_SPACE(cache); 101234949Sbapt } 102234949Sbapt cache[cinc] = (char)c; 103234949Sbapt ++cinc; 104234949Sbapt} 105234949Sbapt 106234949Sbaptstatic void 107234949Sbaptget_line(void) 108234949Sbapt{ 109234949Sbapt FILE *f = input_file; 110234949Sbapt int c; 111234949Sbapt int i; 112234949Sbapt 113234949Sbapt if (saw_eof || (c = getc(f)) == EOF) 114234949Sbapt { 115234949Sbapt if (line) 116234949Sbapt { 117234949Sbapt FREE(line); 118234949Sbapt line = 0; 119234949Sbapt } 120234949Sbapt cptr = 0; 121234949Sbapt saw_eof = 1; 122234949Sbapt return; 123234949Sbapt } 124234949Sbapt 125234949Sbapt if (line == 0 || linesize != (LINESIZE + 1)) 126234949Sbapt { 127234949Sbapt if (line) 128234949Sbapt FREE(line); 129234949Sbapt linesize = LINESIZE + 1; 130272957Srodrigc line = TMALLOC(char, linesize); 131234949Sbapt NO_SPACE(line); 132234949Sbapt } 133234949Sbapt 134234949Sbapt i = 0; 135234949Sbapt ++lineno; 136234949Sbapt for (;;) 137234949Sbapt { 138272957Srodrigc line[i++] = (char)c; 139234949Sbapt if (c == '\n') 140268899Sbapt break; 141272957Srodrigc if ((i + 3) >= linesize) 142234949Sbapt { 143234949Sbapt linesize += LINESIZE; 144240517Sbapt line = TREALLOC(char, line, linesize); 145234949Sbapt NO_SPACE(line); 146234949Sbapt } 147234949Sbapt c = getc(f); 148234949Sbapt if (c == EOF) 149234949Sbapt { 150272957Srodrigc line[i++] = '\n'; 151234949Sbapt saw_eof = 1; 152268899Sbapt break; 153234949Sbapt } 154234949Sbapt } 155272957Srodrigc line[i] = '\0'; 156268899Sbapt cptr = line; 157268899Sbapt return; 158234949Sbapt} 159234949Sbapt 160234949Sbaptstatic char * 161234949Sbaptdup_line(void) 162234949Sbapt{ 163234949Sbapt char *p, *s, *t; 164234949Sbapt 165234949Sbapt if (line == 0) 166234949Sbapt return (0); 167234949Sbapt s = line; 168234949Sbapt while (*s != '\n') 169234949Sbapt ++s; 170240517Sbapt p = TMALLOC(char, s - line + 1); 171234949Sbapt NO_SPACE(p); 172234949Sbapt 173234949Sbapt s = line; 174234949Sbapt t = p; 175234949Sbapt while ((*t++ = *s++) != '\n') 176234949Sbapt continue; 177234949Sbapt return (p); 178234949Sbapt} 179234949Sbapt 180234949Sbaptstatic void 181234949Sbaptskip_comment(void) 182234949Sbapt{ 183234949Sbapt char *s; 184234949Sbapt 185234949Sbapt int st_lineno = lineno; 186234949Sbapt char *st_line = dup_line(); 187234949Sbapt char *st_cptr = st_line + (cptr - line); 188234949Sbapt 189234949Sbapt s = cptr + 2; 190234949Sbapt for (;;) 191234949Sbapt { 192234949Sbapt if (*s == '*' && s[1] == '/') 193234949Sbapt { 194234949Sbapt cptr = s + 2; 195234949Sbapt FREE(st_line); 196234949Sbapt return; 197234949Sbapt } 198234949Sbapt if (*s == '\n') 199234949Sbapt { 200234949Sbapt get_line(); 201234949Sbapt if (line == 0) 202234949Sbapt unterminated_comment(st_lineno, st_line, st_cptr); 203234949Sbapt s = cptr; 204234949Sbapt } 205234949Sbapt else 206234949Sbapt ++s; 207234949Sbapt } 208234949Sbapt} 209234949Sbapt 210234949Sbaptstatic int 211272955Srodrigcnext_inline(void) 212234949Sbapt{ 213234949Sbapt char *s; 214234949Sbapt 215234949Sbapt if (line == 0) 216234949Sbapt { 217234949Sbapt get_line(); 218234949Sbapt if (line == 0) 219234949Sbapt return (EOF); 220234949Sbapt } 221234949Sbapt 222234949Sbapt s = cptr; 223234949Sbapt for (;;) 224234949Sbapt { 225234949Sbapt switch (*s) 226234949Sbapt { 227234949Sbapt case '/': 228234949Sbapt if (s[1] == '*') 229234949Sbapt { 230234949Sbapt cptr = s; 231234949Sbapt skip_comment(); 232234949Sbapt s = cptr; 233234949Sbapt break; 234234949Sbapt } 235234949Sbapt else if (s[1] == '/') 236234949Sbapt { 237234949Sbapt get_line(); 238234949Sbapt if (line == 0) 239234949Sbapt return (EOF); 240234949Sbapt s = cptr; 241234949Sbapt break; 242234949Sbapt } 243234949Sbapt /* FALLTHRU */ 244234949Sbapt 245234949Sbapt default: 246234949Sbapt cptr = s; 247234949Sbapt return (*s); 248234949Sbapt } 249234949Sbapt } 250234949Sbapt} 251272955Srodrigc 252272955Srodrigcstatic int 253272955Srodrigcnextc(void) 254272955Srodrigc{ 255272955Srodrigc int ch; 256272955Srodrigc int finish = 0; 257272955Srodrigc 258272955Srodrigc do 259272955Srodrigc { 260272955Srodrigc switch (ch = next_inline()) 261272955Srodrigc { 262272955Srodrigc case '\n': 263272955Srodrigc get_line(); 264272955Srodrigc break; 265272955Srodrigc case ' ': 266272955Srodrigc case '\t': 267272955Srodrigc case '\f': 268272955Srodrigc case '\r': 269272955Srodrigc case '\v': 270272955Srodrigc case ',': 271272955Srodrigc case ';': 272272955Srodrigc ++cptr; 273272955Srodrigc break; 274272955Srodrigc case '\\': 275272955Srodrigc ch = '%'; 276272955Srodrigc /* FALLTHRU */ 277272955Srodrigc default: 278272955Srodrigc finish = 1; 279272955Srodrigc break; 280272955Srodrigc } 281272955Srodrigc } 282272955Srodrigc while (!finish); 283272955Srodrigc 284272955Srodrigc return ch; 285272955Srodrigc} 286268899Sbapt/* *INDENT-OFF* */ 287268899Sbaptstatic struct keyword 288268899Sbapt{ 289268899Sbapt char name[13]; 290268899Sbapt int token; 291268899Sbapt} 292268899Sbaptkeywords[] = { 293268899Sbapt { "binary", NONASSOC }, 294268899Sbapt#if defined(YYBTYACC) 295268899Sbapt { "destructor", DESTRUCTOR }, 296268899Sbapt#endif 297268899Sbapt { "expect", EXPECT }, 298268899Sbapt { "expect-rr", EXPECT_RR }, 299268899Sbapt { "ident", IDENT }, 300268899Sbapt { "left", LEFT }, 301268899Sbapt { "lex-param", LEX_PARAM }, 302268899Sbapt#if defined(YYBTYACC) 303268899Sbapt { "locations", LOCATIONS }, 304268899Sbapt#endif 305268899Sbapt { "nonassoc", NONASSOC }, 306268899Sbapt { "parse-param", PARSE_PARAM }, 307268899Sbapt { "pure-parser", PURE_PARSER }, 308268899Sbapt { "right", RIGHT }, 309268899Sbapt { "start", START }, 310268899Sbapt { "term", TOKEN }, 311268899Sbapt { "token", TOKEN }, 312268899Sbapt { "token-table", TOKEN_TABLE }, 313268899Sbapt { "type", TYPE }, 314268899Sbapt { "union", UNION }, 315268899Sbapt { "yacc", POSIX_YACC }, 316268899Sbapt}; 317268899Sbapt/* *INDENT-ON* */ 318234949Sbapt 319234949Sbaptstatic int 320268899Sbaptcompare_keys(const void *a, const void *b) 321234949Sbapt{ 322268899Sbapt const struct keyword *p = (const struct keyword *)a; 323268899Sbapt const struct keyword *q = (const struct keyword *)b; 324268899Sbapt return strcmp(p->name, q->name); 325234949Sbapt} 326234949Sbapt 327234949Sbaptstatic int 328234949Sbaptkeyword(void) 329234949Sbapt{ 330234949Sbapt int c; 331234949Sbapt char *t_cptr = cptr; 332268899Sbapt struct keyword *key; 333234949Sbapt 334234949Sbapt c = *++cptr; 335234949Sbapt if (isalpha(c)) 336234949Sbapt { 337234949Sbapt cinc = 0; 338234949Sbapt for (;;) 339234949Sbapt { 340234949Sbapt if (isalpha(c)) 341234949Sbapt { 342234949Sbapt if (isupper(c)) 343234949Sbapt c = tolower(c); 344234949Sbapt cachec(c); 345234949Sbapt } 346234949Sbapt else if (isdigit(c) 347234949Sbapt || c == '-' 348234949Sbapt || c == '.' 349234949Sbapt || c == '$') 350234949Sbapt { 351234949Sbapt cachec(c); 352234949Sbapt } 353268899Sbapt else if (c == '_') 354268899Sbapt { 355268899Sbapt /* treat keywords spelled with '_' as if it were '-' */ 356268899Sbapt cachec('-'); 357268899Sbapt } 358234949Sbapt else 359234949Sbapt { 360234949Sbapt break; 361234949Sbapt } 362234949Sbapt c = *++cptr; 363234949Sbapt } 364234949Sbapt cachec(NUL); 365234949Sbapt 366268899Sbapt if ((key = bsearch(cache, keywords, 367268899Sbapt sizeof(keywords) / sizeof(*key), 368268899Sbapt sizeof(*key), compare_keys))) 369268899Sbapt return key->token; 370234949Sbapt } 371234949Sbapt else 372234949Sbapt { 373234949Sbapt ++cptr; 374234949Sbapt if (c == L_CURL) 375234949Sbapt return (TEXT); 376234949Sbapt if (c == '%' || c == '\\') 377234949Sbapt return (MARK); 378234949Sbapt if (c == '<') 379234949Sbapt return (LEFT); 380234949Sbapt if (c == '>') 381234949Sbapt return (RIGHT); 382234949Sbapt if (c == '0') 383234949Sbapt return (TOKEN); 384234949Sbapt if (c == '2') 385234949Sbapt return (NONASSOC); 386234949Sbapt } 387234949Sbapt syntax_error(lineno, line, t_cptr); 388235723Sbapt return (-1); 389234949Sbapt} 390234949Sbapt 391234949Sbaptstatic void 392234949Sbaptcopy_ident(void) 393234949Sbapt{ 394234949Sbapt int c; 395234949Sbapt FILE *f = output_file; 396234949Sbapt 397234949Sbapt c = nextc(); 398234949Sbapt if (c == EOF) 399234949Sbapt unexpected_EOF(); 400234949Sbapt if (c != '"') 401234949Sbapt syntax_error(lineno, line, cptr); 402234949Sbapt ++outline; 403234949Sbapt fprintf(f, "#ident \""); 404234949Sbapt for (;;) 405234949Sbapt { 406234949Sbapt c = *++cptr; 407234949Sbapt if (c == '\n') 408234949Sbapt { 409234949Sbapt fprintf(f, "\"\n"); 410234949Sbapt return; 411234949Sbapt } 412234949Sbapt putc(c, f); 413234949Sbapt if (c == '"') 414234949Sbapt { 415234949Sbapt putc('\n', f); 416234949Sbapt ++cptr; 417234949Sbapt return; 418234949Sbapt } 419234949Sbapt } 420234949Sbapt} 421234949Sbapt 422268899Sbaptstatic char * 423268899Sbaptcopy_string(int quote) 424268899Sbapt{ 425268899Sbapt struct mstring *temp = msnew(); 426268899Sbapt int c; 427268899Sbapt int s_lineno = lineno; 428268899Sbapt char *s_line = dup_line(); 429268899Sbapt char *s_cptr = s_line + (cptr - line - 1); 430268899Sbapt 431268899Sbapt for (;;) 432268899Sbapt { 433268899Sbapt c = *cptr++; 434268899Sbapt mputc(temp, c); 435268899Sbapt if (c == quote) 436268899Sbapt { 437268899Sbapt FREE(s_line); 438268899Sbapt return msdone(temp); 439268899Sbapt } 440268899Sbapt if (c == '\n') 441268899Sbapt unterminated_string(s_lineno, s_line, s_cptr); 442268899Sbapt if (c == '\\') 443268899Sbapt { 444268899Sbapt c = *cptr++; 445268899Sbapt mputc(temp, c); 446268899Sbapt if (c == '\n') 447268899Sbapt { 448268899Sbapt get_line(); 449268899Sbapt if (line == 0) 450268899Sbapt unterminated_string(s_lineno, s_line, s_cptr); 451268899Sbapt } 452268899Sbapt } 453268899Sbapt } 454268899Sbapt} 455268899Sbapt 456268899Sbaptstatic char * 457268899Sbaptcopy_comment(void) 458268899Sbapt{ 459268899Sbapt struct mstring *temp = msnew(); 460268899Sbapt int c; 461268899Sbapt 462268899Sbapt c = *cptr; 463268899Sbapt if (c == '/') 464268899Sbapt { 465268899Sbapt mputc(temp, '*'); 466268899Sbapt while ((c = *++cptr) != '\n') 467268899Sbapt { 468268899Sbapt mputc(temp, c); 469268899Sbapt if (c == '*' && cptr[1] == '/') 470268899Sbapt mputc(temp, ' '); 471268899Sbapt } 472268899Sbapt mputc(temp, '*'); 473268899Sbapt mputc(temp, '/'); 474268899Sbapt } 475268899Sbapt else if (c == '*') 476268899Sbapt { 477268899Sbapt int c_lineno = lineno; 478268899Sbapt char *c_line = dup_line(); 479268899Sbapt char *c_cptr = c_line + (cptr - line - 1); 480268899Sbapt 481268899Sbapt mputc(temp, c); 482268899Sbapt ++cptr; 483268899Sbapt for (;;) 484268899Sbapt { 485268899Sbapt c = *cptr++; 486268899Sbapt mputc(temp, c); 487268899Sbapt if (c == '*' && *cptr == '/') 488268899Sbapt { 489268899Sbapt mputc(temp, '/'); 490268899Sbapt ++cptr; 491268899Sbapt FREE(c_line); 492268899Sbapt return msdone(temp); 493268899Sbapt } 494268899Sbapt if (c == '\n') 495268899Sbapt { 496268899Sbapt get_line(); 497268899Sbapt if (line == 0) 498268899Sbapt unterminated_comment(c_lineno, c_line, c_cptr); 499268899Sbapt } 500268899Sbapt } 501268899Sbapt } 502268899Sbapt return msdone(temp); 503268899Sbapt} 504268899Sbapt 505234949Sbaptstatic void 506234949Sbaptcopy_text(void) 507234949Sbapt{ 508234949Sbapt int c; 509234949Sbapt FILE *f = text_file; 510234949Sbapt int need_newline = 0; 511234949Sbapt int t_lineno = lineno; 512234949Sbapt char *t_line = dup_line(); 513234949Sbapt char *t_cptr = t_line + (cptr - line - 2); 514234949Sbapt 515234949Sbapt if (*cptr == '\n') 516234949Sbapt { 517234949Sbapt get_line(); 518234949Sbapt if (line == 0) 519234949Sbapt unterminated_text(t_lineno, t_line, t_cptr); 520234949Sbapt } 521234949Sbapt if (!lflag) 522234949Sbapt fprintf(f, line_format, lineno, input_file_name); 523234949Sbapt 524234949Sbapt loop: 525234949Sbapt c = *cptr++; 526234949Sbapt switch (c) 527234949Sbapt { 528234949Sbapt case '\n': 529234949Sbapt putc('\n', f); 530234949Sbapt need_newline = 0; 531234949Sbapt get_line(); 532234949Sbapt if (line) 533234949Sbapt goto loop; 534234949Sbapt unterminated_text(t_lineno, t_line, t_cptr); 535234949Sbapt 536234949Sbapt case '\'': 537234949Sbapt case '"': 538268899Sbapt putc(c, f); 539234949Sbapt { 540268899Sbapt char *s = copy_string(c); 541268899Sbapt fputs(s, f); 542268899Sbapt free(s); 543234949Sbapt } 544268899Sbapt need_newline = 1; 545268899Sbapt goto loop; 546234949Sbapt 547234949Sbapt case '/': 548234949Sbapt putc(c, f); 549234949Sbapt { 550268899Sbapt char *s = copy_comment(); 551268899Sbapt fputs(s, f); 552268899Sbapt free(s); 553234949Sbapt } 554234949Sbapt need_newline = 1; 555234949Sbapt goto loop; 556234949Sbapt 557234949Sbapt case '%': 558234949Sbapt case '\\': 559234949Sbapt if (*cptr == R_CURL) 560234949Sbapt { 561234949Sbapt if (need_newline) 562234949Sbapt putc('\n', f); 563234949Sbapt ++cptr; 564234949Sbapt FREE(t_line); 565234949Sbapt return; 566234949Sbapt } 567234949Sbapt /* FALLTHRU */ 568234949Sbapt 569234949Sbapt default: 570234949Sbapt putc(c, f); 571234949Sbapt need_newline = 1; 572234949Sbapt goto loop; 573234949Sbapt } 574234949Sbapt} 575234949Sbapt 576234949Sbaptstatic void 577234949Sbaptputs_both(const char *s) 578234949Sbapt{ 579234949Sbapt fputs(s, text_file); 580234949Sbapt if (dflag) 581234949Sbapt fputs(s, union_file); 582234949Sbapt} 583234949Sbapt 584234949Sbaptstatic void 585234949Sbaptputc_both(int c) 586234949Sbapt{ 587234949Sbapt putc(c, text_file); 588234949Sbapt if (dflag) 589234949Sbapt putc(c, union_file); 590234949Sbapt} 591234949Sbapt 592234949Sbaptstatic void 593234949Sbaptcopy_union(void) 594234949Sbapt{ 595234949Sbapt int c; 596234949Sbapt int depth; 597234949Sbapt int u_lineno = lineno; 598234949Sbapt char *u_line = dup_line(); 599234949Sbapt char *u_cptr = u_line + (cptr - line - 6); 600234949Sbapt 601234949Sbapt if (unionized) 602234949Sbapt over_unionized(cptr - 6); 603234949Sbapt unionized = 1; 604234949Sbapt 605234949Sbapt if (!lflag) 606234949Sbapt fprintf(text_file, line_format, lineno, input_file_name); 607234949Sbapt 608234949Sbapt puts_both("#ifdef YYSTYPE\n"); 609234949Sbapt puts_both("#undef YYSTYPE_IS_DECLARED\n"); 610234949Sbapt puts_both("#define YYSTYPE_IS_DECLARED 1\n"); 611234949Sbapt puts_both("#endif\n"); 612234949Sbapt puts_both("#ifndef YYSTYPE_IS_DECLARED\n"); 613234949Sbapt puts_both("#define YYSTYPE_IS_DECLARED 1\n"); 614234949Sbapt puts_both("typedef union"); 615234949Sbapt 616234949Sbapt depth = 0; 617234949Sbapt loop: 618234949Sbapt c = *cptr++; 619234949Sbapt putc_both(c); 620234949Sbapt switch (c) 621234949Sbapt { 622234949Sbapt case '\n': 623234949Sbapt get_line(); 624234949Sbapt if (line == 0) 625234949Sbapt unterminated_union(u_lineno, u_line, u_cptr); 626234949Sbapt goto loop; 627234949Sbapt 628234949Sbapt case L_CURL: 629234949Sbapt ++depth; 630234949Sbapt goto loop; 631234949Sbapt 632234949Sbapt case R_CURL: 633234949Sbapt if (--depth == 0) 634234949Sbapt { 635234949Sbapt puts_both(" YYSTYPE;\n"); 636234949Sbapt puts_both("#endif /* !YYSTYPE_IS_DECLARED */\n"); 637234949Sbapt FREE(u_line); 638234949Sbapt return; 639234949Sbapt } 640234949Sbapt goto loop; 641234949Sbapt 642234949Sbapt case '\'': 643234949Sbapt case '"': 644234949Sbapt { 645268899Sbapt char *s = copy_string(c); 646268899Sbapt puts_both(s); 647268899Sbapt free(s); 648234949Sbapt } 649268899Sbapt goto loop; 650234949Sbapt 651234949Sbapt case '/': 652234949Sbapt { 653268899Sbapt char *s = copy_comment(); 654268899Sbapt puts_both(s); 655268899Sbapt free(s); 656234949Sbapt } 657234949Sbapt goto loop; 658234949Sbapt 659234949Sbapt default: 660234949Sbapt goto loop; 661234949Sbapt } 662234949Sbapt} 663234949Sbapt 664272955Srodrigcstatic char * 665272955Srodrigcafter_blanks(char *s) 666272955Srodrigc{ 667272955Srodrigc while (*s != '\0' && isspace(UCH(*s))) 668272955Srodrigc ++s; 669272955Srodrigc return s; 670272955Srodrigc} 671272955Srodrigc 672234949Sbapt/* 673272955Srodrigc * Trim leading/trailing blanks, and collapse multiple embedded blanks to a 674272955Srodrigc * single space. Return index to last character in the buffer. 675234949Sbapt */ 676272955Srodrigcstatic int 677272955Srodrigctrim_blanks(char *buffer) 678234949Sbapt{ 679272955Srodrigc if (*buffer != '\0') 680272955Srodrigc { 681272955Srodrigc char *d = buffer; 682272955Srodrigc char *s = after_blanks(d); 683234949Sbapt 684272955Srodrigc while ((*d++ = *s++) != '\0') 685272955Srodrigc { 686272955Srodrigc ; 687272955Srodrigc } 688234949Sbapt 689272955Srodrigc --d; 690272955Srodrigc while ((--d != buffer) && isspace(UCH(*d))) 691272955Srodrigc *d = '\0'; 692234949Sbapt 693272955Srodrigc for (s = d = buffer; (*d++ = *s++) != '\0';) 694272955Srodrigc { 695272955Srodrigc if (isspace(UCH(*s))) 696272955Srodrigc { 697272955Srodrigc *s = ' '; 698272955Srodrigc while (isspace(UCH(*s))) 699272955Srodrigc { 700272955Srodrigc *s++ = ' '; 701272955Srodrigc } 702272955Srodrigc --s; 703272955Srodrigc } 704272955Srodrigc } 705234949Sbapt } 706234949Sbapt 707272955Srodrigc return (int)strlen(buffer) - 1; 708272955Srodrigc} 709234949Sbapt 710272955Srodrigc/* 711272955Srodrigc * Scan forward in the current line-buffer looking for a right-curly bracket. 712272955Srodrigc * 713272955Srodrigc * Parameters begin with a left-curly bracket, and continue until there are no 714272955Srodrigc * more interesting characters after the last right-curly bracket on the 715272955Srodrigc * current line. Bison documents parameters as separated like this: 716272955Srodrigc * {type param1} {type2 param2} 717272955Srodrigc * but also accepts commas (although some versions of bison mishandle this) 718272955Srodrigc * {type param1, type2 param2} 719272955Srodrigc */ 720272955Srodrigcstatic int 721272955Srodrigcmore_curly(void) 722272955Srodrigc{ 723272955Srodrigc char *save = cptr; 724272955Srodrigc int result = 0; 725272955Srodrigc int finish = 0; 726272955Srodrigc do 727234949Sbapt { 728272955Srodrigc switch (next_inline()) 729234949Sbapt { 730272955Srodrigc case 0: 731272955Srodrigc case '\n': 732272955Srodrigc finish = 1; 733272955Srodrigc break; 734272955Srodrigc case R_CURL: 735272955Srodrigc finish = 1; 736272955Srodrigc result = 1; 737272955Srodrigc break; 738234949Sbapt } 739272955Srodrigc ++cptr; 740234949Sbapt } 741272955Srodrigc while (!finish); 742272955Srodrigc cptr = save; 743272955Srodrigc return result; 744272955Srodrigc} 745234949Sbapt 746272955Srodrigcstatic void 747272955Srodrigcsave_param(int k, char *buffer, int name, int type2) 748272955Srodrigc{ 749272955Srodrigc param *head, *p; 750234949Sbapt 751240517Sbapt p = TMALLOC(param, 1); 752234949Sbapt NO_SPACE(p); 753234949Sbapt 754272955Srodrigc p->type2 = strdup(buffer + type2); 755234949Sbapt NO_SPACE(p->type2); 756272955Srodrigc buffer[type2] = '\0'; 757272955Srodrigc (void)trim_blanks(p->type2); 758234949Sbapt 759272955Srodrigc p->name = strdup(buffer + name); 760234949Sbapt NO_SPACE(p->name); 761272955Srodrigc buffer[name] = '\0'; 762272955Srodrigc (void)trim_blanks(p->name); 763234949Sbapt 764272955Srodrigc p->type = strdup(buffer); 765272955Srodrigc NO_SPACE(p->type); 766272955Srodrigc (void)trim_blanks(p->type); 767234949Sbapt 768234949Sbapt if (k == LEX_PARAM) 769234949Sbapt head = lex_param; 770234949Sbapt else 771234949Sbapt head = parse_param; 772234949Sbapt 773234949Sbapt if (head != NULL) 774234949Sbapt { 775234949Sbapt while (head->next) 776234949Sbapt head = head->next; 777234949Sbapt head->next = p; 778234949Sbapt } 779234949Sbapt else 780234949Sbapt { 781234949Sbapt if (k == LEX_PARAM) 782234949Sbapt lex_param = p; 783234949Sbapt else 784234949Sbapt parse_param = p; 785234949Sbapt } 786234949Sbapt p->next = NULL; 787272955Srodrigc} 788272955Srodrigc 789272955Srodrigc/* 790272955Srodrigc * Keep a linked list of parameters. This may be multi-line, if the trailing 791272955Srodrigc * right-curly bracket is absent. 792272955Srodrigc */ 793272955Srodrigcstatic void 794272955Srodrigccopy_param(int k) 795272955Srodrigc{ 796272955Srodrigc int c; 797272955Srodrigc int name, type2; 798272955Srodrigc int curly = 0; 799272955Srodrigc char *buf = 0; 800272955Srodrigc int i = -1; 801272955Srodrigc size_t buf_size = 0; 802272955Srodrigc int st_lineno = lineno; 803272955Srodrigc char *comma; 804272955Srodrigc 805272955Srodrigc do 806272955Srodrigc { 807272955Srodrigc int state = curly; 808272955Srodrigc c = next_inline(); 809272955Srodrigc switch (c) 810272955Srodrigc { 811272955Srodrigc case EOF: 812272955Srodrigc unexpected_EOF(); 813272955Srodrigc break; 814272955Srodrigc case L_CURL: 815272955Srodrigc if (curly == 1) 816272955Srodrigc { 817272955Srodrigc goto oops; 818272955Srodrigc } 819272955Srodrigc curly = 1; 820272955Srodrigc st_lineno = lineno; 821272955Srodrigc break; 822272955Srodrigc case R_CURL: 823272955Srodrigc if (curly != 1) 824272955Srodrigc { 825272955Srodrigc goto oops; 826272955Srodrigc } 827272955Srodrigc curly = 2; 828272955Srodrigc break; 829272955Srodrigc case '\n': 830272955Srodrigc if (curly == 0) 831272955Srodrigc { 832272955Srodrigc goto oops; 833272955Srodrigc } 834272955Srodrigc break; 835272955Srodrigc case '%': 836272955Srodrigc if ((curly == 1) && (cptr == line)) 837272955Srodrigc { 838272955Srodrigc lineno = st_lineno; 839272955Srodrigc missing_brace(); 840272955Srodrigc } 841272955Srodrigc /* FALLTHRU */ 842272955Srodrigc case '"': 843272955Srodrigc case '\'': 844272955Srodrigc goto oops; 845272955Srodrigc default: 846272955Srodrigc if (curly == 0 && !isspace(UCH(c))) 847272955Srodrigc { 848272955Srodrigc goto oops; 849272955Srodrigc } 850272955Srodrigc break; 851272955Srodrigc } 852272955Srodrigc if (buf == 0) 853272955Srodrigc { 854272955Srodrigc buf_size = (size_t) linesize; 855272955Srodrigc buf = TMALLOC(char, buf_size); 856272955Srodrigc } 857272955Srodrigc else if (c == '\n') 858272955Srodrigc { 859272955Srodrigc get_line(); 860272955Srodrigc if (line == 0) 861272955Srodrigc unexpected_EOF(); 862272955Srodrigc --cptr; 863272955Srodrigc buf_size += (size_t) linesize; 864272955Srodrigc buf = TREALLOC(char, buf, buf_size); 865272955Srodrigc } 866272955Srodrigc NO_SPACE(buf); 867272955Srodrigc if (curly) 868272955Srodrigc { 869272955Srodrigc if ((state == 2) && (c == L_CURL)) 870272955Srodrigc { 871272955Srodrigc buf[++i] = ','; 872272955Srodrigc } 873272955Srodrigc else if ((state == 2) && isspace(UCH(c))) 874272955Srodrigc { 875272955Srodrigc ; 876272955Srodrigc } 877272955Srodrigc else if ((c != L_CURL) && (c != R_CURL)) 878272955Srodrigc { 879272955Srodrigc buf[++i] = (char)c; 880272955Srodrigc } 881272955Srodrigc } 882272955Srodrigc cptr++; 883272955Srodrigc } 884272955Srodrigc while (curly < 2 || more_curly()); 885272955Srodrigc 886272955Srodrigc if (i == 0) 887272955Srodrigc { 888272955Srodrigc if (curly == 1) 889272955Srodrigc { 890272955Srodrigc lineno = st_lineno; 891272955Srodrigc missing_brace(); 892272955Srodrigc } 893272955Srodrigc goto oops; 894272955Srodrigc } 895272955Srodrigc 896272955Srodrigc buf[i--] = '\0'; 897272955Srodrigc i = trim_blanks(buf); 898272955Srodrigc 899272955Srodrigc comma = buf - 1; 900272955Srodrigc do 901272955Srodrigc { 902272955Srodrigc char *parms = (comma + 1); 903272955Srodrigc comma = strchr(parms, ','); 904272955Srodrigc if (comma != 0) 905272955Srodrigc *comma = '\0'; 906272955Srodrigc 907272955Srodrigc (void)trim_blanks(parms); 908272955Srodrigc i = (int)strlen(parms) - 1; 909272955Srodrigc if (i < 0) 910272955Srodrigc { 911272955Srodrigc goto oops; 912272955Srodrigc } 913272955Srodrigc 914272955Srodrigc if (parms[i] == ']') 915272955Srodrigc { 916272955Srodrigc int level = 1; 917272955Srodrigc while (i >= 0 && level > 0 && parms[i] != '[') 918272955Srodrigc { 919272955Srodrigc if (parms[i] == ']') 920272955Srodrigc ++level; 921272955Srodrigc else if (parms[i] == '[') 922272955Srodrigc --level; 923272955Srodrigc i--; 924272955Srodrigc } 925272955Srodrigc if (i <= 0) 926272955Srodrigc unexpected_EOF(); 927272955Srodrigc type2 = i--; 928272955Srodrigc } 929272955Srodrigc else 930272955Srodrigc { 931272955Srodrigc type2 = i + 1; 932272955Srodrigc } 933272955Srodrigc 934272955Srodrigc while (i > 0 && (isalnum(UCH(parms[i])) || UCH(parms[i]) == '_')) 935272955Srodrigc i--; 936272955Srodrigc 937272955Srodrigc if (!isspace(UCH(parms[i])) && parms[i] != '*') 938272955Srodrigc goto oops; 939272955Srodrigc 940272955Srodrigc name = i + 1; 941272955Srodrigc 942272955Srodrigc save_param(k, parms, name, type2); 943272955Srodrigc } 944272955Srodrigc while (comma != 0); 945272955Srodrigc FREE(buf); 946234949Sbapt return; 947234949Sbapt 948272955Srodrigc oops: 949272955Srodrigc FREE(buf); 950234949Sbapt syntax_error(lineno, line, cptr); 951234949Sbapt} 952234949Sbapt 953234949Sbaptstatic int 954234949Sbapthexval(int c) 955234949Sbapt{ 956234949Sbapt if (c >= '0' && c <= '9') 957234949Sbapt return (c - '0'); 958234949Sbapt if (c >= 'A' && c <= 'F') 959234949Sbapt return (c - 'A' + 10); 960234949Sbapt if (c >= 'a' && c <= 'f') 961234949Sbapt return (c - 'a' + 10); 962234949Sbapt return (-1); 963234949Sbapt} 964234949Sbapt 965234949Sbaptstatic bucket * 966234949Sbaptget_literal(void) 967234949Sbapt{ 968234949Sbapt int c, quote; 969234949Sbapt int i; 970234949Sbapt int n; 971234949Sbapt char *s; 972234949Sbapt bucket *bp; 973234949Sbapt int s_lineno = lineno; 974234949Sbapt char *s_line = dup_line(); 975234949Sbapt char *s_cptr = s_line + (cptr - line); 976234949Sbapt 977234949Sbapt quote = *cptr++; 978234949Sbapt cinc = 0; 979234949Sbapt for (;;) 980234949Sbapt { 981234949Sbapt c = *cptr++; 982234949Sbapt if (c == quote) 983234949Sbapt break; 984234949Sbapt if (c == '\n') 985234949Sbapt unterminated_string(s_lineno, s_line, s_cptr); 986234949Sbapt if (c == '\\') 987234949Sbapt { 988234949Sbapt char *c_cptr = cptr - 1; 989234949Sbapt 990234949Sbapt c = *cptr++; 991234949Sbapt switch (c) 992234949Sbapt { 993234949Sbapt case '\n': 994234949Sbapt get_line(); 995234949Sbapt if (line == 0) 996234949Sbapt unterminated_string(s_lineno, s_line, s_cptr); 997234949Sbapt continue; 998234949Sbapt 999234949Sbapt case '0': 1000234949Sbapt case '1': 1001234949Sbapt case '2': 1002234949Sbapt case '3': 1003234949Sbapt case '4': 1004234949Sbapt case '5': 1005234949Sbapt case '6': 1006234949Sbapt case '7': 1007234949Sbapt n = c - '0'; 1008234949Sbapt c = *cptr; 1009234949Sbapt if (IS_OCTAL(c)) 1010234949Sbapt { 1011234949Sbapt n = (n << 3) + (c - '0'); 1012234949Sbapt c = *++cptr; 1013234949Sbapt if (IS_OCTAL(c)) 1014234949Sbapt { 1015234949Sbapt n = (n << 3) + (c - '0'); 1016234949Sbapt ++cptr; 1017234949Sbapt } 1018234949Sbapt } 1019234949Sbapt if (n > MAXCHAR) 1020234949Sbapt illegal_character(c_cptr); 1021234949Sbapt c = n; 1022234949Sbapt break; 1023234949Sbapt 1024234949Sbapt case 'x': 1025234949Sbapt c = *cptr++; 1026234949Sbapt n = hexval(c); 1027234949Sbapt if (n < 0 || n >= 16) 1028234949Sbapt illegal_character(c_cptr); 1029234949Sbapt for (;;) 1030234949Sbapt { 1031234949Sbapt c = *cptr; 1032234949Sbapt i = hexval(c); 1033234949Sbapt if (i < 0 || i >= 16) 1034234949Sbapt break; 1035234949Sbapt ++cptr; 1036234949Sbapt n = (n << 4) + i; 1037234949Sbapt if (n > MAXCHAR) 1038234949Sbapt illegal_character(c_cptr); 1039234949Sbapt } 1040234949Sbapt c = n; 1041234949Sbapt break; 1042234949Sbapt 1043234949Sbapt case 'a': 1044234949Sbapt c = 7; 1045234949Sbapt break; 1046234949Sbapt case 'b': 1047234949Sbapt c = '\b'; 1048234949Sbapt break; 1049234949Sbapt case 'f': 1050234949Sbapt c = '\f'; 1051234949Sbapt break; 1052234949Sbapt case 'n': 1053234949Sbapt c = '\n'; 1054234949Sbapt break; 1055234949Sbapt case 'r': 1056234949Sbapt c = '\r'; 1057234949Sbapt break; 1058234949Sbapt case 't': 1059234949Sbapt c = '\t'; 1060234949Sbapt break; 1061234949Sbapt case 'v': 1062234949Sbapt c = '\v'; 1063234949Sbapt break; 1064234949Sbapt } 1065234949Sbapt } 1066234949Sbapt cachec(c); 1067234949Sbapt } 1068234949Sbapt FREE(s_line); 1069234949Sbapt 1070234949Sbapt n = cinc; 1071240517Sbapt s = TMALLOC(char, n); 1072234949Sbapt NO_SPACE(s); 1073234949Sbapt 1074234949Sbapt for (i = 0; i < n; ++i) 1075234949Sbapt s[i] = cache[i]; 1076234949Sbapt 1077234949Sbapt cinc = 0; 1078234949Sbapt if (n == 1) 1079234949Sbapt cachec('\''); 1080234949Sbapt else 1081234949Sbapt cachec('"'); 1082234949Sbapt 1083234949Sbapt for (i = 0; i < n; ++i) 1084234949Sbapt { 1085234949Sbapt c = UCH(s[i]); 1086234949Sbapt if (c == '\\' || c == cache[0]) 1087234949Sbapt { 1088234949Sbapt cachec('\\'); 1089234949Sbapt cachec(c); 1090234949Sbapt } 1091234949Sbapt else if (isprint(c)) 1092234949Sbapt cachec(c); 1093234949Sbapt else 1094234949Sbapt { 1095234949Sbapt cachec('\\'); 1096234949Sbapt switch (c) 1097234949Sbapt { 1098234949Sbapt case 7: 1099234949Sbapt cachec('a'); 1100234949Sbapt break; 1101234949Sbapt case '\b': 1102234949Sbapt cachec('b'); 1103234949Sbapt break; 1104234949Sbapt case '\f': 1105234949Sbapt cachec('f'); 1106234949Sbapt break; 1107234949Sbapt case '\n': 1108234949Sbapt cachec('n'); 1109234949Sbapt break; 1110234949Sbapt case '\r': 1111234949Sbapt cachec('r'); 1112234949Sbapt break; 1113234949Sbapt case '\t': 1114234949Sbapt cachec('t'); 1115234949Sbapt break; 1116234949Sbapt case '\v': 1117234949Sbapt cachec('v'); 1118234949Sbapt break; 1119234949Sbapt default: 1120234949Sbapt cachec(((c >> 6) & 7) + '0'); 1121234949Sbapt cachec(((c >> 3) & 7) + '0'); 1122234949Sbapt cachec((c & 7) + '0'); 1123234949Sbapt break; 1124234949Sbapt } 1125234949Sbapt } 1126234949Sbapt } 1127234949Sbapt 1128234949Sbapt if (n == 1) 1129234949Sbapt cachec('\''); 1130234949Sbapt else 1131234949Sbapt cachec('"'); 1132234949Sbapt 1133234949Sbapt cachec(NUL); 1134234949Sbapt bp = lookup(cache); 1135234949Sbapt bp->class = TERM; 1136234949Sbapt if (n == 1 && bp->value == UNDEFINED) 1137234949Sbapt bp->value = UCH(*s); 1138234949Sbapt FREE(s); 1139234949Sbapt 1140234949Sbapt return (bp); 1141234949Sbapt} 1142234949Sbapt 1143234949Sbaptstatic int 1144234949Sbaptis_reserved(char *name) 1145234949Sbapt{ 1146234949Sbapt char *s; 1147234949Sbapt 1148234949Sbapt if (strcmp(name, ".") == 0 || 1149234949Sbapt strcmp(name, "$accept") == 0 || 1150234949Sbapt strcmp(name, "$end") == 0) 1151234949Sbapt return (1); 1152234949Sbapt 1153234949Sbapt if (name[0] == '$' && name[1] == '$' && isdigit(UCH(name[2]))) 1154234949Sbapt { 1155234949Sbapt s = name + 3; 1156234949Sbapt while (isdigit(UCH(*s))) 1157234949Sbapt ++s; 1158234949Sbapt if (*s == NUL) 1159234949Sbapt return (1); 1160234949Sbapt } 1161234949Sbapt 1162234949Sbapt return (0); 1163234949Sbapt} 1164234949Sbapt 1165234949Sbaptstatic bucket * 1166234949Sbaptget_name(void) 1167234949Sbapt{ 1168234949Sbapt int c; 1169234949Sbapt 1170234949Sbapt cinc = 0; 1171234949Sbapt for (c = *cptr; IS_IDENT(c); c = *++cptr) 1172234949Sbapt cachec(c); 1173234949Sbapt cachec(NUL); 1174234949Sbapt 1175234949Sbapt if (is_reserved(cache)) 1176234949Sbapt used_reserved(cache); 1177234949Sbapt 1178234949Sbapt return (lookup(cache)); 1179234949Sbapt} 1180234949Sbapt 1181234949Sbaptstatic Value_t 1182234949Sbaptget_number(void) 1183234949Sbapt{ 1184234949Sbapt int c; 1185234949Sbapt Value_t n; 1186234949Sbapt 1187234949Sbapt n = 0; 1188234949Sbapt for (c = *cptr; isdigit(c); c = *++cptr) 1189234949Sbapt n = (Value_t) (10 * n + (c - '0')); 1190234949Sbapt 1191234949Sbapt return (n); 1192234949Sbapt} 1193234949Sbapt 1194234949Sbaptstatic char * 1195268899Sbaptcache_tag(char *tag, size_t len) 1196268899Sbapt{ 1197268899Sbapt int i; 1198268899Sbapt char *s; 1199268899Sbapt 1200268899Sbapt for (i = 0; i < ntags; ++i) 1201268899Sbapt { 1202268899Sbapt if (strncmp(tag, tag_table[i], len) == 0 && 1203268899Sbapt tag_table[i][len] == NUL) 1204268899Sbapt return (tag_table[i]); 1205268899Sbapt } 1206268899Sbapt 1207268899Sbapt if (ntags >= tagmax) 1208268899Sbapt { 1209268899Sbapt tagmax += 16; 1210268899Sbapt tag_table = 1211268899Sbapt (tag_table 1212268899Sbapt ? TREALLOC(char *, tag_table, tagmax) 1213268899Sbapt : TMALLOC(char *, tagmax)); 1214268899Sbapt NO_SPACE(tag_table); 1215268899Sbapt } 1216268899Sbapt 1217268899Sbapt s = TMALLOC(char, len + 1); 1218268899Sbapt NO_SPACE(s); 1219268899Sbapt 1220268899Sbapt strncpy(s, tag, len); 1221268899Sbapt s[len] = 0; 1222268899Sbapt tag_table[ntags++] = s; 1223268899Sbapt return s; 1224268899Sbapt} 1225268899Sbapt 1226268899Sbaptstatic char * 1227234949Sbaptget_tag(void) 1228234949Sbapt{ 1229234949Sbapt int c; 1230234949Sbapt int t_lineno = lineno; 1231234949Sbapt char *t_line = dup_line(); 1232234949Sbapt char *t_cptr = t_line + (cptr - line); 1233234949Sbapt 1234234949Sbapt ++cptr; 1235234949Sbapt c = nextc(); 1236234949Sbapt if (c == EOF) 1237234949Sbapt unexpected_EOF(); 1238234949Sbapt if (!isalpha(c) && c != '_' && c != '$') 1239234949Sbapt illegal_tag(t_lineno, t_line, t_cptr); 1240234949Sbapt 1241234949Sbapt cinc = 0; 1242234949Sbapt do 1243234949Sbapt { 1244234949Sbapt cachec(c); 1245234949Sbapt c = *++cptr; 1246234949Sbapt } 1247234949Sbapt while (IS_IDENT(c)); 1248234949Sbapt cachec(NUL); 1249234949Sbapt 1250234949Sbapt c = nextc(); 1251234949Sbapt if (c == EOF) 1252234949Sbapt unexpected_EOF(); 1253234949Sbapt if (c != '>') 1254234949Sbapt illegal_tag(t_lineno, t_line, t_cptr); 1255234949Sbapt ++cptr; 1256234949Sbapt 1257268899Sbapt FREE(t_line); 1258268899Sbapt havetags = 1; 1259268899Sbapt return cache_tag(cache, (size_t) cinc); 1260268899Sbapt} 1261234949Sbapt 1262268899Sbapt#if defined(YYBTYACC) 1263268899Sbaptstatic char * 1264268899Sbaptscan_id(void) 1265268899Sbapt{ 1266268899Sbapt char *b = cptr; 1267234949Sbapt 1268268899Sbapt while (isalnum(*cptr) || *cptr == '_' || *cptr == '$') 1269268899Sbapt cptr++; 1270268899Sbapt return cache_tag(b, (size_t) (cptr - b)); 1271234949Sbapt} 1272268899Sbapt#endif 1273234949Sbapt 1274234949Sbaptstatic void 1275234949Sbaptdeclare_tokens(int assoc) 1276234949Sbapt{ 1277234949Sbapt int c; 1278234949Sbapt bucket *bp; 1279234949Sbapt Value_t value; 1280234949Sbapt char *tag = 0; 1281234949Sbapt 1282234949Sbapt if (assoc != TOKEN) 1283234949Sbapt ++prec; 1284234949Sbapt 1285234949Sbapt c = nextc(); 1286234949Sbapt if (c == EOF) 1287234949Sbapt unexpected_EOF(); 1288234949Sbapt if (c == '<') 1289234949Sbapt { 1290234949Sbapt tag = get_tag(); 1291234949Sbapt c = nextc(); 1292234949Sbapt if (c == EOF) 1293234949Sbapt unexpected_EOF(); 1294234949Sbapt } 1295234949Sbapt 1296234949Sbapt for (;;) 1297234949Sbapt { 1298234949Sbapt if (isalpha(c) || c == '_' || c == '.' || c == '$') 1299234949Sbapt bp = get_name(); 1300234949Sbapt else if (c == '\'' || c == '"') 1301234949Sbapt bp = get_literal(); 1302234949Sbapt else 1303234949Sbapt return; 1304234949Sbapt 1305234949Sbapt if (bp == goal) 1306234949Sbapt tokenized_start(bp->name); 1307234949Sbapt bp->class = TERM; 1308234949Sbapt 1309234949Sbapt if (tag) 1310234949Sbapt { 1311234949Sbapt if (bp->tag && tag != bp->tag) 1312234949Sbapt retyped_warning(bp->name); 1313234949Sbapt bp->tag = tag; 1314234949Sbapt } 1315234949Sbapt 1316234949Sbapt if (assoc != TOKEN) 1317234949Sbapt { 1318234949Sbapt if (bp->prec && prec != bp->prec) 1319234949Sbapt reprec_warning(bp->name); 1320234949Sbapt bp->assoc = (Assoc_t) assoc; 1321234949Sbapt bp->prec = prec; 1322234949Sbapt } 1323234949Sbapt 1324234949Sbapt c = nextc(); 1325234949Sbapt if (c == EOF) 1326234949Sbapt unexpected_EOF(); 1327234949Sbapt 1328234949Sbapt if (isdigit(c)) 1329234949Sbapt { 1330234949Sbapt value = get_number(); 1331234949Sbapt if (bp->value != UNDEFINED && value != bp->value) 1332234949Sbapt revalued_warning(bp->name); 1333234949Sbapt bp->value = value; 1334234949Sbapt c = nextc(); 1335234949Sbapt if (c == EOF) 1336234949Sbapt unexpected_EOF(); 1337234949Sbapt } 1338234949Sbapt } 1339234949Sbapt} 1340234949Sbapt 1341234949Sbapt/* 1342234949Sbapt * %expect requires special handling 1343234949Sbapt * as it really isn't part of the yacc 1344234949Sbapt * grammar only a flag for yacc proper. 1345234949Sbapt */ 1346234949Sbaptstatic void 1347234949Sbaptdeclare_expect(int assoc) 1348234949Sbapt{ 1349234949Sbapt int c; 1350234949Sbapt 1351234949Sbapt if (assoc != EXPECT && assoc != EXPECT_RR) 1352234949Sbapt ++prec; 1353234949Sbapt 1354234949Sbapt /* 1355234949Sbapt * Stay away from nextc - doesn't 1356234949Sbapt * detect EOL and will read to EOF. 1357234949Sbapt */ 1358234949Sbapt c = *++cptr; 1359234949Sbapt if (c == EOF) 1360234949Sbapt unexpected_EOF(); 1361234949Sbapt 1362234949Sbapt for (;;) 1363234949Sbapt { 1364234949Sbapt if (isdigit(c)) 1365234949Sbapt { 1366234949Sbapt if (assoc == EXPECT) 1367234949Sbapt SRexpect = get_number(); 1368234949Sbapt else 1369234949Sbapt RRexpect = get_number(); 1370234949Sbapt break; 1371234949Sbapt } 1372234949Sbapt /* 1373234949Sbapt * Looking for number before EOL. 1374234949Sbapt * Spaces, tabs, and numbers are ok, 1375234949Sbapt * words, punc., etc. are syntax errors. 1376234949Sbapt */ 1377234949Sbapt else if (c == '\n' || isalpha(c) || !isspace(c)) 1378234949Sbapt { 1379234949Sbapt syntax_error(lineno, line, cptr); 1380234949Sbapt } 1381234949Sbapt else 1382234949Sbapt { 1383234949Sbapt c = *++cptr; 1384234949Sbapt if (c == EOF) 1385234949Sbapt unexpected_EOF(); 1386234949Sbapt } 1387234949Sbapt } 1388234949Sbapt} 1389234949Sbapt 1390268899Sbapt#if defined(YYBTYACC) 1391234949Sbaptstatic void 1392268899Sbaptdeclare_argtypes(bucket *bp) 1393268899Sbapt{ 1394268899Sbapt char *tags[MAXARGS]; 1395268899Sbapt int args = 0, c; 1396268899Sbapt 1397268899Sbapt if (bp->args >= 0) 1398268899Sbapt retyped_warning(bp->name); 1399268899Sbapt cptr++; /* skip open paren */ 1400268899Sbapt for (;;) 1401268899Sbapt { 1402268899Sbapt c = nextc(); 1403268899Sbapt if (c == EOF) 1404268899Sbapt unexpected_EOF(); 1405268899Sbapt if (c != '<') 1406268899Sbapt syntax_error(lineno, line, cptr); 1407268899Sbapt tags[args++] = get_tag(); 1408268899Sbapt c = nextc(); 1409268899Sbapt if (c == R_PAREN) 1410268899Sbapt break; 1411268899Sbapt if (c == EOF) 1412268899Sbapt unexpected_EOF(); 1413268899Sbapt } 1414268899Sbapt cptr++; /* skip close paren */ 1415268899Sbapt bp->args = args; 1416268899Sbapt bp->argnames = TMALLOC(char *, args); 1417268899Sbapt NO_SPACE(bp->argnames); 1418268899Sbapt bp->argtags = CALLOC(sizeof(char *), args + 1); 1419268899Sbapt NO_SPACE(bp->argtags); 1420268899Sbapt while (--args >= 0) 1421268899Sbapt { 1422268899Sbapt bp->argtags[args] = tags[args]; 1423268899Sbapt bp->argnames[args] = NULL; 1424268899Sbapt } 1425268899Sbapt} 1426268899Sbapt#endif 1427268899Sbapt 1428268899Sbaptstatic void 1429234949Sbaptdeclare_types(void) 1430234949Sbapt{ 1431234949Sbapt int c; 1432234949Sbapt bucket *bp; 1433268899Sbapt char *tag = NULL; 1434234949Sbapt 1435234949Sbapt c = nextc(); 1436234949Sbapt if (c == EOF) 1437234949Sbapt unexpected_EOF(); 1438268899Sbapt if (c == '<') 1439268899Sbapt tag = get_tag(); 1440234949Sbapt 1441234949Sbapt for (;;) 1442234949Sbapt { 1443234949Sbapt c = nextc(); 1444268899Sbapt if (c == EOF) 1445268899Sbapt unexpected_EOF(); 1446234949Sbapt if (isalpha(c) || c == '_' || c == '.' || c == '$') 1447268899Sbapt { 1448234949Sbapt bp = get_name(); 1449268899Sbapt#if defined(YYBTYACC) 1450268899Sbapt if (nextc() == L_PAREN) 1451268899Sbapt declare_argtypes(bp); 1452268899Sbapt else 1453268899Sbapt bp->args = 0; 1454268899Sbapt#endif 1455268899Sbapt } 1456234949Sbapt else if (c == '\'' || c == '"') 1457268899Sbapt { 1458234949Sbapt bp = get_literal(); 1459268899Sbapt#if defined(YYBTYACC) 1460268899Sbapt bp->args = 0; 1461268899Sbapt#endif 1462268899Sbapt } 1463234949Sbapt else 1464234949Sbapt return; 1465234949Sbapt 1466268899Sbapt if (tag) 1467268899Sbapt { 1468268899Sbapt if (bp->tag && tag != bp->tag) 1469268899Sbapt retyped_warning(bp->name); 1470268899Sbapt bp->tag = tag; 1471268899Sbapt } 1472234949Sbapt } 1473234949Sbapt} 1474234949Sbapt 1475234949Sbaptstatic void 1476234949Sbaptdeclare_start(void) 1477234949Sbapt{ 1478234949Sbapt int c; 1479234949Sbapt bucket *bp; 1480234949Sbapt 1481234949Sbapt c = nextc(); 1482234949Sbapt if (c == EOF) 1483234949Sbapt unexpected_EOF(); 1484234949Sbapt if (!isalpha(c) && c != '_' && c != '.' && c != '$') 1485234949Sbapt syntax_error(lineno, line, cptr); 1486234949Sbapt bp = get_name(); 1487234949Sbapt if (bp->class == TERM) 1488234949Sbapt terminal_start(bp->name); 1489234949Sbapt if (goal && goal != bp) 1490234949Sbapt restarted_warning(); 1491234949Sbapt goal = bp; 1492234949Sbapt} 1493234949Sbapt 1494234949Sbaptstatic void 1495234949Sbaptread_declarations(void) 1496234949Sbapt{ 1497234949Sbapt int c, k; 1498234949Sbapt 1499234949Sbapt cache_size = 256; 1500240517Sbapt cache = TMALLOC(char, cache_size); 1501234949Sbapt NO_SPACE(cache); 1502234949Sbapt 1503234949Sbapt for (;;) 1504234949Sbapt { 1505234949Sbapt c = nextc(); 1506234949Sbapt if (c == EOF) 1507234949Sbapt unexpected_EOF(); 1508234949Sbapt if (c != '%') 1509234949Sbapt syntax_error(lineno, line, cptr); 1510234949Sbapt switch (k = keyword()) 1511234949Sbapt { 1512234949Sbapt case MARK: 1513234949Sbapt return; 1514234949Sbapt 1515234949Sbapt case IDENT: 1516234949Sbapt copy_ident(); 1517234949Sbapt break; 1518234949Sbapt 1519234949Sbapt case TEXT: 1520234949Sbapt copy_text(); 1521234949Sbapt break; 1522234949Sbapt 1523234949Sbapt case UNION: 1524234949Sbapt copy_union(); 1525234949Sbapt break; 1526234949Sbapt 1527234949Sbapt case TOKEN: 1528234949Sbapt case LEFT: 1529234949Sbapt case RIGHT: 1530234949Sbapt case NONASSOC: 1531234949Sbapt declare_tokens(k); 1532234949Sbapt break; 1533234949Sbapt 1534234949Sbapt case EXPECT: 1535234949Sbapt case EXPECT_RR: 1536234949Sbapt declare_expect(k); 1537234949Sbapt break; 1538234949Sbapt 1539234949Sbapt case TYPE: 1540234949Sbapt declare_types(); 1541234949Sbapt break; 1542234949Sbapt 1543234949Sbapt case START: 1544234949Sbapt declare_start(); 1545234949Sbapt break; 1546234949Sbapt 1547234949Sbapt case PURE_PARSER: 1548234949Sbapt pure_parser = 1; 1549234949Sbapt break; 1550234949Sbapt 1551234949Sbapt case PARSE_PARAM: 1552234949Sbapt case LEX_PARAM: 1553234949Sbapt copy_param(k); 1554234949Sbapt break; 1555234949Sbapt 1556268899Sbapt case TOKEN_TABLE: 1557268899Sbapt token_table = 1; 1558268899Sbapt break; 1559268899Sbapt 1560268899Sbapt#if defined(YYBTYACC) 1561268899Sbapt case LOCATIONS: 1562268899Sbapt locations = 1; 1563268899Sbapt break; 1564268899Sbapt 1565268899Sbapt case DESTRUCTOR: 1566268899Sbapt destructor = 1; 1567268899Sbapt copy_destructor(); 1568268899Sbapt break; 1569268899Sbapt#endif 1570268899Sbapt 1571234949Sbapt case POSIX_YACC: 1572234949Sbapt /* noop for bison compatibility. byacc is already designed to be posix 1573234949Sbapt * yacc compatible. */ 1574234949Sbapt break; 1575234949Sbapt } 1576234949Sbapt } 1577234949Sbapt} 1578234949Sbapt 1579234949Sbaptstatic void 1580234949Sbaptinitialize_grammar(void) 1581234949Sbapt{ 1582234949Sbapt nitems = 4; 1583234949Sbapt maxitems = 300; 1584234949Sbapt 1585240517Sbapt pitem = TMALLOC(bucket *, maxitems); 1586234949Sbapt NO_SPACE(pitem); 1587234949Sbapt 1588234949Sbapt pitem[0] = 0; 1589234949Sbapt pitem[1] = 0; 1590234949Sbapt pitem[2] = 0; 1591234949Sbapt pitem[3] = 0; 1592234949Sbapt 1593234949Sbapt nrules = 3; 1594234949Sbapt maxrules = 100; 1595234949Sbapt 1596240517Sbapt plhs = TMALLOC(bucket *, maxrules); 1597234949Sbapt NO_SPACE(plhs); 1598234949Sbapt 1599234949Sbapt plhs[0] = 0; 1600234949Sbapt plhs[1] = 0; 1601234949Sbapt plhs[2] = 0; 1602234949Sbapt 1603240517Sbapt rprec = TMALLOC(Value_t, maxrules); 1604234949Sbapt NO_SPACE(rprec); 1605234949Sbapt 1606234949Sbapt rprec[0] = 0; 1607234949Sbapt rprec[1] = 0; 1608234949Sbapt rprec[2] = 0; 1609234949Sbapt 1610240517Sbapt rassoc = TMALLOC(Assoc_t, maxrules); 1611234949Sbapt NO_SPACE(rassoc); 1612234949Sbapt 1613234949Sbapt rassoc[0] = TOKEN; 1614234949Sbapt rassoc[1] = TOKEN; 1615234949Sbapt rassoc[2] = TOKEN; 1616234949Sbapt} 1617234949Sbapt 1618234949Sbaptstatic void 1619234949Sbaptexpand_items(void) 1620234949Sbapt{ 1621234949Sbapt maxitems += 300; 1622240517Sbapt pitem = TREALLOC(bucket *, pitem, maxitems); 1623234949Sbapt NO_SPACE(pitem); 1624234949Sbapt} 1625234949Sbapt 1626234949Sbaptstatic void 1627234949Sbaptexpand_rules(void) 1628234949Sbapt{ 1629234949Sbapt maxrules += 100; 1630234949Sbapt 1631240517Sbapt plhs = TREALLOC(bucket *, plhs, maxrules); 1632234949Sbapt NO_SPACE(plhs); 1633234949Sbapt 1634240517Sbapt rprec = TREALLOC(Value_t, rprec, maxrules); 1635234949Sbapt NO_SPACE(rprec); 1636234949Sbapt 1637240517Sbapt rassoc = TREALLOC(Assoc_t, rassoc, maxrules); 1638234949Sbapt NO_SPACE(rassoc); 1639234949Sbapt} 1640234949Sbapt 1641268899Sbapt/* set immediately prior to where copy_args() could be called, and incremented by 1642268899Sbapt the various routines that will rescan the argument list as appropriate */ 1643268899Sbaptstatic int rescan_lineno; 1644268899Sbapt#if defined(YYBTYACC) 1645268899Sbapt 1646268899Sbaptstatic char * 1647268899Sbaptcopy_args(int *alen) 1648268899Sbapt{ 1649268899Sbapt struct mstring *s = msnew(); 1650268899Sbapt int depth = 0, len = 1; 1651268899Sbapt char c, quote = 0; 1652268899Sbapt int a_lineno = lineno; 1653268899Sbapt char *a_line = dup_line(); 1654268899Sbapt char *a_cptr = a_line + (cptr - line - 1); 1655268899Sbapt 1656268899Sbapt while ((c = *cptr++) != R_PAREN || depth || quote) 1657268899Sbapt { 1658268899Sbapt if (c == ',' && !quote && !depth) 1659268899Sbapt { 1660268899Sbapt len++; 1661268899Sbapt mputc(s, 0); 1662268899Sbapt continue; 1663268899Sbapt } 1664268899Sbapt mputc(s, c); 1665268899Sbapt if (c == '\n') 1666268899Sbapt { 1667268899Sbapt get_line(); 1668268899Sbapt if (!line) 1669268899Sbapt { 1670268899Sbapt if (quote) 1671268899Sbapt unterminated_string(a_lineno, a_line, a_cptr); 1672268899Sbapt else 1673268899Sbapt unterminated_arglist(a_lineno, a_line, a_cptr); 1674268899Sbapt } 1675268899Sbapt } 1676268899Sbapt else if (quote) 1677268899Sbapt { 1678268899Sbapt if (c == quote) 1679268899Sbapt quote = 0; 1680268899Sbapt else if (c == '\\') 1681268899Sbapt { 1682268899Sbapt if (*cptr != '\n') 1683268899Sbapt mputc(s, *cptr++); 1684268899Sbapt } 1685268899Sbapt } 1686268899Sbapt else 1687268899Sbapt { 1688268899Sbapt if (c == L_PAREN) 1689268899Sbapt depth++; 1690268899Sbapt else if (c == R_PAREN) 1691268899Sbapt depth--; 1692268899Sbapt else if (c == '\"' || c == '\'') 1693268899Sbapt quote = c; 1694268899Sbapt } 1695268899Sbapt } 1696268899Sbapt if (alen) 1697268899Sbapt *alen = len; 1698268899Sbapt FREE(a_line); 1699268899Sbapt return msdone(s); 1700268899Sbapt} 1701268899Sbapt 1702268899Sbaptstatic char * 1703268899Sbaptparse_id(char *p, char **save) 1704268899Sbapt{ 1705268899Sbapt char *b; 1706268899Sbapt 1707268899Sbapt while (isspace(*p)) 1708268899Sbapt if (*p++ == '\n') 1709268899Sbapt rescan_lineno++; 1710268899Sbapt if (!isalpha(*p) && *p != '_') 1711268899Sbapt return NULL; 1712268899Sbapt b = p; 1713268899Sbapt while (isalnum(*p) || *p == '_' || *p == '$') 1714268899Sbapt p++; 1715268899Sbapt if (save) 1716268899Sbapt { 1717268899Sbapt *save = cache_tag(b, (size_t) (p - b)); 1718268899Sbapt } 1719268899Sbapt return p; 1720268899Sbapt} 1721268899Sbapt 1722268899Sbaptstatic char * 1723268899Sbaptparse_int(char *p, int *save) 1724268899Sbapt{ 1725268899Sbapt int neg = 0, val = 0; 1726268899Sbapt 1727268899Sbapt while (isspace(*p)) 1728268899Sbapt if (*p++ == '\n') 1729268899Sbapt rescan_lineno++; 1730268899Sbapt if (*p == '-') 1731268899Sbapt { 1732268899Sbapt neg = 1; 1733268899Sbapt p++; 1734268899Sbapt } 1735268899Sbapt if (!isdigit(*p)) 1736268899Sbapt return NULL; 1737268899Sbapt while (isdigit(*p)) 1738268899Sbapt val = val * 10 + *p++ - '0'; 1739268899Sbapt if (neg) 1740268899Sbapt val = -val; 1741268899Sbapt if (save) 1742268899Sbapt *save = val; 1743268899Sbapt return p; 1744268899Sbapt} 1745268899Sbapt 1746234949Sbaptstatic void 1747268899Sbaptparse_arginfo(bucket *a, char *args, int argslen) 1748268899Sbapt{ 1749268899Sbapt char *p = args, *tmp; 1750268899Sbapt int i, redec = 0; 1751268899Sbapt 1752268899Sbapt if (a->args > 0) 1753268899Sbapt { 1754268899Sbapt if (a->args != argslen) 1755268899Sbapt arg_number_disagree_warning(rescan_lineno, a->name); 1756268899Sbapt redec = 1; 1757268899Sbapt } 1758268899Sbapt else 1759268899Sbapt { 1760268899Sbapt if ((a->args = argslen) == 0) 1761268899Sbapt return; 1762268899Sbapt a->argnames = TMALLOC(char *, argslen); 1763268899Sbapt NO_SPACE(a->argnames); 1764268899Sbapt a->argtags = TMALLOC(char *, argslen); 1765268899Sbapt NO_SPACE(a->argtags); 1766268899Sbapt } 1767268899Sbapt if (!args) 1768268899Sbapt return; 1769268899Sbapt for (i = 0; i < argslen; i++) 1770268899Sbapt { 1771268899Sbapt while (isspace(*p)) 1772268899Sbapt if (*p++ == '\n') 1773268899Sbapt rescan_lineno++; 1774268899Sbapt if (*p++ != '$') 1775268899Sbapt bad_formals(); 1776268899Sbapt while (isspace(*p)) 1777268899Sbapt if (*p++ == '\n') 1778268899Sbapt rescan_lineno++; 1779268899Sbapt if (*p == '<') 1780268899Sbapt { 1781268899Sbapt havetags = 1; 1782268899Sbapt if (!(p = parse_id(p + 1, &tmp))) 1783268899Sbapt bad_formals(); 1784268899Sbapt while (isspace(*p)) 1785268899Sbapt if (*p++ == '\n') 1786268899Sbapt rescan_lineno++; 1787268899Sbapt if (*p++ != '>') 1788268899Sbapt bad_formals(); 1789268899Sbapt if (redec) 1790268899Sbapt { 1791268899Sbapt if (a->argtags[i] != tmp) 1792268899Sbapt arg_type_disagree_warning(rescan_lineno, i + 1, a->name); 1793268899Sbapt } 1794268899Sbapt else 1795268899Sbapt a->argtags[i] = tmp; 1796268899Sbapt } 1797268899Sbapt else if (!redec) 1798268899Sbapt a->argtags[i] = NULL; 1799268899Sbapt if (!(p = parse_id(p, &a->argnames[i]))) 1800268899Sbapt bad_formals(); 1801268899Sbapt while (isspace(*p)) 1802268899Sbapt if (*p++ == '\n') 1803268899Sbapt rescan_lineno++; 1804268899Sbapt if (*p++) 1805268899Sbapt bad_formals(); 1806268899Sbapt } 1807268899Sbapt free(args); 1808268899Sbapt} 1809268899Sbapt 1810268899Sbaptstatic char * 1811268899Sbaptcompile_arg(char **theptr, char *yyvaltag) 1812268899Sbapt{ 1813268899Sbapt char *p = *theptr; 1814268899Sbapt struct mstring *c = msnew(); 1815268899Sbapt int i, j, n; 1816268899Sbapt Value_t *offsets = NULL, maxoffset; 1817268899Sbapt bucket **rhs; 1818268899Sbapt 1819268899Sbapt maxoffset = 0; 1820268899Sbapt n = 0; 1821268899Sbapt for (i = nitems - 1; pitem[i]; --i) 1822268899Sbapt { 1823268899Sbapt n++; 1824268899Sbapt if (pitem[i]->class != ARGUMENT) 1825268899Sbapt maxoffset++; 1826268899Sbapt } 1827268899Sbapt if (maxoffset > 0) 1828268899Sbapt { 1829268899Sbapt offsets = TMALLOC(Value_t, maxoffset + 1); 1830268899Sbapt NO_SPACE(offsets); 1831272955Srodrigc 1832272955Srodrigc for (j = 0, i++; i < nitems; i++) 1833272955Srodrigc if (pitem[i]->class != ARGUMENT) 1834272955Srodrigc offsets[++j] = (Value_t) (i - nitems + 1); 1835268899Sbapt } 1836268899Sbapt rhs = pitem + nitems - 1; 1837268899Sbapt 1838268899Sbapt if (yyvaltag) 1839268899Sbapt msprintf(c, "yyval.%s = ", yyvaltag); 1840268899Sbapt else 1841268899Sbapt msprintf(c, "yyval = "); 1842268899Sbapt while (*p) 1843268899Sbapt { 1844268899Sbapt if (*p == '$') 1845268899Sbapt { 1846268899Sbapt char *tag = NULL; 1847268899Sbapt if (*++p == '<') 1848268899Sbapt if (!(p = parse_id(++p, &tag)) || *p++ != '>') 1849268899Sbapt illegal_tag(rescan_lineno, NULL, NULL); 1850268899Sbapt if (isdigit(*p) || *p == '-') 1851268899Sbapt { 1852268899Sbapt int val; 1853268899Sbapt if (!(p = parse_int(p, &val))) 1854268899Sbapt dollar_error(rescan_lineno, NULL, NULL); 1855268899Sbapt if (val <= 0) 1856268899Sbapt i = val - n; 1857268899Sbapt else if (val > maxoffset) 1858268899Sbapt { 1859268899Sbapt dollar_warning(rescan_lineno, val); 1860268899Sbapt i = val - maxoffset; 1861268899Sbapt } 1862272955Srodrigc else if (maxoffset > 0) 1863268899Sbapt { 1864268899Sbapt i = offsets[val]; 1865268899Sbapt if (!tag && !(tag = rhs[i]->tag) && havetags) 1866268899Sbapt untyped_rhs(val, rhs[i]->name); 1867268899Sbapt } 1868268899Sbapt msprintf(c, "yystack.l_mark[%d]", i); 1869268899Sbapt if (tag) 1870268899Sbapt msprintf(c, ".%s", tag); 1871268899Sbapt else if (havetags) 1872268899Sbapt unknown_rhs(val); 1873268899Sbapt } 1874268899Sbapt else if (isalpha(*p) || *p == '_') 1875268899Sbapt { 1876268899Sbapt char *arg; 1877268899Sbapt if (!(p = parse_id(p, &arg))) 1878268899Sbapt dollar_error(rescan_lineno, NULL, NULL); 1879268899Sbapt for (i = plhs[nrules]->args - 1; i >= 0; i--) 1880268899Sbapt if (arg == plhs[nrules]->argnames[i]) 1881268899Sbapt break; 1882268899Sbapt if (i < 0) 1883268899Sbapt unknown_arg_warning(rescan_lineno, "$", arg, NULL, NULL); 1884268899Sbapt else if (!tag) 1885268899Sbapt tag = plhs[nrules]->argtags[i]; 1886268899Sbapt msprintf(c, "yystack.l_mark[%d]", i - plhs[nrules]->args + 1 1887268899Sbapt - n); 1888268899Sbapt if (tag) 1889268899Sbapt msprintf(c, ".%s", tag); 1890268899Sbapt else if (havetags) 1891268899Sbapt untyped_arg_warning(rescan_lineno, "$", arg); 1892268899Sbapt } 1893268899Sbapt else 1894268899Sbapt dollar_error(rescan_lineno, NULL, NULL); 1895268899Sbapt } 1896268899Sbapt else if (*p == '@') 1897268899Sbapt { 1898268899Sbapt at_error(rescan_lineno, NULL, NULL); 1899268899Sbapt } 1900268899Sbapt else 1901268899Sbapt { 1902268899Sbapt if (*p == '\n') 1903268899Sbapt rescan_lineno++; 1904268899Sbapt mputc(c, *p++); 1905268899Sbapt } 1906268899Sbapt } 1907268899Sbapt *theptr = p; 1908268899Sbapt if (maxoffset > 0) 1909268899Sbapt FREE(offsets); 1910268899Sbapt return msdone(c); 1911268899Sbapt} 1912268899Sbapt 1913268899Sbapt#define ARG_CACHE_SIZE 1024 1914268899Sbaptstatic struct arg_cache 1915268899Sbapt{ 1916268899Sbapt struct arg_cache *next; 1917268899Sbapt char *code; 1918268899Sbapt int rule; 1919268899Sbapt} 1920268899Sbapt *arg_cache[ARG_CACHE_SIZE]; 1921268899Sbapt 1922268899Sbaptstatic int 1923268899Sbaptlookup_arg_cache(char *code) 1924268899Sbapt{ 1925268899Sbapt struct arg_cache *entry; 1926268899Sbapt 1927268899Sbapt entry = arg_cache[strnshash(code) % ARG_CACHE_SIZE]; 1928268899Sbapt while (entry) 1929268899Sbapt { 1930268899Sbapt if (!strnscmp(entry->code, code)) 1931268899Sbapt return entry->rule; 1932268899Sbapt entry = entry->next; 1933268899Sbapt } 1934268899Sbapt return -1; 1935268899Sbapt} 1936268899Sbapt 1937268899Sbaptstatic void 1938268899Sbaptinsert_arg_cache(char *code, int rule) 1939268899Sbapt{ 1940268899Sbapt struct arg_cache *entry = NEW(struct arg_cache); 1941268899Sbapt int i; 1942268899Sbapt 1943268899Sbapt NO_SPACE(entry); 1944268899Sbapt i = strnshash(code) % ARG_CACHE_SIZE; 1945268899Sbapt entry->code = code; 1946268899Sbapt entry->rule = rule; 1947268899Sbapt entry->next = arg_cache[i]; 1948268899Sbapt arg_cache[i] = entry; 1949268899Sbapt} 1950268899Sbapt 1951268899Sbaptstatic void 1952268899Sbaptclean_arg_cache(void) 1953268899Sbapt{ 1954268899Sbapt struct arg_cache *e, *t; 1955268899Sbapt int i; 1956268899Sbapt 1957268899Sbapt for (i = 0; i < ARG_CACHE_SIZE; i++) 1958268899Sbapt { 1959268899Sbapt for (e = arg_cache[i]; (t = e); e = e->next, FREE(t)) 1960268899Sbapt free(e->code); 1961268899Sbapt arg_cache[i] = NULL; 1962268899Sbapt } 1963268899Sbapt} 1964268899Sbapt#endif 1965268899Sbapt 1966268899Sbaptstatic void 1967234949Sbaptadvance_to_start(void) 1968234949Sbapt{ 1969234949Sbapt int c; 1970234949Sbapt bucket *bp; 1971234949Sbapt char *s_cptr; 1972234949Sbapt int s_lineno; 1973268899Sbapt#if defined(YYBTYACC) 1974268899Sbapt char *args = NULL; 1975268899Sbapt int argslen = 0; 1976268899Sbapt#endif 1977234949Sbapt 1978234949Sbapt for (;;) 1979234949Sbapt { 1980234949Sbapt c = nextc(); 1981234949Sbapt if (c != '%') 1982234949Sbapt break; 1983234949Sbapt s_cptr = cptr; 1984234949Sbapt switch (keyword()) 1985234949Sbapt { 1986234949Sbapt case MARK: 1987234949Sbapt no_grammar(); 1988234949Sbapt 1989234949Sbapt case TEXT: 1990234949Sbapt copy_text(); 1991234949Sbapt break; 1992234949Sbapt 1993234949Sbapt case START: 1994234949Sbapt declare_start(); 1995234949Sbapt break; 1996234949Sbapt 1997234949Sbapt default: 1998234949Sbapt syntax_error(lineno, line, s_cptr); 1999234949Sbapt } 2000234949Sbapt } 2001234949Sbapt 2002234949Sbapt c = nextc(); 2003234949Sbapt if (!isalpha(c) && c != '_' && c != '.' && c != '_') 2004234949Sbapt syntax_error(lineno, line, cptr); 2005234949Sbapt bp = get_name(); 2006234949Sbapt if (goal == 0) 2007234949Sbapt { 2008234949Sbapt if (bp->class == TERM) 2009234949Sbapt terminal_start(bp->name); 2010234949Sbapt goal = bp; 2011234949Sbapt } 2012234949Sbapt 2013234949Sbapt s_lineno = lineno; 2014234949Sbapt c = nextc(); 2015234949Sbapt if (c == EOF) 2016234949Sbapt unexpected_EOF(); 2017268899Sbapt rescan_lineno = lineno; /* line# for possible inherited args rescan */ 2018268899Sbapt#if defined(YYBTYACC) 2019268899Sbapt if (c == L_PAREN) 2020268899Sbapt { 2021268899Sbapt ++cptr; 2022268899Sbapt args = copy_args(&argslen); 2023268899Sbapt NO_SPACE(args); 2024268899Sbapt c = nextc(); 2025268899Sbapt } 2026268899Sbapt#endif 2027234949Sbapt if (c != ':') 2028234949Sbapt syntax_error(lineno, line, cptr); 2029234949Sbapt start_rule(bp, s_lineno); 2030268899Sbapt#if defined(YYBTYACC) 2031268899Sbapt parse_arginfo(bp, args, argslen); 2032268899Sbapt#endif 2033234949Sbapt ++cptr; 2034234949Sbapt} 2035234949Sbapt 2036234949Sbaptstatic void 2037234949Sbaptstart_rule(bucket *bp, int s_lineno) 2038234949Sbapt{ 2039234949Sbapt if (bp->class == TERM) 2040234949Sbapt terminal_lhs(s_lineno); 2041234949Sbapt bp->class = NONTERM; 2042268899Sbapt if (!bp->index) 2043268899Sbapt bp->index = nrules; 2044234949Sbapt if (nrules >= maxrules) 2045234949Sbapt expand_rules(); 2046234949Sbapt plhs[nrules] = bp; 2047234949Sbapt rprec[nrules] = UNDEFINED; 2048234949Sbapt rassoc[nrules] = TOKEN; 2049234949Sbapt} 2050234949Sbapt 2051234949Sbaptstatic void 2052234949Sbaptend_rule(void) 2053234949Sbapt{ 2054234949Sbapt int i; 2055234949Sbapt 2056234949Sbapt if (!last_was_action && plhs[nrules]->tag) 2057234949Sbapt { 2058234949Sbapt if (pitem[nitems - 1]) 2059234949Sbapt { 2060234949Sbapt for (i = nitems - 1; (i > 0) && pitem[i]; --i) 2061234949Sbapt continue; 2062234949Sbapt if (pitem[i + 1] == 0 || pitem[i + 1]->tag != plhs[nrules]->tag) 2063234949Sbapt default_action_warning(); 2064234949Sbapt } 2065234949Sbapt else 2066234949Sbapt { 2067234949Sbapt default_action_warning(); 2068234949Sbapt } 2069234949Sbapt } 2070234949Sbapt 2071234949Sbapt last_was_action = 0; 2072234949Sbapt if (nitems >= maxitems) 2073234949Sbapt expand_items(); 2074234949Sbapt pitem[nitems] = 0; 2075234949Sbapt ++nitems; 2076234949Sbapt ++nrules; 2077234949Sbapt} 2078234949Sbapt 2079234949Sbaptstatic void 2080234949Sbaptinsert_empty_rule(void) 2081234949Sbapt{ 2082234949Sbapt bucket *bp, **bpp; 2083234949Sbapt 2084234949Sbapt assert(cache); 2085234949Sbapt sprintf(cache, "$$%d", ++gensym); 2086234949Sbapt bp = make_bucket(cache); 2087234949Sbapt last_symbol->next = bp; 2088234949Sbapt last_symbol = bp; 2089234949Sbapt bp->tag = plhs[nrules]->tag; 2090268899Sbapt bp->class = ACTION; 2091268899Sbapt#if defined(YYBTYACC) 2092268899Sbapt bp->args = 0; 2093268899Sbapt#endif 2094234949Sbapt 2095268899Sbapt nitems = (Value_t) (nitems + 2); 2096268899Sbapt if (nitems > maxitems) 2097234949Sbapt expand_items(); 2098234949Sbapt bpp = pitem + nitems - 1; 2099234949Sbapt *bpp-- = bp; 2100234949Sbapt while ((bpp[0] = bpp[-1]) != 0) 2101234949Sbapt --bpp; 2102234949Sbapt 2103234949Sbapt if (++nrules >= maxrules) 2104234949Sbapt expand_rules(); 2105234949Sbapt plhs[nrules] = plhs[nrules - 1]; 2106234949Sbapt plhs[nrules - 1] = bp; 2107234949Sbapt rprec[nrules] = rprec[nrules - 1]; 2108234949Sbapt rprec[nrules - 1] = 0; 2109234949Sbapt rassoc[nrules] = rassoc[nrules - 1]; 2110234949Sbapt rassoc[nrules - 1] = TOKEN; 2111234949Sbapt} 2112234949Sbapt 2113268899Sbapt#if defined(YYBTYACC) 2114268899Sbaptstatic char * 2115268899Sbaptinsert_arg_rule(char *arg, char *tag) 2116268899Sbapt{ 2117268899Sbapt int line_number = rescan_lineno; 2118268899Sbapt char *code = compile_arg(&arg, tag); 2119268899Sbapt int rule = lookup_arg_cache(code); 2120268899Sbapt FILE *f = action_file; 2121268899Sbapt 2122268899Sbapt if (rule < 0) 2123268899Sbapt { 2124268899Sbapt rule = nrules; 2125268899Sbapt insert_arg_cache(code, rule); 2126268899Sbapt fprintf(f, "case %d:\n", rule - 2); 2127268899Sbapt if (!lflag) 2128268899Sbapt fprintf(f, line_format, line_number, input_file_name); 2129268899Sbapt fprintf(f, "%s;\n", code); 2130268899Sbapt fprintf(f, "break;\n"); 2131268899Sbapt insert_empty_rule(); 2132268899Sbapt plhs[rule]->tag = tag; 2133268899Sbapt plhs[rule]->class = ARGUMENT; 2134268899Sbapt } 2135268899Sbapt else 2136268899Sbapt { 2137268899Sbapt if (++nitems > maxitems) 2138268899Sbapt expand_items(); 2139268899Sbapt pitem[nitems - 1] = plhs[rule]; 2140268899Sbapt free(code); 2141268899Sbapt } 2142268899Sbapt return arg + 1; 2143268899Sbapt} 2144268899Sbapt#endif 2145268899Sbapt 2146234949Sbaptstatic void 2147234949Sbaptadd_symbol(void) 2148234949Sbapt{ 2149234949Sbapt int c; 2150234949Sbapt bucket *bp; 2151234949Sbapt int s_lineno = lineno; 2152268899Sbapt#if defined(YYBTYACC) 2153268899Sbapt char *args = NULL; 2154268899Sbapt int argslen = 0; 2155268899Sbapt#endif 2156234949Sbapt 2157234949Sbapt c = *cptr; 2158234949Sbapt if (c == '\'' || c == '"') 2159234949Sbapt bp = get_literal(); 2160234949Sbapt else 2161234949Sbapt bp = get_name(); 2162234949Sbapt 2163234949Sbapt c = nextc(); 2164268899Sbapt rescan_lineno = lineno; /* line# for possible inherited args rescan */ 2165268899Sbapt#if defined(YYBTYACC) 2166268899Sbapt if (c == L_PAREN) 2167268899Sbapt { 2168268899Sbapt ++cptr; 2169268899Sbapt args = copy_args(&argslen); 2170268899Sbapt NO_SPACE(args); 2171268899Sbapt c = nextc(); 2172268899Sbapt } 2173268899Sbapt#endif 2174234949Sbapt if (c == ':') 2175234949Sbapt { 2176234949Sbapt end_rule(); 2177234949Sbapt start_rule(bp, s_lineno); 2178268899Sbapt#if defined(YYBTYACC) 2179268899Sbapt parse_arginfo(bp, args, argslen); 2180268899Sbapt#endif 2181234949Sbapt ++cptr; 2182234949Sbapt return; 2183234949Sbapt } 2184234949Sbapt 2185234949Sbapt if (last_was_action) 2186234949Sbapt insert_empty_rule(); 2187234949Sbapt last_was_action = 0; 2188234949Sbapt 2189268899Sbapt#if defined(YYBTYACC) 2190268899Sbapt if (bp->args < 0) 2191268899Sbapt bp->args = argslen; 2192268899Sbapt if (argslen == 0 && bp->args > 0 && pitem[nitems - 1] == NULL) 2193268899Sbapt { 2194268899Sbapt int i; 2195268899Sbapt if (plhs[nrules]->args != bp->args) 2196268899Sbapt wrong_number_args_warning("default ", bp->name); 2197268899Sbapt for (i = bp->args - 1; i >= 0; i--) 2198268899Sbapt if (plhs[nrules]->argtags[i] != bp->argtags[i]) 2199268899Sbapt wrong_type_for_arg_warning(i + 1, bp->name); 2200268899Sbapt } 2201268899Sbapt else if (bp->args != argslen) 2202268899Sbapt wrong_number_args_warning("", bp->name); 2203268899Sbapt if (bp->args > 0 && argslen > 0) 2204268899Sbapt { 2205268899Sbapt char *ap; 2206268899Sbapt int i; 2207268899Sbapt for (ap = args, i = 0; i < argslen; i++) 2208268899Sbapt ap = insert_arg_rule(ap, bp->argtags[i]); 2209268899Sbapt free(args); 2210268899Sbapt } 2211268899Sbapt#endif /* defined(YYBTYACC) */ 2212268899Sbapt 2213234949Sbapt if (++nitems > maxitems) 2214234949Sbapt expand_items(); 2215234949Sbapt pitem[nitems - 1] = bp; 2216234949Sbapt} 2217234949Sbapt 2218234949Sbaptstatic void 2219234949Sbaptcopy_action(void) 2220234949Sbapt{ 2221234949Sbapt int c; 2222268899Sbapt int i, j, n; 2223234949Sbapt int depth; 2224268899Sbapt#if defined(YYBTYACC) 2225268899Sbapt int trialaction = 0; 2226268899Sbapt int haveyyval = 0; 2227268899Sbapt#endif 2228234949Sbapt char *tag; 2229234949Sbapt FILE *f = action_file; 2230234949Sbapt int a_lineno = lineno; 2231234949Sbapt char *a_line = dup_line(); 2232234949Sbapt char *a_cptr = a_line + (cptr - line); 2233268899Sbapt Value_t *offsets = NULL, maxoffset; 2234268899Sbapt bucket **rhs; 2235234949Sbapt 2236234949Sbapt if (last_was_action) 2237234949Sbapt insert_empty_rule(); 2238234949Sbapt last_was_action = 1; 2239234949Sbapt 2240234949Sbapt fprintf(f, "case %d:\n", nrules - 2); 2241268899Sbapt#if defined(YYBTYACC) 2242268899Sbapt if (backtrack) 2243268899Sbapt { 2244268899Sbapt if (*cptr != L_BRAC) 2245268899Sbapt fprintf(f, " if (!yytrial)\n"); 2246268899Sbapt else 2247268899Sbapt trialaction = 1; 2248268899Sbapt } 2249268899Sbapt#endif 2250234949Sbapt if (!lflag) 2251234949Sbapt fprintf(f, line_format, lineno, input_file_name); 2252234949Sbapt if (*cptr == '=') 2253234949Sbapt ++cptr; 2254234949Sbapt 2255234949Sbapt /* avoid putting curly-braces in first column, to ease editing */ 2256234949Sbapt if (*after_blanks(cptr) == L_CURL) 2257234949Sbapt { 2258234949Sbapt putc('\t', f); 2259234949Sbapt cptr = after_blanks(cptr); 2260234949Sbapt } 2261234949Sbapt 2262268899Sbapt maxoffset = 0; 2263234949Sbapt n = 0; 2264234949Sbapt for (i = nitems - 1; pitem[i]; --i) 2265268899Sbapt { 2266234949Sbapt ++n; 2267268899Sbapt if (pitem[i]->class != ARGUMENT) 2268268899Sbapt maxoffset++; 2269268899Sbapt } 2270268899Sbapt if (maxoffset > 0) 2271268899Sbapt { 2272268899Sbapt offsets = TMALLOC(Value_t, maxoffset + 1); 2273268899Sbapt NO_SPACE(offsets); 2274272955Srodrigc 2275272955Srodrigc for (j = 0, i++; i < nitems; i++) 2276268899Sbapt { 2277272955Srodrigc if (pitem[i]->class != ARGUMENT) 2278272955Srodrigc { 2279272955Srodrigc offsets[++j] = (Value_t) (i - nitems + 1); 2280272955Srodrigc } 2281268899Sbapt } 2282268899Sbapt } 2283268899Sbapt rhs = pitem + nitems - 1; 2284234949Sbapt 2285234949Sbapt depth = 0; 2286234949Sbapt loop: 2287234949Sbapt c = *cptr; 2288234949Sbapt if (c == '$') 2289234949Sbapt { 2290234949Sbapt if (cptr[1] == '<') 2291234949Sbapt { 2292234949Sbapt int d_lineno = lineno; 2293234949Sbapt char *d_line = dup_line(); 2294234949Sbapt char *d_cptr = d_line + (cptr - line); 2295234949Sbapt 2296234949Sbapt ++cptr; 2297234949Sbapt tag = get_tag(); 2298234949Sbapt c = *cptr; 2299234949Sbapt if (c == '$') 2300234949Sbapt { 2301234949Sbapt fprintf(f, "yyval.%s", tag); 2302234949Sbapt ++cptr; 2303234949Sbapt FREE(d_line); 2304234949Sbapt goto loop; 2305234949Sbapt } 2306234949Sbapt else if (isdigit(c)) 2307234949Sbapt { 2308234949Sbapt i = get_number(); 2309268899Sbapt if (i == 0) 2310268899Sbapt fprintf(f, "yystack.l_mark[%d].%s", -n, tag); 2311268899Sbapt else if (i > maxoffset) 2312268899Sbapt { 2313234949Sbapt dollar_warning(d_lineno, i); 2314268899Sbapt fprintf(f, "yystack.l_mark[%d].%s", i - maxoffset, tag); 2315268899Sbapt } 2316268899Sbapt else if (offsets) 2317268899Sbapt fprintf(f, "yystack.l_mark[%d].%s", offsets[i], tag); 2318234949Sbapt FREE(d_line); 2319234949Sbapt goto loop; 2320234949Sbapt } 2321234949Sbapt else if (c == '-' && isdigit(UCH(cptr[1]))) 2322234949Sbapt { 2323234949Sbapt ++cptr; 2324234949Sbapt i = -get_number() - n; 2325234949Sbapt fprintf(f, "yystack.l_mark[%d].%s", i, tag); 2326234949Sbapt FREE(d_line); 2327234949Sbapt goto loop; 2328234949Sbapt } 2329268899Sbapt#if defined(YYBTYACC) 2330268899Sbapt else if (isalpha(c) || c == '_') 2331268899Sbapt { 2332268899Sbapt char *arg = scan_id(); 2333268899Sbapt for (i = plhs[nrules]->args - 1; i >= 0; i--) 2334268899Sbapt if (arg == plhs[nrules]->argnames[i]) 2335268899Sbapt break; 2336268899Sbapt if (i < 0) 2337268899Sbapt unknown_arg_warning(d_lineno, "$", arg, d_line, d_cptr); 2338268899Sbapt fprintf(f, "yystack.l_mark[%d].%s", i - plhs[nrules]->args + 2339268899Sbapt 1 - n, tag); 2340268899Sbapt FREE(d_line); 2341268899Sbapt goto loop; 2342268899Sbapt } 2343268899Sbapt#endif 2344234949Sbapt else 2345234949Sbapt dollar_error(d_lineno, d_line, d_cptr); 2346234949Sbapt } 2347234949Sbapt else if (cptr[1] == '$') 2348234949Sbapt { 2349268899Sbapt if (havetags) 2350234949Sbapt { 2351234949Sbapt tag = plhs[nrules]->tag; 2352234949Sbapt if (tag == 0) 2353234949Sbapt untyped_lhs(); 2354234949Sbapt fprintf(f, "yyval.%s", tag); 2355234949Sbapt } 2356234949Sbapt else 2357234949Sbapt fprintf(f, "yyval"); 2358234949Sbapt cptr += 2; 2359268899Sbapt#if defined(YYBTYACC) 2360268899Sbapt haveyyval = 1; 2361268899Sbapt#endif 2362234949Sbapt goto loop; 2363234949Sbapt } 2364234949Sbapt else if (isdigit(UCH(cptr[1]))) 2365234949Sbapt { 2366234949Sbapt ++cptr; 2367234949Sbapt i = get_number(); 2368272955Srodrigc if (havetags && offsets) 2369234949Sbapt { 2370268899Sbapt if (i <= 0 || i > maxoffset) 2371234949Sbapt unknown_rhs(i); 2372268899Sbapt tag = rhs[offsets[i]]->tag; 2373234949Sbapt if (tag == 0) 2374268899Sbapt untyped_rhs(i, rhs[offsets[i]]->name); 2375268899Sbapt fprintf(f, "yystack.l_mark[%d].%s", offsets[i], tag); 2376234949Sbapt } 2377234949Sbapt else 2378234949Sbapt { 2379268899Sbapt if (i == 0) 2380268899Sbapt fprintf(f, "yystack.l_mark[%d]", -n); 2381268899Sbapt else if (i > maxoffset) 2382268899Sbapt { 2383234949Sbapt dollar_warning(lineno, i); 2384268899Sbapt fprintf(f, "yystack.l_mark[%d]", i - maxoffset); 2385268899Sbapt } 2386268899Sbapt else if (offsets) 2387268899Sbapt fprintf(f, "yystack.l_mark[%d]", offsets[i]); 2388234949Sbapt } 2389234949Sbapt goto loop; 2390234949Sbapt } 2391234949Sbapt else if (cptr[1] == '-') 2392234949Sbapt { 2393234949Sbapt cptr += 2; 2394234949Sbapt i = get_number(); 2395268899Sbapt if (havetags) 2396234949Sbapt unknown_rhs(-i); 2397234949Sbapt fprintf(f, "yystack.l_mark[%d]", -i - n); 2398234949Sbapt goto loop; 2399234949Sbapt } 2400268899Sbapt#if defined(YYBTYACC) 2401268899Sbapt else if (isalpha(cptr[1]) || cptr[1] == '_') 2402268899Sbapt { 2403268899Sbapt char *arg; 2404268899Sbapt ++cptr; 2405268899Sbapt arg = scan_id(); 2406268899Sbapt for (i = plhs[nrules]->args - 1; i >= 0; i--) 2407268899Sbapt if (arg == plhs[nrules]->argnames[i]) 2408268899Sbapt break; 2409268899Sbapt if (i < 0) 2410268899Sbapt unknown_arg_warning(lineno, "$", arg, line, cptr); 2411268899Sbapt tag = (i < 0 ? NULL : plhs[nrules]->argtags[i]); 2412268899Sbapt fprintf(f, "yystack.l_mark[%d]", i - plhs[nrules]->args + 1 - n); 2413268899Sbapt if (tag) 2414268899Sbapt fprintf(f, ".%s", tag); 2415268899Sbapt else if (havetags) 2416268899Sbapt untyped_arg_warning(lineno, "$", arg); 2417268899Sbapt goto loop; 2418268899Sbapt } 2419268899Sbapt#endif 2420234949Sbapt } 2421268899Sbapt#if defined(YYBTYACC) 2422268899Sbapt if (c == '@') 2423268899Sbapt { 2424268899Sbapt if (!locations) 2425268899Sbapt { 2426268899Sbapt int l_lineno = lineno; 2427268899Sbapt char *l_line = dup_line(); 2428268899Sbapt char *l_cptr = l_line + (cptr - line); 2429268899Sbapt syntax_error(l_lineno, l_line, l_cptr); 2430268899Sbapt } 2431268899Sbapt if (cptr[1] == '$') 2432268899Sbapt { 2433268899Sbapt fprintf(f, "yyloc"); 2434268899Sbapt cptr += 2; 2435268899Sbapt goto loop; 2436268899Sbapt } 2437268899Sbapt else if (isdigit(UCH(cptr[1]))) 2438268899Sbapt { 2439268899Sbapt ++cptr; 2440268899Sbapt i = get_number(); 2441268899Sbapt if (i == 0) 2442268899Sbapt fprintf(f, "yystack.p_mark[%d]", -n); 2443268899Sbapt else if (i > maxoffset) 2444268899Sbapt { 2445268899Sbapt at_warning(lineno, i); 2446268899Sbapt fprintf(f, "yystack.p_mark[%d]", i - maxoffset); 2447268899Sbapt } 2448268899Sbapt else if (offsets) 2449268899Sbapt fprintf(f, "yystack.p_mark[%d]", offsets[i]); 2450268899Sbapt goto loop; 2451268899Sbapt } 2452268899Sbapt } 2453268899Sbapt#endif 2454234949Sbapt if (isalpha(c) || c == '_' || c == '$') 2455234949Sbapt { 2456234949Sbapt do 2457234949Sbapt { 2458234949Sbapt putc(c, f); 2459234949Sbapt c = *++cptr; 2460234949Sbapt } 2461234949Sbapt while (isalnum(c) || c == '_' || c == '$'); 2462234949Sbapt goto loop; 2463234949Sbapt } 2464268899Sbapt ++cptr; 2465268899Sbapt#if defined(YYBTYACC) 2466268899Sbapt if (backtrack) 2467268899Sbapt { 2468268899Sbapt if (trialaction && c == L_BRAC && depth == 0) 2469268899Sbapt { 2470268899Sbapt ++depth; 2471268899Sbapt putc(L_CURL, f); 2472268899Sbapt goto loop; 2473268899Sbapt } 2474268899Sbapt if (trialaction && c == R_BRAC && depth == 1) 2475268899Sbapt { 2476268899Sbapt --depth; 2477268899Sbapt putc(R_CURL, f); 2478268899Sbapt c = nextc(); 2479268899Sbapt if (c == L_BRAC && !haveyyval) 2480268899Sbapt { 2481268899Sbapt goto loop; 2482268899Sbapt } 2483268899Sbapt if (c == L_CURL && !haveyyval) 2484268899Sbapt { 2485268899Sbapt fprintf(f, " if (!yytrial)\n"); 2486268899Sbapt if (!lflag) 2487268899Sbapt fprintf(f, line_format, lineno, input_file_name); 2488268899Sbapt trialaction = 0; 2489268899Sbapt goto loop; 2490268899Sbapt } 2491268899Sbapt fprintf(f, "\nbreak;\n"); 2492268899Sbapt FREE(a_line); 2493268899Sbapt if (maxoffset > 0) 2494268899Sbapt FREE(offsets); 2495268899Sbapt return; 2496268899Sbapt } 2497268899Sbapt } 2498268899Sbapt#endif 2499234949Sbapt putc(c, f); 2500234949Sbapt switch (c) 2501234949Sbapt { 2502234949Sbapt case '\n': 2503234949Sbapt get_line(); 2504234949Sbapt if (line) 2505234949Sbapt goto loop; 2506234949Sbapt unterminated_action(a_lineno, a_line, a_cptr); 2507234949Sbapt 2508234949Sbapt case ';': 2509234949Sbapt if (depth > 0) 2510234949Sbapt goto loop; 2511234949Sbapt fprintf(f, "\nbreak;\n"); 2512234949Sbapt free(a_line); 2513268899Sbapt if (maxoffset > 0) 2514268899Sbapt FREE(offsets); 2515234949Sbapt return; 2516234949Sbapt 2517268899Sbapt#if defined(YYBTYACC) 2518268899Sbapt case L_BRAC: 2519268899Sbapt if (backtrack) 2520268899Sbapt ++depth; 2521268899Sbapt goto loop; 2522268899Sbapt 2523268899Sbapt case R_BRAC: 2524268899Sbapt if (backtrack) 2525268899Sbapt --depth; 2526268899Sbapt goto loop; 2527268899Sbapt#endif 2528268899Sbapt 2529234949Sbapt case L_CURL: 2530234949Sbapt ++depth; 2531234949Sbapt goto loop; 2532234949Sbapt 2533234949Sbapt case R_CURL: 2534234949Sbapt if (--depth > 0) 2535234949Sbapt goto loop; 2536268899Sbapt#if defined(YYBTYACC) 2537268899Sbapt if (backtrack) 2538268899Sbapt { 2539268899Sbapt c = nextc(); 2540268899Sbapt if (c == L_BRAC && !haveyyval) 2541268899Sbapt { 2542268899Sbapt trialaction = 1; 2543268899Sbapt goto loop; 2544268899Sbapt } 2545268899Sbapt if (c == L_CURL && !haveyyval) 2546268899Sbapt { 2547268899Sbapt fprintf(f, " if (!yytrial)\n"); 2548268899Sbapt if (!lflag) 2549268899Sbapt fprintf(f, line_format, lineno, input_file_name); 2550268899Sbapt goto loop; 2551268899Sbapt } 2552268899Sbapt } 2553268899Sbapt#endif 2554234949Sbapt fprintf(f, "\nbreak;\n"); 2555234949Sbapt free(a_line); 2556268899Sbapt if (maxoffset > 0) 2557268899Sbapt FREE(offsets); 2558234949Sbapt return; 2559234949Sbapt 2560234949Sbapt case '\'': 2561234949Sbapt case '"': 2562234949Sbapt { 2563268899Sbapt char *s = copy_string(c); 2564268899Sbapt fputs(s, f); 2565268899Sbapt free(s); 2566268899Sbapt } 2567268899Sbapt goto loop; 2568234949Sbapt 2569268899Sbapt case '/': 2570268899Sbapt { 2571268899Sbapt char *s = copy_comment(); 2572268899Sbapt fputs(s, f); 2573268899Sbapt free(s); 2574268899Sbapt } 2575268899Sbapt goto loop; 2576268899Sbapt 2577268899Sbapt default: 2578268899Sbapt goto loop; 2579268899Sbapt } 2580268899Sbapt} 2581268899Sbapt 2582268899Sbapt#if defined(YYBTYACC) 2583268899Sbaptstatic void 2584268899Sbaptcopy_destructor(void) 2585268899Sbapt{ 2586268899Sbapt int c; 2587268899Sbapt int depth; 2588268899Sbapt char *tag; 2589268899Sbapt bucket *bp; 2590268899Sbapt struct mstring *destructor_text = msnew(); 2591268899Sbapt char *code_text; 2592268899Sbapt int a_lineno; 2593268899Sbapt char *a_line; 2594268899Sbapt char *a_cptr; 2595268899Sbapt 2596268899Sbapt if (!lflag) 2597268899Sbapt msprintf(destructor_text, line_format, lineno, input_file_name); 2598268899Sbapt 2599268899Sbapt cptr = after_blanks(cptr); 2600268899Sbapt if (*cptr == L_CURL) 2601268899Sbapt /* avoid putting curly-braces in first column, to ease editing */ 2602268899Sbapt mputc(destructor_text, '\t'); 2603268899Sbapt else 2604268899Sbapt syntax_error(lineno, line, cptr); 2605268899Sbapt 2606268899Sbapt a_lineno = lineno; 2607268899Sbapt a_line = dup_line(); 2608268899Sbapt a_cptr = a_line + (cptr - line); 2609268899Sbapt 2610268899Sbapt depth = 0; 2611268899Sbapt loop: 2612268899Sbapt c = *cptr; 2613268899Sbapt if (c == '$') 2614268899Sbapt { 2615268899Sbapt if (cptr[1] == '<') 2616268899Sbapt { 2617268899Sbapt int d_lineno = lineno; 2618268899Sbapt char *d_line = dup_line(); 2619268899Sbapt char *d_cptr = d_line + (cptr - line); 2620268899Sbapt 2621268899Sbapt ++cptr; 2622268899Sbapt tag = get_tag(); 2623268899Sbapt c = *cptr; 2624268899Sbapt if (c == '$') 2625234949Sbapt { 2626268899Sbapt msprintf(destructor_text, "(*val).%s", tag); 2627268899Sbapt ++cptr; 2628268899Sbapt FREE(d_line); 2629268899Sbapt goto loop; 2630268899Sbapt } 2631268899Sbapt else 2632268899Sbapt dollar_error(d_lineno, d_line, d_cptr); 2633268899Sbapt } 2634268899Sbapt else if (cptr[1] == '$') 2635268899Sbapt { 2636268899Sbapt /* process '$$' later; replacement is context dependent */ 2637268899Sbapt msprintf(destructor_text, "$$"); 2638268899Sbapt cptr += 2; 2639268899Sbapt goto loop; 2640268899Sbapt } 2641268899Sbapt } 2642268899Sbapt if (c == '@' && cptr[1] == '$') 2643268899Sbapt { 2644268899Sbapt if (!locations) 2645268899Sbapt { 2646268899Sbapt int l_lineno = lineno; 2647268899Sbapt char *l_line = dup_line(); 2648268899Sbapt char *l_cptr = l_line + (cptr - line); 2649268899Sbapt syntax_error(l_lineno, l_line, l_cptr); 2650268899Sbapt } 2651268899Sbapt msprintf(destructor_text, "(*loc)"); 2652268899Sbapt cptr += 2; 2653268899Sbapt goto loop; 2654268899Sbapt } 2655268899Sbapt if (isalpha(c) || c == '_' || c == '$') 2656268899Sbapt { 2657268899Sbapt do 2658268899Sbapt { 2659268899Sbapt mputc(destructor_text, c); 2660268899Sbapt c = *++cptr; 2661268899Sbapt } 2662268899Sbapt while (isalnum(c) || c == '_' || c == '$'); 2663268899Sbapt goto loop; 2664268899Sbapt } 2665268899Sbapt ++cptr; 2666268899Sbapt mputc(destructor_text, c); 2667268899Sbapt switch (c) 2668268899Sbapt { 2669268899Sbapt case '\n': 2670268899Sbapt get_line(); 2671268899Sbapt if (line) 2672268899Sbapt goto loop; 2673268899Sbapt unterminated_action(a_lineno, a_line, a_cptr); 2674268899Sbapt 2675268899Sbapt case L_CURL: 2676268899Sbapt ++depth; 2677268899Sbapt goto loop; 2678268899Sbapt 2679268899Sbapt case R_CURL: 2680268899Sbapt if (--depth > 0) 2681268899Sbapt goto loop; 2682268899Sbapt goto process_symbols; 2683268899Sbapt 2684268899Sbapt case '\'': 2685268899Sbapt case '"': 2686268899Sbapt { 2687268899Sbapt char *s = copy_string(c); 2688268899Sbapt msprintf(destructor_text, "%s", s); 2689268899Sbapt free(s); 2690268899Sbapt } 2691268899Sbapt goto loop; 2692268899Sbapt 2693268899Sbapt case '/': 2694268899Sbapt { 2695268899Sbapt char *s = copy_comment(); 2696268899Sbapt msprintf(destructor_text, "%s", s); 2697268899Sbapt free(s); 2698268899Sbapt } 2699268899Sbapt goto loop; 2700268899Sbapt 2701268899Sbapt default: 2702268899Sbapt goto loop; 2703268899Sbapt } 2704268899Sbapt process_symbols: 2705268899Sbapt code_text = msdone(destructor_text); 2706268899Sbapt for (;;) 2707268899Sbapt { 2708268899Sbapt c = nextc(); 2709268899Sbapt if (c == EOF) 2710268899Sbapt unexpected_EOF(); 2711268899Sbapt if (c == '<') 2712268899Sbapt { 2713268899Sbapt if (cptr[1] == '>') 2714268899Sbapt { /* "no semantic type" default destructor */ 2715268899Sbapt cptr += 2; 2716268899Sbapt if ((bp = default_destructor[UNTYPED_DEFAULT]) == NULL) 2717234949Sbapt { 2718268899Sbapt static char untyped_default[] = "<>"; 2719268899Sbapt bp = make_bucket("untyped default"); 2720268899Sbapt bp->tag = untyped_default; 2721268899Sbapt default_destructor[UNTYPED_DEFAULT] = bp; 2722234949Sbapt } 2723268899Sbapt if (bp->destructor != NULL) 2724268899Sbapt destructor_redeclared_warning(a_lineno, a_line, a_cptr); 2725268899Sbapt else 2726268899Sbapt /* replace "$$" with "(*val)" in destructor code */ 2727268899Sbapt bp->destructor = process_destructor_XX(code_text, NULL); 2728268899Sbapt } 2729268899Sbapt else if (cptr[1] == '*' && cptr[2] == '>') 2730268899Sbapt { /* "no per-symbol or per-type" default destructor */ 2731268899Sbapt cptr += 3; 2732268899Sbapt if ((bp = default_destructor[TYPED_DEFAULT]) == NULL) 2733234949Sbapt { 2734268899Sbapt static char typed_default[] = "<*>"; 2735268899Sbapt bp = make_bucket("typed default"); 2736268899Sbapt bp->tag = typed_default; 2737268899Sbapt default_destructor[TYPED_DEFAULT] = bp; 2738234949Sbapt } 2739268899Sbapt if (bp->destructor != NULL) 2740268899Sbapt destructor_redeclared_warning(a_lineno, a_line, a_cptr); 2741268899Sbapt else 2742268899Sbapt { 2743268899Sbapt /* postpone re-processing destructor $$s until end of grammar spec */ 2744268899Sbapt bp->destructor = TMALLOC(char, strlen(code_text) + 1); 2745268899Sbapt NO_SPACE(bp->destructor); 2746268899Sbapt strcpy(bp->destructor, code_text); 2747268899Sbapt } 2748234949Sbapt } 2749268899Sbapt else 2750268899Sbapt { /* "semantic type" default destructor */ 2751268899Sbapt tag = get_tag(); 2752268899Sbapt bp = lookup_type_destructor(tag); 2753268899Sbapt if (bp->destructor != NULL) 2754268899Sbapt destructor_redeclared_warning(a_lineno, a_line, a_cptr); 2755268899Sbapt else 2756268899Sbapt /* replace "$$" with "(*val).tag" in destructor code */ 2757268899Sbapt bp->destructor = process_destructor_XX(code_text, tag); 2758268899Sbapt } 2759234949Sbapt } 2760268899Sbapt else if (isalpha(c) || c == '_' || c == '.' || c == '$') 2761268899Sbapt { /* "symbol" destructor */ 2762268899Sbapt bp = get_name(); 2763268899Sbapt if (bp->destructor != NULL) 2764268899Sbapt destructor_redeclared_warning(a_lineno, a_line, a_cptr); 2765268899Sbapt else 2766268899Sbapt { 2767268899Sbapt /* postpone re-processing destructor $$s until end of grammar spec */ 2768268899Sbapt bp->destructor = TMALLOC(char, strlen(code_text) + 1); 2769268899Sbapt NO_SPACE(bp->destructor); 2770268899Sbapt strcpy(bp->destructor, code_text); 2771268899Sbapt } 2772268899Sbapt } 2773268899Sbapt else 2774268899Sbapt break; 2775268899Sbapt } 2776268899Sbapt free(a_line); 2777268899Sbapt free(code_text); 2778268899Sbapt} 2779234949Sbapt 2780268899Sbaptstatic char * 2781268899Sbaptprocess_destructor_XX(char *code, char *tag) 2782268899Sbapt{ 2783268899Sbapt int c; 2784268899Sbapt int quote; 2785268899Sbapt int depth; 2786268899Sbapt struct mstring *new_code = msnew(); 2787268899Sbapt char *codeptr = code; 2788268899Sbapt 2789268899Sbapt depth = 0; 2790268899Sbapt loop: /* step thru code */ 2791268899Sbapt c = *codeptr; 2792268899Sbapt if (c == '$' && codeptr[1] == '$') 2793268899Sbapt { 2794268899Sbapt codeptr += 2; 2795268899Sbapt if (tag == NULL) 2796268899Sbapt msprintf(new_code, "(*val)"); 2797268899Sbapt else 2798268899Sbapt msprintf(new_code, "(*val).%s", tag); 2799268899Sbapt goto loop; 2800268899Sbapt } 2801268899Sbapt if (isalpha(c) || c == '_' || c == '$') 2802268899Sbapt { 2803268899Sbapt do 2804234949Sbapt { 2805268899Sbapt mputc(new_code, c); 2806268899Sbapt c = *++codeptr; 2807268899Sbapt } 2808268899Sbapt while (isalnum(c) || c == '_' || c == '$'); 2809268899Sbapt goto loop; 2810268899Sbapt } 2811268899Sbapt ++codeptr; 2812268899Sbapt mputc(new_code, c); 2813268899Sbapt switch (c) 2814268899Sbapt { 2815268899Sbapt case L_CURL: 2816268899Sbapt ++depth; 2817268899Sbapt goto loop; 2818268899Sbapt 2819268899Sbapt case R_CURL: 2820268899Sbapt if (--depth > 0) 2821268899Sbapt goto loop; 2822268899Sbapt return msdone(new_code); 2823268899Sbapt 2824268899Sbapt case '\'': 2825268899Sbapt case '"': 2826268899Sbapt quote = c; 2827268899Sbapt for (;;) 2828268899Sbapt { 2829268899Sbapt c = *codeptr++; 2830268899Sbapt mputc(new_code, c); 2831268899Sbapt if (c == quote) 2832268899Sbapt goto loop; 2833268899Sbapt if (c == '\\') 2834234949Sbapt { 2835268899Sbapt c = *codeptr++; 2836268899Sbapt mputc(new_code, c); 2837234949Sbapt } 2838234949Sbapt } 2839268899Sbapt 2840268899Sbapt case '/': 2841268899Sbapt c = *codeptr; 2842234949Sbapt if (c == '*') 2843234949Sbapt { 2844268899Sbapt mputc(new_code, c); 2845268899Sbapt ++codeptr; 2846234949Sbapt for (;;) 2847234949Sbapt { 2848268899Sbapt c = *codeptr++; 2849268899Sbapt mputc(new_code, c); 2850268899Sbapt if (c == '*' && *codeptr == '/') 2851234949Sbapt { 2852268899Sbapt mputc(new_code, '/'); 2853268899Sbapt ++codeptr; 2854234949Sbapt goto loop; 2855234949Sbapt } 2856234949Sbapt } 2857234949Sbapt } 2858234949Sbapt goto loop; 2859234949Sbapt 2860234949Sbapt default: 2861234949Sbapt goto loop; 2862234949Sbapt } 2863234949Sbapt} 2864268899Sbapt#endif /* defined(YYBTYACC) */ 2865234949Sbapt 2866234949Sbaptstatic int 2867234949Sbaptmark_symbol(void) 2868234949Sbapt{ 2869234949Sbapt int c; 2870240517Sbapt bucket *bp = NULL; 2871234949Sbapt 2872234949Sbapt c = cptr[1]; 2873234949Sbapt if (c == '%' || c == '\\') 2874234949Sbapt { 2875234949Sbapt cptr += 2; 2876234949Sbapt return (1); 2877234949Sbapt } 2878234949Sbapt 2879234949Sbapt if (c == '=') 2880234949Sbapt cptr += 2; 2881234949Sbapt else if ((c == 'p' || c == 'P') && 2882234949Sbapt ((c = cptr[2]) == 'r' || c == 'R') && 2883234949Sbapt ((c = cptr[3]) == 'e' || c == 'E') && 2884234949Sbapt ((c = cptr[4]) == 'c' || c == 'C') && 2885234949Sbapt ((c = cptr[5], !IS_IDENT(c)))) 2886234949Sbapt cptr += 5; 2887234949Sbapt else 2888234949Sbapt syntax_error(lineno, line, cptr); 2889234949Sbapt 2890234949Sbapt c = nextc(); 2891234949Sbapt if (isalpha(c) || c == '_' || c == '.' || c == '$') 2892234949Sbapt bp = get_name(); 2893234949Sbapt else if (c == '\'' || c == '"') 2894234949Sbapt bp = get_literal(); 2895234949Sbapt else 2896234949Sbapt { 2897234949Sbapt syntax_error(lineno, line, cptr); 2898234949Sbapt } 2899234949Sbapt 2900234949Sbapt if (rprec[nrules] != UNDEFINED && bp->prec != rprec[nrules]) 2901234949Sbapt prec_redeclared(); 2902234949Sbapt 2903234949Sbapt rprec[nrules] = bp->prec; 2904234949Sbapt rassoc[nrules] = bp->assoc; 2905234949Sbapt return (0); 2906234949Sbapt} 2907234949Sbapt 2908234949Sbaptstatic void 2909234949Sbaptread_grammar(void) 2910234949Sbapt{ 2911234949Sbapt int c; 2912234949Sbapt 2913234949Sbapt initialize_grammar(); 2914234949Sbapt advance_to_start(); 2915234949Sbapt 2916234949Sbapt for (;;) 2917234949Sbapt { 2918234949Sbapt c = nextc(); 2919234949Sbapt if (c == EOF) 2920234949Sbapt break; 2921234949Sbapt if (isalpha(c) 2922234949Sbapt || c == '_' 2923234949Sbapt || c == '.' 2924234949Sbapt || c == '$' 2925234949Sbapt || c == '\'' 2926234949Sbapt || c == '"') 2927234949Sbapt add_symbol(); 2928268899Sbapt#if defined(YYBTYACC) 2929268899Sbapt else if (c == L_CURL || c == '=' || (backtrack && c == L_BRAC)) 2930268899Sbapt#else 2931234949Sbapt else if (c == L_CURL || c == '=') 2932268899Sbapt#endif 2933234949Sbapt copy_action(); 2934234949Sbapt else if (c == '|') 2935234949Sbapt { 2936234949Sbapt end_rule(); 2937234949Sbapt start_rule(plhs[nrules - 1], 0); 2938234949Sbapt ++cptr; 2939234949Sbapt } 2940234949Sbapt else if (c == '%') 2941234949Sbapt { 2942234949Sbapt if (mark_symbol()) 2943234949Sbapt break; 2944234949Sbapt } 2945234949Sbapt else 2946234949Sbapt syntax_error(lineno, line, cptr); 2947234949Sbapt } 2948234949Sbapt end_rule(); 2949268899Sbapt#if defined(YYBTYACC) 2950268899Sbapt if (goal->args > 0) 2951268899Sbapt start_requires_args(goal->name); 2952268899Sbapt#endif 2953234949Sbapt} 2954234949Sbapt 2955234949Sbaptstatic void 2956234949Sbaptfree_tags(void) 2957234949Sbapt{ 2958234949Sbapt int i; 2959234949Sbapt 2960234949Sbapt if (tag_table == 0) 2961234949Sbapt return; 2962234949Sbapt 2963234949Sbapt for (i = 0; i < ntags; ++i) 2964234949Sbapt { 2965234949Sbapt assert(tag_table[i]); 2966234949Sbapt FREE(tag_table[i]); 2967234949Sbapt } 2968234949Sbapt FREE(tag_table); 2969234949Sbapt} 2970234949Sbapt 2971234949Sbaptstatic void 2972234949Sbaptpack_names(void) 2973234949Sbapt{ 2974234949Sbapt bucket *bp; 2975234949Sbapt char *p, *s, *t; 2976234949Sbapt 2977234949Sbapt name_pool_size = 13; /* 13 == sizeof("$end") + sizeof("$accept") */ 2978234949Sbapt for (bp = first_symbol; bp; bp = bp->next) 2979234949Sbapt name_pool_size += strlen(bp->name) + 1; 2980234949Sbapt 2981240517Sbapt name_pool = TMALLOC(char, name_pool_size); 2982234949Sbapt NO_SPACE(name_pool); 2983234949Sbapt 2984234949Sbapt strcpy(name_pool, "$accept"); 2985234949Sbapt strcpy(name_pool + 8, "$end"); 2986234949Sbapt t = name_pool + 13; 2987234949Sbapt for (bp = first_symbol; bp; bp = bp->next) 2988234949Sbapt { 2989234949Sbapt p = t; 2990234949Sbapt s = bp->name; 2991234949Sbapt while ((*t++ = *s++) != 0) 2992234949Sbapt continue; 2993234949Sbapt FREE(bp->name); 2994234949Sbapt bp->name = p; 2995234949Sbapt } 2996234949Sbapt} 2997234949Sbapt 2998234949Sbaptstatic void 2999234949Sbaptcheck_symbols(void) 3000234949Sbapt{ 3001234949Sbapt bucket *bp; 3002234949Sbapt 3003234949Sbapt if (goal->class == UNKNOWN) 3004234949Sbapt undefined_goal(goal->name); 3005234949Sbapt 3006234949Sbapt for (bp = first_symbol; bp; bp = bp->next) 3007234949Sbapt { 3008234949Sbapt if (bp->class == UNKNOWN) 3009234949Sbapt { 3010234949Sbapt undefined_symbol_warning(bp->name); 3011234949Sbapt bp->class = TERM; 3012234949Sbapt } 3013234949Sbapt } 3014234949Sbapt} 3015234949Sbapt 3016234949Sbaptstatic void 3017234949Sbaptprotect_string(char *src, char **des) 3018234949Sbapt{ 3019234949Sbapt unsigned len; 3020234949Sbapt char *s; 3021234949Sbapt char *d; 3022234949Sbapt 3023234949Sbapt *des = src; 3024234949Sbapt if (src) 3025234949Sbapt { 3026234949Sbapt len = 1; 3027234949Sbapt s = src; 3028234949Sbapt while (*s) 3029234949Sbapt { 3030234949Sbapt if ('\\' == *s || '"' == *s) 3031234949Sbapt len++; 3032234949Sbapt s++; 3033234949Sbapt len++; 3034234949Sbapt } 3035234949Sbapt 3036240517Sbapt *des = d = TMALLOC(char, len); 3037234949Sbapt NO_SPACE(d); 3038234949Sbapt 3039234949Sbapt s = src; 3040234949Sbapt while (*s) 3041234949Sbapt { 3042234949Sbapt if ('\\' == *s || '"' == *s) 3043234949Sbapt *d++ = '\\'; 3044234949Sbapt *d++ = *s++; 3045234949Sbapt } 3046234949Sbapt *d = '\0'; 3047234949Sbapt } 3048234949Sbapt} 3049234949Sbapt 3050234949Sbaptstatic void 3051234949Sbaptpack_symbols(void) 3052234949Sbapt{ 3053234949Sbapt bucket *bp; 3054234949Sbapt bucket **v; 3055234949Sbapt Value_t i, j, k, n; 3056268899Sbapt#if defined(YYBTYACC) 3057268899Sbapt Value_t max_tok_pval; 3058268899Sbapt#endif 3059234949Sbapt 3060234949Sbapt nsyms = 2; 3061234949Sbapt ntokens = 1; 3062234949Sbapt for (bp = first_symbol; bp; bp = bp->next) 3063234949Sbapt { 3064234949Sbapt ++nsyms; 3065234949Sbapt if (bp->class == TERM) 3066234949Sbapt ++ntokens; 3067234949Sbapt } 3068234949Sbapt start_symbol = (Value_t) ntokens; 3069268899Sbapt nvars = (Value_t) (nsyms - ntokens); 3070234949Sbapt 3071240517Sbapt symbol_name = TMALLOC(char *, nsyms); 3072234949Sbapt NO_SPACE(symbol_name); 3073234949Sbapt 3074240517Sbapt symbol_value = TMALLOC(Value_t, nsyms); 3075234949Sbapt NO_SPACE(symbol_value); 3076234949Sbapt 3077268899Sbapt symbol_prec = TMALLOC(Value_t, nsyms); 3078234949Sbapt NO_SPACE(symbol_prec); 3079234949Sbapt 3080240517Sbapt symbol_assoc = TMALLOC(char, nsyms); 3081234949Sbapt NO_SPACE(symbol_assoc); 3082234949Sbapt 3083268899Sbapt#if defined(YYBTYACC) 3084268899Sbapt symbol_pval = TMALLOC(Value_t, nsyms); 3085268899Sbapt NO_SPACE(symbol_pval); 3086268899Sbapt 3087268899Sbapt if (destructor) 3088268899Sbapt { 3089268899Sbapt symbol_destructor = CALLOC(sizeof(char *), nsyms); 3090268899Sbapt NO_SPACE(symbol_destructor); 3091268899Sbapt 3092268899Sbapt symbol_type_tag = CALLOC(sizeof(char *), nsyms); 3093268899Sbapt NO_SPACE(symbol_type_tag); 3094268899Sbapt } 3095268899Sbapt#endif 3096268899Sbapt 3097240517Sbapt v = TMALLOC(bucket *, nsyms); 3098234949Sbapt NO_SPACE(v); 3099234949Sbapt 3100234949Sbapt v[0] = 0; 3101234949Sbapt v[start_symbol] = 0; 3102234949Sbapt 3103234949Sbapt i = 1; 3104234949Sbapt j = (Value_t) (start_symbol + 1); 3105234949Sbapt for (bp = first_symbol; bp; bp = bp->next) 3106234949Sbapt { 3107234949Sbapt if (bp->class == TERM) 3108234949Sbapt v[i++] = bp; 3109234949Sbapt else 3110234949Sbapt v[j++] = bp; 3111234949Sbapt } 3112234949Sbapt assert(i == ntokens && j == nsyms); 3113234949Sbapt 3114234949Sbapt for (i = 1; i < ntokens; ++i) 3115234949Sbapt v[i]->index = i; 3116234949Sbapt 3117234949Sbapt goal->index = (Index_t) (start_symbol + 1); 3118234949Sbapt k = (Value_t) (start_symbol + 2); 3119234949Sbapt while (++i < nsyms) 3120234949Sbapt if (v[i] != goal) 3121234949Sbapt { 3122234949Sbapt v[i]->index = k; 3123234949Sbapt ++k; 3124234949Sbapt } 3125234949Sbapt 3126234949Sbapt goal->value = 0; 3127234949Sbapt k = 1; 3128234949Sbapt for (i = (Value_t) (start_symbol + 1); i < nsyms; ++i) 3129234949Sbapt { 3130234949Sbapt if (v[i] != goal) 3131234949Sbapt { 3132234949Sbapt v[i]->value = k; 3133234949Sbapt ++k; 3134234949Sbapt } 3135234949Sbapt } 3136234949Sbapt 3137234949Sbapt k = 0; 3138234949Sbapt for (i = 1; i < ntokens; ++i) 3139234949Sbapt { 3140234949Sbapt n = v[i]->value; 3141234949Sbapt if (n > 256) 3142234949Sbapt { 3143234949Sbapt for (j = k++; j > 0 && symbol_value[j - 1] > n; --j) 3144234949Sbapt symbol_value[j] = symbol_value[j - 1]; 3145234949Sbapt symbol_value[j] = n; 3146234949Sbapt } 3147234949Sbapt } 3148234949Sbapt 3149234949Sbapt assert(v[1] != 0); 3150234949Sbapt 3151234949Sbapt if (v[1]->value == UNDEFINED) 3152234949Sbapt v[1]->value = 256; 3153234949Sbapt 3154234949Sbapt j = 0; 3155234949Sbapt n = 257; 3156234949Sbapt for (i = 2; i < ntokens; ++i) 3157234949Sbapt { 3158234949Sbapt if (v[i]->value == UNDEFINED) 3159234949Sbapt { 3160234949Sbapt while (j < k && n == symbol_value[j]) 3161234949Sbapt { 3162234949Sbapt while (++j < k && n == symbol_value[j]) 3163234949Sbapt continue; 3164234949Sbapt ++n; 3165234949Sbapt } 3166234949Sbapt v[i]->value = n; 3167234949Sbapt ++n; 3168234949Sbapt } 3169234949Sbapt } 3170234949Sbapt 3171234949Sbapt symbol_name[0] = name_pool + 8; 3172234949Sbapt symbol_value[0] = 0; 3173234949Sbapt symbol_prec[0] = 0; 3174234949Sbapt symbol_assoc[0] = TOKEN; 3175268899Sbapt#if defined(YYBTYACC) 3176268899Sbapt symbol_pval[0] = 0; 3177268899Sbapt max_tok_pval = 0; 3178268899Sbapt#endif 3179234949Sbapt for (i = 1; i < ntokens; ++i) 3180234949Sbapt { 3181234949Sbapt symbol_name[i] = v[i]->name; 3182234949Sbapt symbol_value[i] = v[i]->value; 3183234949Sbapt symbol_prec[i] = v[i]->prec; 3184234949Sbapt symbol_assoc[i] = v[i]->assoc; 3185268899Sbapt#if defined(YYBTYACC) 3186268899Sbapt symbol_pval[i] = v[i]->value; 3187268899Sbapt if (symbol_pval[i] > max_tok_pval) 3188268899Sbapt max_tok_pval = symbol_pval[i]; 3189268899Sbapt if (destructor) 3190268899Sbapt { 3191268899Sbapt symbol_destructor[i] = v[i]->destructor; 3192268899Sbapt symbol_type_tag[i] = v[i]->tag; 3193268899Sbapt } 3194268899Sbapt#endif 3195234949Sbapt } 3196234949Sbapt symbol_name[start_symbol] = name_pool; 3197234949Sbapt symbol_value[start_symbol] = -1; 3198234949Sbapt symbol_prec[start_symbol] = 0; 3199234949Sbapt symbol_assoc[start_symbol] = TOKEN; 3200268899Sbapt#if defined(YYBTYACC) 3201268899Sbapt symbol_pval[start_symbol] = (Value_t) (max_tok_pval + 1); 3202268899Sbapt#endif 3203234949Sbapt for (++i; i < nsyms; ++i) 3204234949Sbapt { 3205234949Sbapt k = v[i]->index; 3206234949Sbapt symbol_name[k] = v[i]->name; 3207234949Sbapt symbol_value[k] = v[i]->value; 3208234949Sbapt symbol_prec[k] = v[i]->prec; 3209234949Sbapt symbol_assoc[k] = v[i]->assoc; 3210268899Sbapt#if defined(YYBTYACC) 3211268899Sbapt symbol_pval[k] = (Value_t) ((max_tok_pval + 1) + v[i]->value + 1); 3212268899Sbapt if (destructor) 3213268899Sbapt { 3214268899Sbapt symbol_destructor[k] = v[i]->destructor; 3215268899Sbapt symbol_type_tag[k] = v[i]->tag; 3216268899Sbapt } 3217268899Sbapt#endif 3218234949Sbapt } 3219234949Sbapt 3220234949Sbapt if (gflag) 3221234949Sbapt { 3222240517Sbapt symbol_pname = TMALLOC(char *, nsyms); 3223234949Sbapt NO_SPACE(symbol_pname); 3224234949Sbapt 3225234949Sbapt for (i = 0; i < nsyms; ++i) 3226234949Sbapt protect_string(symbol_name[i], &(symbol_pname[i])); 3227234949Sbapt } 3228234949Sbapt 3229234949Sbapt FREE(v); 3230234949Sbapt} 3231234949Sbapt 3232234949Sbaptstatic void 3233234949Sbaptpack_grammar(void) 3234234949Sbapt{ 3235234949Sbapt int i; 3236234949Sbapt Value_t j; 3237234949Sbapt Assoc_t assoc; 3238234949Sbapt Value_t prec2; 3239234949Sbapt 3240240517Sbapt ritem = TMALLOC(Value_t, nitems); 3241234949Sbapt NO_SPACE(ritem); 3242234949Sbapt 3243240517Sbapt rlhs = TMALLOC(Value_t, nrules); 3244234949Sbapt NO_SPACE(rlhs); 3245234949Sbapt 3246240517Sbapt rrhs = TMALLOC(Value_t, nrules + 1); 3247234949Sbapt NO_SPACE(rrhs); 3248234949Sbapt 3249240517Sbapt rprec = TREALLOC(Value_t, rprec, nrules); 3250234949Sbapt NO_SPACE(rprec); 3251234949Sbapt 3252240517Sbapt rassoc = TREALLOC(Assoc_t, rassoc, nrules); 3253234949Sbapt NO_SPACE(rassoc); 3254234949Sbapt 3255234949Sbapt ritem[0] = -1; 3256234949Sbapt ritem[1] = goal->index; 3257234949Sbapt ritem[2] = 0; 3258234949Sbapt ritem[3] = -2; 3259234949Sbapt rlhs[0] = 0; 3260234949Sbapt rlhs[1] = 0; 3261234949Sbapt rlhs[2] = start_symbol; 3262234949Sbapt rrhs[0] = 0; 3263234949Sbapt rrhs[1] = 0; 3264234949Sbapt rrhs[2] = 1; 3265234949Sbapt 3266234949Sbapt j = 4; 3267234949Sbapt for (i = 3; i < nrules; ++i) 3268234949Sbapt { 3269268899Sbapt#if defined(YYBTYACC) 3270268899Sbapt if (plhs[i]->args > 0) 3271268899Sbapt { 3272268899Sbapt if (plhs[i]->argnames) 3273268899Sbapt { 3274268899Sbapt FREE(plhs[i]->argnames); 3275268899Sbapt plhs[i]->argnames = NULL; 3276268899Sbapt } 3277268899Sbapt if (plhs[i]->argtags) 3278268899Sbapt { 3279268899Sbapt FREE(plhs[i]->argtags); 3280268899Sbapt plhs[i]->argtags = NULL; 3281268899Sbapt } 3282268899Sbapt } 3283268899Sbapt#endif /* defined(YYBTYACC) */ 3284234949Sbapt rlhs[i] = plhs[i]->index; 3285234949Sbapt rrhs[i] = j; 3286234949Sbapt assoc = TOKEN; 3287234949Sbapt prec2 = 0; 3288234949Sbapt while (pitem[j]) 3289234949Sbapt { 3290234949Sbapt ritem[j] = pitem[j]->index; 3291234949Sbapt if (pitem[j]->class == TERM) 3292234949Sbapt { 3293234949Sbapt prec2 = pitem[j]->prec; 3294234949Sbapt assoc = pitem[j]->assoc; 3295234949Sbapt } 3296234949Sbapt ++j; 3297234949Sbapt } 3298234949Sbapt ritem[j] = (Value_t) - i; 3299234949Sbapt ++j; 3300234949Sbapt if (rprec[i] == UNDEFINED) 3301234949Sbapt { 3302234949Sbapt rprec[i] = prec2; 3303234949Sbapt rassoc[i] = assoc; 3304234949Sbapt } 3305234949Sbapt } 3306234949Sbapt rrhs[i] = j; 3307234949Sbapt 3308234949Sbapt FREE(plhs); 3309234949Sbapt FREE(pitem); 3310268899Sbapt#if defined(YYBTYACC) 3311268899Sbapt clean_arg_cache(); 3312268899Sbapt#endif 3313234949Sbapt} 3314234949Sbapt 3315234949Sbaptstatic void 3316234949Sbaptprint_grammar(void) 3317234949Sbapt{ 3318234949Sbapt int i, k; 3319234949Sbapt size_t j, spacing = 0; 3320234949Sbapt FILE *f = verbose_file; 3321234949Sbapt 3322234949Sbapt if (!vflag) 3323234949Sbapt return; 3324234949Sbapt 3325234949Sbapt k = 1; 3326234949Sbapt for (i = 2; i < nrules; ++i) 3327234949Sbapt { 3328234949Sbapt if (rlhs[i] != rlhs[i - 1]) 3329234949Sbapt { 3330234949Sbapt if (i != 2) 3331234949Sbapt fprintf(f, "\n"); 3332234949Sbapt fprintf(f, "%4d %s :", i - 2, symbol_name[rlhs[i]]); 3333234949Sbapt spacing = strlen(symbol_name[rlhs[i]]) + 1; 3334234949Sbapt } 3335234949Sbapt else 3336234949Sbapt { 3337234949Sbapt fprintf(f, "%4d ", i - 2); 3338234949Sbapt j = spacing; 3339234949Sbapt while (j-- != 0) 3340234949Sbapt putc(' ', f); 3341234949Sbapt putc('|', f); 3342234949Sbapt } 3343234949Sbapt 3344234949Sbapt while (ritem[k] >= 0) 3345234949Sbapt { 3346234949Sbapt fprintf(f, " %s", symbol_name[ritem[k]]); 3347234949Sbapt ++k; 3348234949Sbapt } 3349234949Sbapt ++k; 3350234949Sbapt putc('\n', f); 3351234949Sbapt } 3352234949Sbapt} 3353234949Sbapt 3354268899Sbapt#if defined(YYBTYACC) 3355268899Sbaptstatic void 3356268899Sbaptfinalize_destructors(void) 3357268899Sbapt{ 3358268899Sbapt int i; 3359268899Sbapt bucket *bp; 3360268899Sbapt char *tag; 3361268899Sbapt 3362268899Sbapt for (i = 2; i < nsyms; ++i) 3363268899Sbapt { 3364268899Sbapt tag = symbol_type_tag[i]; 3365268899Sbapt if (symbol_destructor[i] == NULL) 3366268899Sbapt { 3367268899Sbapt if (tag == NULL) 3368268899Sbapt { /* use <> destructor, if there is one */ 3369268899Sbapt if ((bp = default_destructor[UNTYPED_DEFAULT]) != NULL) 3370268899Sbapt { 3371268899Sbapt symbol_destructor[i] = TMALLOC(char, 3372268899Sbapt strlen(bp->destructor) + 1); 3373268899Sbapt NO_SPACE(symbol_destructor[i]); 3374268899Sbapt strcpy(symbol_destructor[i], bp->destructor); 3375268899Sbapt } 3376268899Sbapt } 3377268899Sbapt else 3378268899Sbapt { /* use type destructor for this tag, if there is one */ 3379268899Sbapt bp = lookup_type_destructor(tag); 3380268899Sbapt if (bp->destructor != NULL) 3381268899Sbapt { 3382268899Sbapt symbol_destructor[i] = TMALLOC(char, 3383268899Sbapt strlen(bp->destructor) + 1); 3384268899Sbapt NO_SPACE(symbol_destructor[i]); 3385268899Sbapt strcpy(symbol_destructor[i], bp->destructor); 3386268899Sbapt } 3387268899Sbapt else 3388268899Sbapt { /* use <*> destructor, if there is one */ 3389268899Sbapt if ((bp = default_destructor[TYPED_DEFAULT]) != NULL) 3390268899Sbapt /* replace "$$" with "(*val).tag" in destructor code */ 3391268899Sbapt symbol_destructor[i] 3392268899Sbapt = process_destructor_XX(bp->destructor, tag); 3393268899Sbapt } 3394268899Sbapt } 3395268899Sbapt } 3396268899Sbapt else 3397268899Sbapt { /* replace "$$" with "(*val)[.tag]" in destructor code */ 3398268899Sbapt symbol_destructor[i] 3399268899Sbapt = process_destructor_XX(symbol_destructor[i], tag); 3400268899Sbapt } 3401268899Sbapt } 3402268899Sbapt /* 'symbol_type_tag[]' elements are freed by 'free_tags()' */ 3403268899Sbapt DO_FREE(symbol_type_tag); /* no longer needed */ 3404268899Sbapt if ((bp = default_destructor[UNTYPED_DEFAULT]) != NULL) 3405268899Sbapt { 3406268899Sbapt FREE(bp->name); 3407268899Sbapt /* 'bp->tag' is a static value, don't free */ 3408268899Sbapt FREE(bp->destructor); 3409268899Sbapt FREE(bp); 3410268899Sbapt } 3411268899Sbapt if ((bp = default_destructor[TYPED_DEFAULT]) != NULL) 3412268899Sbapt { 3413268899Sbapt FREE(bp->name); 3414268899Sbapt /* 'bp->tag' is a static value, don't free */ 3415268899Sbapt FREE(bp->destructor); 3416268899Sbapt FREE(bp); 3417268899Sbapt } 3418268899Sbapt if ((bp = default_destructor[TYPE_SPECIFIED]) != NULL) 3419268899Sbapt { 3420268899Sbapt bucket *p; 3421268899Sbapt for (; bp; bp = p) 3422268899Sbapt { 3423268899Sbapt p = bp->link; 3424268899Sbapt FREE(bp->name); 3425268899Sbapt /* 'bp->tag' freed by 'free_tags()' */ 3426268899Sbapt FREE(bp->destructor); 3427268899Sbapt FREE(bp); 3428268899Sbapt } 3429268899Sbapt } 3430268899Sbapt} 3431268899Sbapt#endif /* defined(YYBTYACC) */ 3432268899Sbapt 3433234949Sbaptvoid 3434234949Sbaptreader(void) 3435234949Sbapt{ 3436234949Sbapt write_section(code_file, banner); 3437234949Sbapt create_symbol_table(); 3438234949Sbapt read_declarations(); 3439234949Sbapt read_grammar(); 3440234949Sbapt free_symbol_table(); 3441234949Sbapt pack_names(); 3442234949Sbapt check_symbols(); 3443234949Sbapt pack_symbols(); 3444234949Sbapt pack_grammar(); 3445234949Sbapt free_symbols(); 3446234949Sbapt print_grammar(); 3447268899Sbapt#if defined(YYBTYACC) 3448268899Sbapt if (destructor) 3449268899Sbapt finalize_destructors(); 3450268899Sbapt#endif 3451268899Sbapt free_tags(); 3452234949Sbapt} 3453234949Sbapt 3454234949Sbapt#ifdef NO_LEAKS 3455234949Sbaptstatic param * 3456234949Sbaptfree_declarations(param * list) 3457234949Sbapt{ 3458234949Sbapt while (list != 0) 3459234949Sbapt { 3460234949Sbapt param *next = list->next; 3461234949Sbapt free(list->type); 3462234949Sbapt free(list->name); 3463234949Sbapt free(list->type2); 3464234949Sbapt free(list); 3465234949Sbapt list = next; 3466234949Sbapt } 3467234949Sbapt return list; 3468234949Sbapt} 3469234949Sbapt 3470234949Sbaptvoid 3471234949Sbaptreader_leaks(void) 3472234949Sbapt{ 3473234949Sbapt lex_param = free_declarations(lex_param); 3474234949Sbapt parse_param = free_declarations(parse_param); 3475234949Sbapt 3476234949Sbapt DO_FREE(line); 3477234949Sbapt DO_FREE(rrhs); 3478234949Sbapt DO_FREE(rlhs); 3479234949Sbapt DO_FREE(rprec); 3480234949Sbapt DO_FREE(ritem); 3481234949Sbapt DO_FREE(rassoc); 3482234949Sbapt DO_FREE(cache); 3483234949Sbapt DO_FREE(name_pool); 3484234949Sbapt DO_FREE(symbol_name); 3485234949Sbapt DO_FREE(symbol_prec); 3486234949Sbapt DO_FREE(symbol_assoc); 3487234949Sbapt DO_FREE(symbol_value); 3488268899Sbapt#if defined(YYBTYACC) 3489268899Sbapt DO_FREE(symbol_pval); 3490268899Sbapt DO_FREE(symbol_destructor); 3491268899Sbapt DO_FREE(symbol_type_tag); 3492268899Sbapt#endif 3493234949Sbapt} 3494234949Sbapt#endif 3495