reader.c revision 235723
1234949Sbapt/* $Id: reader.c,v 1.33 2011/09/06 22:56:53 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 12234949Sbapt#define L_CURL '{' 13234949Sbapt#define R_CURL '}' 14234949Sbapt 15234949Sbaptstatic void start_rule(bucket *bp, int s_lineno); 16234949Sbapt 17234949Sbaptstatic char *cache; 18234949Sbaptstatic int cinc, cache_size; 19234949Sbapt 20234949Sbaptint ntags; 21234949Sbaptstatic int tagmax; 22234949Sbaptstatic char **tag_table; 23234949Sbapt 24234949Sbaptstatic char saw_eof; 25234949Sbaptchar unionized; 26234949Sbaptchar *cptr, *line; 27234949Sbaptstatic int linesize; 28234949Sbapt 29234949Sbaptstatic bucket *goal; 30234949Sbaptstatic Value_t prec; 31234949Sbaptstatic int gensym; 32234949Sbaptstatic char last_was_action; 33234949Sbapt 34234949Sbaptstatic int maxitems; 35234949Sbaptstatic bucket **pitem; 36234949Sbapt 37234949Sbaptstatic int maxrules; 38234949Sbaptstatic bucket **plhs; 39234949Sbapt 40234949Sbaptstatic size_t name_pool_size; 41234949Sbaptstatic char *name_pool; 42234949Sbapt 43234949Sbaptchar line_format[] = "#line %d \"%s\"\n"; 44234949Sbapt 45234949Sbaptparam *lex_param; 46234949Sbaptparam *parse_param; 47234949Sbapt 48234949Sbaptstatic void 49234949Sbaptcachec(int c) 50234949Sbapt{ 51234949Sbapt assert(cinc >= 0); 52234949Sbapt if (cinc >= cache_size) 53234949Sbapt { 54234949Sbapt cache_size += 256; 55234949Sbapt cache = REALLOC(cache, cache_size); 56234949Sbapt NO_SPACE(cache); 57234949Sbapt } 58234949Sbapt cache[cinc] = (char)c; 59234949Sbapt ++cinc; 60234949Sbapt} 61234949Sbapt 62234949Sbaptstatic void 63234949Sbaptget_line(void) 64234949Sbapt{ 65234949Sbapt FILE *f = input_file; 66234949Sbapt int c; 67234949Sbapt int i; 68234949Sbapt 69234949Sbapt if (saw_eof || (c = getc(f)) == EOF) 70234949Sbapt { 71234949Sbapt if (line) 72234949Sbapt { 73234949Sbapt FREE(line); 74234949Sbapt line = 0; 75234949Sbapt } 76234949Sbapt cptr = 0; 77234949Sbapt saw_eof = 1; 78234949Sbapt return; 79234949Sbapt } 80234949Sbapt 81234949Sbapt if (line == 0 || linesize != (LINESIZE + 1)) 82234949Sbapt { 83234949Sbapt if (line) 84234949Sbapt FREE(line); 85234949Sbapt linesize = LINESIZE + 1; 86234949Sbapt line = MALLOC(linesize); 87234949Sbapt NO_SPACE(line); 88234949Sbapt } 89234949Sbapt 90234949Sbapt i = 0; 91234949Sbapt ++lineno; 92234949Sbapt for (;;) 93234949Sbapt { 94234949Sbapt line[i] = (char)c; 95234949Sbapt if (c == '\n') 96234949Sbapt { 97234949Sbapt cptr = line; 98234949Sbapt return; 99234949Sbapt } 100234949Sbapt if (++i >= linesize) 101234949Sbapt { 102234949Sbapt linesize += LINESIZE; 103234949Sbapt line = REALLOC(line, linesize); 104234949Sbapt NO_SPACE(line); 105234949Sbapt } 106234949Sbapt c = getc(f); 107234949Sbapt if (c == EOF) 108234949Sbapt { 109234949Sbapt line[i] = '\n'; 110234949Sbapt saw_eof = 1; 111234949Sbapt cptr = line; 112234949Sbapt return; 113234949Sbapt } 114234949Sbapt } 115234949Sbapt} 116234949Sbapt 117234949Sbaptstatic char * 118234949Sbaptdup_line(void) 119234949Sbapt{ 120234949Sbapt char *p, *s, *t; 121234949Sbapt 122234949Sbapt if (line == 0) 123234949Sbapt return (0); 124234949Sbapt s = line; 125234949Sbapt while (*s != '\n') 126234949Sbapt ++s; 127234949Sbapt p = MALLOC(s - line + 1); 128234949Sbapt NO_SPACE(p); 129234949Sbapt 130234949Sbapt s = line; 131234949Sbapt t = p; 132234949Sbapt while ((*t++ = *s++) != '\n') 133234949Sbapt continue; 134234949Sbapt return (p); 135234949Sbapt} 136234949Sbapt 137234949Sbaptstatic void 138234949Sbaptskip_comment(void) 139234949Sbapt{ 140234949Sbapt char *s; 141234949Sbapt 142234949Sbapt int st_lineno = lineno; 143234949Sbapt char *st_line = dup_line(); 144234949Sbapt char *st_cptr = st_line + (cptr - line); 145234949Sbapt 146234949Sbapt s = cptr + 2; 147234949Sbapt for (;;) 148234949Sbapt { 149234949Sbapt if (*s == '*' && s[1] == '/') 150234949Sbapt { 151234949Sbapt cptr = s + 2; 152234949Sbapt FREE(st_line); 153234949Sbapt return; 154234949Sbapt } 155234949Sbapt if (*s == '\n') 156234949Sbapt { 157234949Sbapt get_line(); 158234949Sbapt if (line == 0) 159234949Sbapt unterminated_comment(st_lineno, st_line, st_cptr); 160234949Sbapt s = cptr; 161234949Sbapt } 162234949Sbapt else 163234949Sbapt ++s; 164234949Sbapt } 165234949Sbapt} 166234949Sbapt 167234949Sbaptstatic int 168234949Sbaptnextc(void) 169234949Sbapt{ 170234949Sbapt char *s; 171234949Sbapt 172234949Sbapt if (line == 0) 173234949Sbapt { 174234949Sbapt get_line(); 175234949Sbapt if (line == 0) 176234949Sbapt return (EOF); 177234949Sbapt } 178234949Sbapt 179234949Sbapt s = cptr; 180234949Sbapt for (;;) 181234949Sbapt { 182234949Sbapt switch (*s) 183234949Sbapt { 184234949Sbapt case '\n': 185234949Sbapt get_line(); 186234949Sbapt if (line == 0) 187234949Sbapt return (EOF); 188234949Sbapt s = cptr; 189234949Sbapt break; 190234949Sbapt 191234949Sbapt case ' ': 192234949Sbapt case '\t': 193234949Sbapt case '\f': 194234949Sbapt case '\r': 195234949Sbapt case '\v': 196234949Sbapt case ',': 197234949Sbapt case ';': 198234949Sbapt ++s; 199234949Sbapt break; 200234949Sbapt 201234949Sbapt case '\\': 202234949Sbapt cptr = s; 203234949Sbapt return ('%'); 204234949Sbapt 205234949Sbapt case '/': 206234949Sbapt if (s[1] == '*') 207234949Sbapt { 208234949Sbapt cptr = s; 209234949Sbapt skip_comment(); 210234949Sbapt s = cptr; 211234949Sbapt break; 212234949Sbapt } 213234949Sbapt else if (s[1] == '/') 214234949Sbapt { 215234949Sbapt get_line(); 216234949Sbapt if (line == 0) 217234949Sbapt return (EOF); 218234949Sbapt s = cptr; 219234949Sbapt break; 220234949Sbapt } 221234949Sbapt /* FALLTHRU */ 222234949Sbapt 223234949Sbapt default: 224234949Sbapt cptr = s; 225234949Sbapt return (*s); 226234949Sbapt } 227234949Sbapt } 228234949Sbapt} 229234949Sbapt 230234949Sbapt/* 231234949Sbapt * Compare keyword to cached token, treating '_' and '-' the same. Some 232234949Sbapt * grammars rely upon this misfeature. 233234949Sbapt */ 234234949Sbaptstatic int 235234949Sbaptmatchec(const char *name) 236234949Sbapt{ 237234949Sbapt const char *p = cache; 238234949Sbapt const char *q = name; 239234949Sbapt int code = 0; /* assume mismatch */ 240234949Sbapt 241234949Sbapt while (*p != '\0' && *q != '\0') 242234949Sbapt { 243234949Sbapt char a = *p++; 244234949Sbapt char b = *q++; 245234949Sbapt if (a == '_') 246234949Sbapt a = '-'; 247234949Sbapt if (b == '_') 248234949Sbapt b = '-'; 249234949Sbapt if (a != b) 250234949Sbapt break; 251234949Sbapt if (*p == '\0' && *q == '\0') 252234949Sbapt { 253234949Sbapt code = 1; 254234949Sbapt break; 255234949Sbapt } 256234949Sbapt } 257234949Sbapt return code; 258234949Sbapt} 259234949Sbapt 260234949Sbaptstatic int 261234949Sbaptkeyword(void) 262234949Sbapt{ 263234949Sbapt int c; 264234949Sbapt char *t_cptr = cptr; 265234949Sbapt 266234949Sbapt c = *++cptr; 267234949Sbapt if (isalpha(c)) 268234949Sbapt { 269234949Sbapt cinc = 0; 270234949Sbapt for (;;) 271234949Sbapt { 272234949Sbapt if (isalpha(c)) 273234949Sbapt { 274234949Sbapt if (isupper(c)) 275234949Sbapt c = tolower(c); 276234949Sbapt cachec(c); 277234949Sbapt } 278234949Sbapt else if (isdigit(c) 279234949Sbapt || c == '-' 280234949Sbapt || c == '_' 281234949Sbapt || c == '.' 282234949Sbapt || c == '$') 283234949Sbapt { 284234949Sbapt cachec(c); 285234949Sbapt } 286234949Sbapt else 287234949Sbapt { 288234949Sbapt break; 289234949Sbapt } 290234949Sbapt c = *++cptr; 291234949Sbapt } 292234949Sbapt cachec(NUL); 293234949Sbapt 294234949Sbapt if (matchec("token") || matchec("term")) 295234949Sbapt return (TOKEN); 296234949Sbapt if (matchec("type")) 297234949Sbapt return (TYPE); 298234949Sbapt if (matchec("left")) 299234949Sbapt return (LEFT); 300234949Sbapt if (matchec("right")) 301234949Sbapt return (RIGHT); 302234949Sbapt if (matchec("nonassoc") || matchec("binary")) 303234949Sbapt return (NONASSOC); 304234949Sbapt if (matchec("start")) 305234949Sbapt return (START); 306234949Sbapt if (matchec("union")) 307234949Sbapt return (UNION); 308234949Sbapt if (matchec("ident")) 309234949Sbapt return (IDENT); 310234949Sbapt if (matchec("expect")) 311234949Sbapt return (EXPECT); 312234949Sbapt if (matchec("expect-rr")) 313234949Sbapt return (EXPECT_RR); 314234949Sbapt if (matchec("pure-parser")) 315234949Sbapt return (PURE_PARSER); 316234949Sbapt if (matchec("parse-param")) 317234949Sbapt return (PARSE_PARAM); 318234949Sbapt if (matchec("lex-param")) 319234949Sbapt return (LEX_PARAM); 320234949Sbapt if (matchec("yacc")) 321234949Sbapt return (POSIX_YACC); 322234949Sbapt } 323234949Sbapt else 324234949Sbapt { 325234949Sbapt ++cptr; 326234949Sbapt if (c == L_CURL) 327234949Sbapt return (TEXT); 328234949Sbapt if (c == '%' || c == '\\') 329234949Sbapt return (MARK); 330234949Sbapt if (c == '<') 331234949Sbapt return (LEFT); 332234949Sbapt if (c == '>') 333234949Sbapt return (RIGHT); 334234949Sbapt if (c == '0') 335234949Sbapt return (TOKEN); 336234949Sbapt if (c == '2') 337234949Sbapt return (NONASSOC); 338234949Sbapt } 339234949Sbapt syntax_error(lineno, line, t_cptr); 340234949Sbapt /*NOTREACHED */ 341235723Sbapt return (-1); 342234949Sbapt} 343234949Sbapt 344234949Sbaptstatic void 345234949Sbaptcopy_ident(void) 346234949Sbapt{ 347234949Sbapt int c; 348234949Sbapt FILE *f = output_file; 349234949Sbapt 350234949Sbapt c = nextc(); 351234949Sbapt if (c == EOF) 352234949Sbapt unexpected_EOF(); 353234949Sbapt if (c != '"') 354234949Sbapt syntax_error(lineno, line, cptr); 355234949Sbapt ++outline; 356234949Sbapt fprintf(f, "#ident \""); 357234949Sbapt for (;;) 358234949Sbapt { 359234949Sbapt c = *++cptr; 360234949Sbapt if (c == '\n') 361234949Sbapt { 362234949Sbapt fprintf(f, "\"\n"); 363234949Sbapt return; 364234949Sbapt } 365234949Sbapt putc(c, f); 366234949Sbapt if (c == '"') 367234949Sbapt { 368234949Sbapt putc('\n', f); 369234949Sbapt ++cptr; 370234949Sbapt return; 371234949Sbapt } 372234949Sbapt } 373234949Sbapt} 374234949Sbapt 375234949Sbaptstatic void 376234949Sbaptcopy_text(void) 377234949Sbapt{ 378234949Sbapt int c; 379234949Sbapt int quote; 380234949Sbapt FILE *f = text_file; 381234949Sbapt int need_newline = 0; 382234949Sbapt int t_lineno = lineno; 383234949Sbapt char *t_line = dup_line(); 384234949Sbapt char *t_cptr = t_line + (cptr - line - 2); 385234949Sbapt 386234949Sbapt if (*cptr == '\n') 387234949Sbapt { 388234949Sbapt get_line(); 389234949Sbapt if (line == 0) 390234949Sbapt unterminated_text(t_lineno, t_line, t_cptr); 391234949Sbapt } 392234949Sbapt if (!lflag) 393234949Sbapt fprintf(f, line_format, lineno, input_file_name); 394234949Sbapt 395234949Sbapt loop: 396234949Sbapt c = *cptr++; 397234949Sbapt switch (c) 398234949Sbapt { 399234949Sbapt case '\n': 400234949Sbapt next_line: 401234949Sbapt putc('\n', f); 402234949Sbapt need_newline = 0; 403234949Sbapt get_line(); 404234949Sbapt if (line) 405234949Sbapt goto loop; 406234949Sbapt unterminated_text(t_lineno, t_line, t_cptr); 407234949Sbapt 408234949Sbapt case '\'': 409234949Sbapt case '"': 410234949Sbapt { 411234949Sbapt int s_lineno = lineno; 412234949Sbapt char *s_line = dup_line(); 413234949Sbapt char *s_cptr = s_line + (cptr - line - 1); 414234949Sbapt 415234949Sbapt quote = c; 416234949Sbapt putc(c, f); 417234949Sbapt for (;;) 418234949Sbapt { 419234949Sbapt c = *cptr++; 420234949Sbapt putc(c, f); 421234949Sbapt if (c == quote) 422234949Sbapt { 423234949Sbapt need_newline = 1; 424234949Sbapt FREE(s_line); 425234949Sbapt goto loop; 426234949Sbapt } 427234949Sbapt if (c == '\n') 428234949Sbapt unterminated_string(s_lineno, s_line, s_cptr); 429234949Sbapt if (c == '\\') 430234949Sbapt { 431234949Sbapt c = *cptr++; 432234949Sbapt putc(c, f); 433234949Sbapt if (c == '\n') 434234949Sbapt { 435234949Sbapt get_line(); 436234949Sbapt if (line == 0) 437234949Sbapt unterminated_string(s_lineno, s_line, s_cptr); 438234949Sbapt } 439234949Sbapt } 440234949Sbapt } 441234949Sbapt } 442234949Sbapt 443234949Sbapt case '/': 444234949Sbapt putc(c, f); 445234949Sbapt need_newline = 1; 446234949Sbapt c = *cptr; 447234949Sbapt if (c == '/') 448234949Sbapt { 449234949Sbapt putc('*', f); 450234949Sbapt while ((c = *++cptr) != '\n') 451234949Sbapt { 452234949Sbapt if (c == '*' && cptr[1] == '/') 453234949Sbapt fprintf(f, "* "); 454234949Sbapt else 455234949Sbapt putc(c, f); 456234949Sbapt } 457234949Sbapt fprintf(f, "*/"); 458234949Sbapt goto next_line; 459234949Sbapt } 460234949Sbapt if (c == '*') 461234949Sbapt { 462234949Sbapt int c_lineno = lineno; 463234949Sbapt char *c_line = dup_line(); 464234949Sbapt char *c_cptr = c_line + (cptr - line - 1); 465234949Sbapt 466234949Sbapt putc('*', f); 467234949Sbapt ++cptr; 468234949Sbapt for (;;) 469234949Sbapt { 470234949Sbapt c = *cptr++; 471234949Sbapt putc(c, f); 472234949Sbapt if (c == '*' && *cptr == '/') 473234949Sbapt { 474234949Sbapt putc('/', f); 475234949Sbapt ++cptr; 476234949Sbapt FREE(c_line); 477234949Sbapt goto loop; 478234949Sbapt } 479234949Sbapt if (c == '\n') 480234949Sbapt { 481234949Sbapt get_line(); 482234949Sbapt if (line == 0) 483234949Sbapt unterminated_comment(c_lineno, c_line, c_cptr); 484234949Sbapt } 485234949Sbapt } 486234949Sbapt } 487234949Sbapt need_newline = 1; 488234949Sbapt goto loop; 489234949Sbapt 490234949Sbapt case '%': 491234949Sbapt case '\\': 492234949Sbapt if (*cptr == R_CURL) 493234949Sbapt { 494234949Sbapt if (need_newline) 495234949Sbapt putc('\n', f); 496234949Sbapt ++cptr; 497234949Sbapt FREE(t_line); 498234949Sbapt return; 499234949Sbapt } 500234949Sbapt /* FALLTHRU */ 501234949Sbapt 502234949Sbapt default: 503234949Sbapt putc(c, f); 504234949Sbapt need_newline = 1; 505234949Sbapt goto loop; 506234949Sbapt } 507234949Sbapt} 508234949Sbapt 509234949Sbaptstatic void 510234949Sbaptputs_both(const char *s) 511234949Sbapt{ 512234949Sbapt fputs(s, text_file); 513234949Sbapt if (dflag) 514234949Sbapt fputs(s, union_file); 515234949Sbapt} 516234949Sbapt 517234949Sbaptstatic void 518234949Sbaptputc_both(int c) 519234949Sbapt{ 520234949Sbapt putc(c, text_file); 521234949Sbapt if (dflag) 522234949Sbapt putc(c, union_file); 523234949Sbapt} 524234949Sbapt 525234949Sbaptstatic void 526234949Sbaptcopy_union(void) 527234949Sbapt{ 528234949Sbapt int c; 529234949Sbapt int quote; 530234949Sbapt int depth; 531234949Sbapt int u_lineno = lineno; 532234949Sbapt char *u_line = dup_line(); 533234949Sbapt char *u_cptr = u_line + (cptr - line - 6); 534234949Sbapt 535234949Sbapt if (unionized) 536234949Sbapt over_unionized(cptr - 6); 537234949Sbapt unionized = 1; 538234949Sbapt 539234949Sbapt if (!lflag) 540234949Sbapt fprintf(text_file, line_format, lineno, input_file_name); 541234949Sbapt 542234949Sbapt puts_both("#ifdef YYSTYPE\n"); 543234949Sbapt puts_both("#undef YYSTYPE_IS_DECLARED\n"); 544234949Sbapt puts_both("#define YYSTYPE_IS_DECLARED 1\n"); 545234949Sbapt puts_both("#endif\n"); 546234949Sbapt puts_both("#ifndef YYSTYPE_IS_DECLARED\n"); 547234949Sbapt puts_both("#define YYSTYPE_IS_DECLARED 1\n"); 548234949Sbapt puts_both("typedef union"); 549234949Sbapt 550234949Sbapt depth = 0; 551234949Sbapt loop: 552234949Sbapt c = *cptr++; 553234949Sbapt putc_both(c); 554234949Sbapt switch (c) 555234949Sbapt { 556234949Sbapt case '\n': 557234949Sbapt next_line: 558234949Sbapt get_line(); 559234949Sbapt if (line == 0) 560234949Sbapt unterminated_union(u_lineno, u_line, u_cptr); 561234949Sbapt goto loop; 562234949Sbapt 563234949Sbapt case L_CURL: 564234949Sbapt ++depth; 565234949Sbapt goto loop; 566234949Sbapt 567234949Sbapt case R_CURL: 568234949Sbapt if (--depth == 0) 569234949Sbapt { 570234949Sbapt puts_both(" YYSTYPE;\n"); 571234949Sbapt puts_both("#endif /* !YYSTYPE_IS_DECLARED */\n"); 572234949Sbapt FREE(u_line); 573234949Sbapt return; 574234949Sbapt } 575234949Sbapt goto loop; 576234949Sbapt 577234949Sbapt case '\'': 578234949Sbapt case '"': 579234949Sbapt { 580234949Sbapt int s_lineno = lineno; 581234949Sbapt char *s_line = dup_line(); 582234949Sbapt char *s_cptr = s_line + (cptr - line - 1); 583234949Sbapt 584234949Sbapt quote = c; 585234949Sbapt for (;;) 586234949Sbapt { 587234949Sbapt c = *cptr++; 588234949Sbapt putc_both(c); 589234949Sbapt if (c == quote) 590234949Sbapt { 591234949Sbapt FREE(s_line); 592234949Sbapt goto loop; 593234949Sbapt } 594234949Sbapt if (c == '\n') 595234949Sbapt unterminated_string(s_lineno, s_line, s_cptr); 596234949Sbapt if (c == '\\') 597234949Sbapt { 598234949Sbapt c = *cptr++; 599234949Sbapt putc_both(c); 600234949Sbapt if (c == '\n') 601234949Sbapt { 602234949Sbapt get_line(); 603234949Sbapt if (line == 0) 604234949Sbapt unterminated_string(s_lineno, s_line, s_cptr); 605234949Sbapt } 606234949Sbapt } 607234949Sbapt } 608234949Sbapt } 609234949Sbapt 610234949Sbapt case '/': 611234949Sbapt c = *cptr; 612234949Sbapt if (c == '/') 613234949Sbapt { 614234949Sbapt putc_both('*'); 615234949Sbapt while ((c = *++cptr) != '\n') 616234949Sbapt { 617234949Sbapt if (c == '*' && cptr[1] == '/') 618234949Sbapt { 619234949Sbapt puts_both("* "); 620234949Sbapt } 621234949Sbapt else 622234949Sbapt { 623234949Sbapt putc_both(c); 624234949Sbapt } 625234949Sbapt } 626234949Sbapt puts_both("*/\n"); 627234949Sbapt goto next_line; 628234949Sbapt } 629234949Sbapt if (c == '*') 630234949Sbapt { 631234949Sbapt int c_lineno = lineno; 632234949Sbapt char *c_line = dup_line(); 633234949Sbapt char *c_cptr = c_line + (cptr - line - 1); 634234949Sbapt 635234949Sbapt putc_both('*'); 636234949Sbapt ++cptr; 637234949Sbapt for (;;) 638234949Sbapt { 639234949Sbapt c = *cptr++; 640234949Sbapt putc_both(c); 641234949Sbapt if (c == '*' && *cptr == '/') 642234949Sbapt { 643234949Sbapt putc_both('/'); 644234949Sbapt ++cptr; 645234949Sbapt FREE(c_line); 646234949Sbapt goto loop; 647234949Sbapt } 648234949Sbapt if (c == '\n') 649234949Sbapt { 650234949Sbapt get_line(); 651234949Sbapt if (line == 0) 652234949Sbapt unterminated_comment(c_lineno, c_line, c_cptr); 653234949Sbapt } 654234949Sbapt } 655234949Sbapt } 656234949Sbapt goto loop; 657234949Sbapt 658234949Sbapt default: 659234949Sbapt goto loop; 660234949Sbapt } 661234949Sbapt} 662234949Sbapt 663234949Sbapt/* 664234949Sbapt * Keep a linked list of parameters 665234949Sbapt */ 666234949Sbaptstatic void 667234949Sbaptcopy_param(int k) 668234949Sbapt{ 669234949Sbapt char *buf; 670234949Sbapt int c; 671234949Sbapt param *head, *p; 672234949Sbapt int i; 673234949Sbapt int name, type2; 674234949Sbapt 675234949Sbapt c = nextc(); 676234949Sbapt if (c == EOF) 677234949Sbapt unexpected_EOF(); 678234949Sbapt if (c != '{') 679234949Sbapt goto out; 680234949Sbapt cptr++; 681234949Sbapt 682234949Sbapt c = nextc(); 683234949Sbapt if (c == EOF) 684234949Sbapt unexpected_EOF(); 685234949Sbapt if (c == '}') 686234949Sbapt goto out; 687234949Sbapt 688234949Sbapt buf = MALLOC(linesize); 689234949Sbapt NO_SPACE(buf); 690234949Sbapt 691234949Sbapt for (i = 0; (c = *cptr++) != '}'; i++) 692234949Sbapt { 693234949Sbapt if (c == '\0') 694234949Sbapt missing_brace(); 695234949Sbapt if (c == EOF) 696234949Sbapt unexpected_EOF(); 697234949Sbapt buf[i] = (char)c; 698234949Sbapt } 699234949Sbapt 700234949Sbapt if (i == 0) 701234949Sbapt goto out; 702234949Sbapt 703234949Sbapt buf[i--] = '\0'; 704234949Sbapt while (i >= 0 && isspace(UCH(buf[i]))) 705234949Sbapt buf[i--] = '\0'; 706234949Sbapt 707234949Sbapt if (buf[i] == ']') 708234949Sbapt { 709234949Sbapt int level = 1; 710234949Sbapt while (i >= 0 && level > 0 && buf[i] != '[') 711234949Sbapt { 712234949Sbapt if (buf[i] == ']') 713234949Sbapt ++level; 714234949Sbapt else if (buf[i] == '[') 715234949Sbapt --level; 716234949Sbapt i--; 717234949Sbapt } 718234949Sbapt if (i <= 0) 719234949Sbapt unexpected_EOF(); 720234949Sbapt type2 = i--; 721234949Sbapt } 722234949Sbapt else 723234949Sbapt { 724234949Sbapt type2 = i + 1; 725234949Sbapt } 726234949Sbapt 727234949Sbapt while (i >= 0 && (isalnum(UCH(buf[i])) || 728234949Sbapt UCH(buf[i]) == '_')) 729234949Sbapt i--; 730234949Sbapt 731234949Sbapt if (!isspace(UCH(buf[i])) && buf[i] != '*') 732234949Sbapt goto out; 733234949Sbapt 734234949Sbapt name = i + 1; 735234949Sbapt 736234949Sbapt p = MALLOC(sizeof(*p)); 737234949Sbapt NO_SPACE(p); 738234949Sbapt 739234949Sbapt p->type2 = strdup(buf + type2); 740234949Sbapt NO_SPACE(p->type2); 741234949Sbapt 742234949Sbapt buf[type2] = '\0'; 743234949Sbapt 744234949Sbapt p->name = strdup(buf + name); 745234949Sbapt NO_SPACE(p->name); 746234949Sbapt 747234949Sbapt buf[name] = '\0'; 748234949Sbapt p->type = buf; 749234949Sbapt 750234949Sbapt if (k == LEX_PARAM) 751234949Sbapt head = lex_param; 752234949Sbapt else 753234949Sbapt head = parse_param; 754234949Sbapt 755234949Sbapt if (head != NULL) 756234949Sbapt { 757234949Sbapt while (head->next) 758234949Sbapt head = head->next; 759234949Sbapt head->next = p; 760234949Sbapt } 761234949Sbapt else 762234949Sbapt { 763234949Sbapt if (k == LEX_PARAM) 764234949Sbapt lex_param = p; 765234949Sbapt else 766234949Sbapt parse_param = p; 767234949Sbapt } 768234949Sbapt p->next = NULL; 769234949Sbapt return; 770234949Sbapt 771234949Sbapt out: 772234949Sbapt syntax_error(lineno, line, cptr); 773234949Sbapt} 774234949Sbapt 775234949Sbaptstatic int 776234949Sbapthexval(int c) 777234949Sbapt{ 778234949Sbapt if (c >= '0' && c <= '9') 779234949Sbapt return (c - '0'); 780234949Sbapt if (c >= 'A' && c <= 'F') 781234949Sbapt return (c - 'A' + 10); 782234949Sbapt if (c >= 'a' && c <= 'f') 783234949Sbapt return (c - 'a' + 10); 784234949Sbapt return (-1); 785234949Sbapt} 786234949Sbapt 787234949Sbaptstatic bucket * 788234949Sbaptget_literal(void) 789234949Sbapt{ 790234949Sbapt int c, quote; 791234949Sbapt int i; 792234949Sbapt int n; 793234949Sbapt char *s; 794234949Sbapt bucket *bp; 795234949Sbapt int s_lineno = lineno; 796234949Sbapt char *s_line = dup_line(); 797234949Sbapt char *s_cptr = s_line + (cptr - line); 798234949Sbapt 799234949Sbapt quote = *cptr++; 800234949Sbapt cinc = 0; 801234949Sbapt for (;;) 802234949Sbapt { 803234949Sbapt c = *cptr++; 804234949Sbapt if (c == quote) 805234949Sbapt break; 806234949Sbapt if (c == '\n') 807234949Sbapt unterminated_string(s_lineno, s_line, s_cptr); 808234949Sbapt if (c == '\\') 809234949Sbapt { 810234949Sbapt char *c_cptr = cptr - 1; 811234949Sbapt 812234949Sbapt c = *cptr++; 813234949Sbapt switch (c) 814234949Sbapt { 815234949Sbapt case '\n': 816234949Sbapt get_line(); 817234949Sbapt if (line == 0) 818234949Sbapt unterminated_string(s_lineno, s_line, s_cptr); 819234949Sbapt continue; 820234949Sbapt 821234949Sbapt case '0': 822234949Sbapt case '1': 823234949Sbapt case '2': 824234949Sbapt case '3': 825234949Sbapt case '4': 826234949Sbapt case '5': 827234949Sbapt case '6': 828234949Sbapt case '7': 829234949Sbapt n = c - '0'; 830234949Sbapt c = *cptr; 831234949Sbapt if (IS_OCTAL(c)) 832234949Sbapt { 833234949Sbapt n = (n << 3) + (c - '0'); 834234949Sbapt c = *++cptr; 835234949Sbapt if (IS_OCTAL(c)) 836234949Sbapt { 837234949Sbapt n = (n << 3) + (c - '0'); 838234949Sbapt ++cptr; 839234949Sbapt } 840234949Sbapt } 841234949Sbapt if (n > MAXCHAR) 842234949Sbapt illegal_character(c_cptr); 843234949Sbapt c = n; 844234949Sbapt break; 845234949Sbapt 846234949Sbapt case 'x': 847234949Sbapt c = *cptr++; 848234949Sbapt n = hexval(c); 849234949Sbapt if (n < 0 || n >= 16) 850234949Sbapt illegal_character(c_cptr); 851234949Sbapt for (;;) 852234949Sbapt { 853234949Sbapt c = *cptr; 854234949Sbapt i = hexval(c); 855234949Sbapt if (i < 0 || i >= 16) 856234949Sbapt break; 857234949Sbapt ++cptr; 858234949Sbapt n = (n << 4) + i; 859234949Sbapt if (n > MAXCHAR) 860234949Sbapt illegal_character(c_cptr); 861234949Sbapt } 862234949Sbapt c = n; 863234949Sbapt break; 864234949Sbapt 865234949Sbapt case 'a': 866234949Sbapt c = 7; 867234949Sbapt break; 868234949Sbapt case 'b': 869234949Sbapt c = '\b'; 870234949Sbapt break; 871234949Sbapt case 'f': 872234949Sbapt c = '\f'; 873234949Sbapt break; 874234949Sbapt case 'n': 875234949Sbapt c = '\n'; 876234949Sbapt break; 877234949Sbapt case 'r': 878234949Sbapt c = '\r'; 879234949Sbapt break; 880234949Sbapt case 't': 881234949Sbapt c = '\t'; 882234949Sbapt break; 883234949Sbapt case 'v': 884234949Sbapt c = '\v'; 885234949Sbapt break; 886234949Sbapt } 887234949Sbapt } 888234949Sbapt cachec(c); 889234949Sbapt } 890234949Sbapt FREE(s_line); 891234949Sbapt 892234949Sbapt n = cinc; 893234949Sbapt s = MALLOC(n); 894234949Sbapt NO_SPACE(s); 895234949Sbapt 896234949Sbapt for (i = 0; i < n; ++i) 897234949Sbapt s[i] = cache[i]; 898234949Sbapt 899234949Sbapt cinc = 0; 900234949Sbapt if (n == 1) 901234949Sbapt cachec('\''); 902234949Sbapt else 903234949Sbapt cachec('"'); 904234949Sbapt 905234949Sbapt for (i = 0; i < n; ++i) 906234949Sbapt { 907234949Sbapt c = UCH(s[i]); 908234949Sbapt if (c == '\\' || c == cache[0]) 909234949Sbapt { 910234949Sbapt cachec('\\'); 911234949Sbapt cachec(c); 912234949Sbapt } 913234949Sbapt else if (isprint(c)) 914234949Sbapt cachec(c); 915234949Sbapt else 916234949Sbapt { 917234949Sbapt cachec('\\'); 918234949Sbapt switch (c) 919234949Sbapt { 920234949Sbapt case 7: 921234949Sbapt cachec('a'); 922234949Sbapt break; 923234949Sbapt case '\b': 924234949Sbapt cachec('b'); 925234949Sbapt break; 926234949Sbapt case '\f': 927234949Sbapt cachec('f'); 928234949Sbapt break; 929234949Sbapt case '\n': 930234949Sbapt cachec('n'); 931234949Sbapt break; 932234949Sbapt case '\r': 933234949Sbapt cachec('r'); 934234949Sbapt break; 935234949Sbapt case '\t': 936234949Sbapt cachec('t'); 937234949Sbapt break; 938234949Sbapt case '\v': 939234949Sbapt cachec('v'); 940234949Sbapt break; 941234949Sbapt default: 942234949Sbapt cachec(((c >> 6) & 7) + '0'); 943234949Sbapt cachec(((c >> 3) & 7) + '0'); 944234949Sbapt cachec((c & 7) + '0'); 945234949Sbapt break; 946234949Sbapt } 947234949Sbapt } 948234949Sbapt } 949234949Sbapt 950234949Sbapt if (n == 1) 951234949Sbapt cachec('\''); 952234949Sbapt else 953234949Sbapt cachec('"'); 954234949Sbapt 955234949Sbapt cachec(NUL); 956234949Sbapt bp = lookup(cache); 957234949Sbapt bp->class = TERM; 958234949Sbapt if (n == 1 && bp->value == UNDEFINED) 959234949Sbapt bp->value = UCH(*s); 960234949Sbapt FREE(s); 961234949Sbapt 962234949Sbapt return (bp); 963234949Sbapt} 964234949Sbapt 965234949Sbaptstatic int 966234949Sbaptis_reserved(char *name) 967234949Sbapt{ 968234949Sbapt char *s; 969234949Sbapt 970234949Sbapt if (strcmp(name, ".") == 0 || 971234949Sbapt strcmp(name, "$accept") == 0 || 972234949Sbapt strcmp(name, "$end") == 0) 973234949Sbapt return (1); 974234949Sbapt 975234949Sbapt if (name[0] == '$' && name[1] == '$' && isdigit(UCH(name[2]))) 976234949Sbapt { 977234949Sbapt s = name + 3; 978234949Sbapt while (isdigit(UCH(*s))) 979234949Sbapt ++s; 980234949Sbapt if (*s == NUL) 981234949Sbapt return (1); 982234949Sbapt } 983234949Sbapt 984234949Sbapt return (0); 985234949Sbapt} 986234949Sbapt 987234949Sbaptstatic bucket * 988234949Sbaptget_name(void) 989234949Sbapt{ 990234949Sbapt int c; 991234949Sbapt 992234949Sbapt cinc = 0; 993234949Sbapt for (c = *cptr; IS_IDENT(c); c = *++cptr) 994234949Sbapt cachec(c); 995234949Sbapt cachec(NUL); 996234949Sbapt 997234949Sbapt if (is_reserved(cache)) 998234949Sbapt used_reserved(cache); 999234949Sbapt 1000234949Sbapt return (lookup(cache)); 1001234949Sbapt} 1002234949Sbapt 1003234949Sbaptstatic Value_t 1004234949Sbaptget_number(void) 1005234949Sbapt{ 1006234949Sbapt int c; 1007234949Sbapt Value_t n; 1008234949Sbapt 1009234949Sbapt n = 0; 1010234949Sbapt for (c = *cptr; isdigit(c); c = *++cptr) 1011234949Sbapt n = (Value_t) (10 * n + (c - '0')); 1012234949Sbapt 1013234949Sbapt return (n); 1014234949Sbapt} 1015234949Sbapt 1016234949Sbaptstatic char * 1017234949Sbaptget_tag(void) 1018234949Sbapt{ 1019234949Sbapt int c; 1020234949Sbapt int i; 1021234949Sbapt char *s; 1022234949Sbapt int t_lineno = lineno; 1023234949Sbapt char *t_line = dup_line(); 1024234949Sbapt char *t_cptr = t_line + (cptr - line); 1025234949Sbapt 1026234949Sbapt ++cptr; 1027234949Sbapt c = nextc(); 1028234949Sbapt if (c == EOF) 1029234949Sbapt unexpected_EOF(); 1030234949Sbapt if (!isalpha(c) && c != '_' && c != '$') 1031234949Sbapt illegal_tag(t_lineno, t_line, t_cptr); 1032234949Sbapt 1033234949Sbapt cinc = 0; 1034234949Sbapt do 1035234949Sbapt { 1036234949Sbapt cachec(c); 1037234949Sbapt c = *++cptr; 1038234949Sbapt } 1039234949Sbapt while (IS_IDENT(c)); 1040234949Sbapt cachec(NUL); 1041234949Sbapt 1042234949Sbapt c = nextc(); 1043234949Sbapt if (c == EOF) 1044234949Sbapt unexpected_EOF(); 1045234949Sbapt if (c != '>') 1046234949Sbapt illegal_tag(t_lineno, t_line, t_cptr); 1047234949Sbapt ++cptr; 1048234949Sbapt 1049234949Sbapt for (i = 0; i < ntags; ++i) 1050234949Sbapt { 1051234949Sbapt if (strcmp(cache, tag_table[i]) == 0) 1052234949Sbapt { 1053234949Sbapt FREE(t_line); 1054234949Sbapt return (tag_table[i]); 1055234949Sbapt } 1056234949Sbapt } 1057234949Sbapt 1058234949Sbapt if (ntags >= tagmax) 1059234949Sbapt { 1060234949Sbapt tagmax += 16; 1061234949Sbapt tag_table = (char **) 1062234949Sbapt (tag_table 1063234949Sbapt ? REALLOC(tag_table, (unsigned)tagmax * sizeof(char *)) 1064234949Sbapt : MALLOC((unsigned)tagmax * sizeof(char *))); 1065234949Sbapt NO_SPACE(tag_table); 1066234949Sbapt } 1067234949Sbapt 1068234949Sbapt s = MALLOC(cinc); 1069234949Sbapt NO_SPACE(s); 1070234949Sbapt 1071234949Sbapt strcpy(s, cache); 1072234949Sbapt tag_table[ntags] = s; 1073234949Sbapt ++ntags; 1074234949Sbapt FREE(t_line); 1075234949Sbapt return (s); 1076234949Sbapt} 1077234949Sbapt 1078234949Sbaptstatic void 1079234949Sbaptdeclare_tokens(int assoc) 1080234949Sbapt{ 1081234949Sbapt int c; 1082234949Sbapt bucket *bp; 1083234949Sbapt Value_t value; 1084234949Sbapt char *tag = 0; 1085234949Sbapt 1086234949Sbapt if (assoc != TOKEN) 1087234949Sbapt ++prec; 1088234949Sbapt 1089234949Sbapt c = nextc(); 1090234949Sbapt if (c == EOF) 1091234949Sbapt unexpected_EOF(); 1092234949Sbapt if (c == '<') 1093234949Sbapt { 1094234949Sbapt tag = get_tag(); 1095234949Sbapt c = nextc(); 1096234949Sbapt if (c == EOF) 1097234949Sbapt unexpected_EOF(); 1098234949Sbapt } 1099234949Sbapt 1100234949Sbapt for (;;) 1101234949Sbapt { 1102234949Sbapt if (isalpha(c) || c == '_' || c == '.' || c == '$') 1103234949Sbapt bp = get_name(); 1104234949Sbapt else if (c == '\'' || c == '"') 1105234949Sbapt bp = get_literal(); 1106234949Sbapt else 1107234949Sbapt return; 1108234949Sbapt 1109234949Sbapt if (bp == goal) 1110234949Sbapt tokenized_start(bp->name); 1111234949Sbapt bp->class = TERM; 1112234949Sbapt 1113234949Sbapt if (tag) 1114234949Sbapt { 1115234949Sbapt if (bp->tag && tag != bp->tag) 1116234949Sbapt retyped_warning(bp->name); 1117234949Sbapt bp->tag = tag; 1118234949Sbapt } 1119234949Sbapt 1120234949Sbapt if (assoc != TOKEN) 1121234949Sbapt { 1122234949Sbapt if (bp->prec && prec != bp->prec) 1123234949Sbapt reprec_warning(bp->name); 1124234949Sbapt bp->assoc = (Assoc_t) assoc; 1125234949Sbapt bp->prec = prec; 1126234949Sbapt } 1127234949Sbapt 1128234949Sbapt c = nextc(); 1129234949Sbapt if (c == EOF) 1130234949Sbapt unexpected_EOF(); 1131234949Sbapt 1132234949Sbapt if (isdigit(c)) 1133234949Sbapt { 1134234949Sbapt value = get_number(); 1135234949Sbapt if (bp->value != UNDEFINED && value != bp->value) 1136234949Sbapt revalued_warning(bp->name); 1137234949Sbapt bp->value = value; 1138234949Sbapt c = nextc(); 1139234949Sbapt if (c == EOF) 1140234949Sbapt unexpected_EOF(); 1141234949Sbapt } 1142234949Sbapt } 1143234949Sbapt} 1144234949Sbapt 1145234949Sbapt/* 1146234949Sbapt * %expect requires special handling 1147234949Sbapt * as it really isn't part of the yacc 1148234949Sbapt * grammar only a flag for yacc proper. 1149234949Sbapt */ 1150234949Sbaptstatic void 1151234949Sbaptdeclare_expect(int assoc) 1152234949Sbapt{ 1153234949Sbapt int c; 1154234949Sbapt 1155234949Sbapt if (assoc != EXPECT && assoc != EXPECT_RR) 1156234949Sbapt ++prec; 1157234949Sbapt 1158234949Sbapt /* 1159234949Sbapt * Stay away from nextc - doesn't 1160234949Sbapt * detect EOL and will read to EOF. 1161234949Sbapt */ 1162234949Sbapt c = *++cptr; 1163234949Sbapt if (c == EOF) 1164234949Sbapt unexpected_EOF(); 1165234949Sbapt 1166234949Sbapt for (;;) 1167234949Sbapt { 1168234949Sbapt if (isdigit(c)) 1169234949Sbapt { 1170234949Sbapt if (assoc == EXPECT) 1171234949Sbapt SRexpect = get_number(); 1172234949Sbapt else 1173234949Sbapt RRexpect = get_number(); 1174234949Sbapt break; 1175234949Sbapt } 1176234949Sbapt /* 1177234949Sbapt * Looking for number before EOL. 1178234949Sbapt * Spaces, tabs, and numbers are ok, 1179234949Sbapt * words, punc., etc. are syntax errors. 1180234949Sbapt */ 1181234949Sbapt else if (c == '\n' || isalpha(c) || !isspace(c)) 1182234949Sbapt { 1183234949Sbapt syntax_error(lineno, line, cptr); 1184234949Sbapt } 1185234949Sbapt else 1186234949Sbapt { 1187234949Sbapt c = *++cptr; 1188234949Sbapt if (c == EOF) 1189234949Sbapt unexpected_EOF(); 1190234949Sbapt } 1191234949Sbapt } 1192234949Sbapt} 1193234949Sbapt 1194234949Sbaptstatic void 1195234949Sbaptdeclare_types(void) 1196234949Sbapt{ 1197234949Sbapt int c; 1198234949Sbapt bucket *bp; 1199234949Sbapt char *tag; 1200234949Sbapt 1201234949Sbapt c = nextc(); 1202234949Sbapt if (c == EOF) 1203234949Sbapt unexpected_EOF(); 1204234949Sbapt if (c != '<') 1205234949Sbapt syntax_error(lineno, line, cptr); 1206234949Sbapt tag = get_tag(); 1207234949Sbapt 1208234949Sbapt for (;;) 1209234949Sbapt { 1210234949Sbapt c = nextc(); 1211234949Sbapt if (isalpha(c) || c == '_' || c == '.' || c == '$') 1212234949Sbapt bp = get_name(); 1213234949Sbapt else if (c == '\'' || c == '"') 1214234949Sbapt bp = get_literal(); 1215234949Sbapt else 1216234949Sbapt return; 1217234949Sbapt 1218234949Sbapt if (bp->tag && tag != bp->tag) 1219234949Sbapt retyped_warning(bp->name); 1220234949Sbapt bp->tag = tag; 1221234949Sbapt } 1222234949Sbapt} 1223234949Sbapt 1224234949Sbaptstatic void 1225234949Sbaptdeclare_start(void) 1226234949Sbapt{ 1227234949Sbapt int c; 1228234949Sbapt bucket *bp; 1229234949Sbapt 1230234949Sbapt c = nextc(); 1231234949Sbapt if (c == EOF) 1232234949Sbapt unexpected_EOF(); 1233234949Sbapt if (!isalpha(c) && c != '_' && c != '.' && c != '$') 1234234949Sbapt syntax_error(lineno, line, cptr); 1235234949Sbapt bp = get_name(); 1236234949Sbapt if (bp->class == TERM) 1237234949Sbapt terminal_start(bp->name); 1238234949Sbapt if (goal && goal != bp) 1239234949Sbapt restarted_warning(); 1240234949Sbapt goal = bp; 1241234949Sbapt} 1242234949Sbapt 1243234949Sbaptstatic void 1244234949Sbaptread_declarations(void) 1245234949Sbapt{ 1246234949Sbapt int c, k; 1247234949Sbapt 1248234949Sbapt cache_size = 256; 1249234949Sbapt cache = MALLOC(cache_size); 1250234949Sbapt NO_SPACE(cache); 1251234949Sbapt 1252234949Sbapt for (;;) 1253234949Sbapt { 1254234949Sbapt c = nextc(); 1255234949Sbapt if (c == EOF) 1256234949Sbapt unexpected_EOF(); 1257234949Sbapt if (c != '%') 1258234949Sbapt syntax_error(lineno, line, cptr); 1259234949Sbapt switch (k = keyword()) 1260234949Sbapt { 1261234949Sbapt case MARK: 1262234949Sbapt return; 1263234949Sbapt 1264234949Sbapt case IDENT: 1265234949Sbapt copy_ident(); 1266234949Sbapt break; 1267234949Sbapt 1268234949Sbapt case TEXT: 1269234949Sbapt copy_text(); 1270234949Sbapt break; 1271234949Sbapt 1272234949Sbapt case UNION: 1273234949Sbapt copy_union(); 1274234949Sbapt break; 1275234949Sbapt 1276234949Sbapt case TOKEN: 1277234949Sbapt case LEFT: 1278234949Sbapt case RIGHT: 1279234949Sbapt case NONASSOC: 1280234949Sbapt declare_tokens(k); 1281234949Sbapt break; 1282234949Sbapt 1283234949Sbapt case EXPECT: 1284234949Sbapt case EXPECT_RR: 1285234949Sbapt declare_expect(k); 1286234949Sbapt break; 1287234949Sbapt 1288234949Sbapt case TYPE: 1289234949Sbapt declare_types(); 1290234949Sbapt break; 1291234949Sbapt 1292234949Sbapt case START: 1293234949Sbapt declare_start(); 1294234949Sbapt break; 1295234949Sbapt 1296234949Sbapt case PURE_PARSER: 1297234949Sbapt pure_parser = 1; 1298234949Sbapt break; 1299234949Sbapt 1300234949Sbapt case PARSE_PARAM: 1301234949Sbapt case LEX_PARAM: 1302234949Sbapt copy_param(k); 1303234949Sbapt break; 1304234949Sbapt 1305234949Sbapt case POSIX_YACC: 1306234949Sbapt /* noop for bison compatibility. byacc is already designed to be posix 1307234949Sbapt * yacc compatible. */ 1308234949Sbapt break; 1309234949Sbapt } 1310234949Sbapt } 1311234949Sbapt} 1312234949Sbapt 1313234949Sbaptstatic void 1314234949Sbaptinitialize_grammar(void) 1315234949Sbapt{ 1316234949Sbapt nitems = 4; 1317234949Sbapt maxitems = 300; 1318234949Sbapt 1319234949Sbapt pitem = (bucket **)MALLOC((unsigned)maxitems * sizeof(bucket *)); 1320234949Sbapt NO_SPACE(pitem); 1321234949Sbapt 1322234949Sbapt pitem[0] = 0; 1323234949Sbapt pitem[1] = 0; 1324234949Sbapt pitem[2] = 0; 1325234949Sbapt pitem[3] = 0; 1326234949Sbapt 1327234949Sbapt nrules = 3; 1328234949Sbapt maxrules = 100; 1329234949Sbapt 1330234949Sbapt plhs = (bucket **)MALLOC((unsigned)maxrules * sizeof(bucket *)); 1331234949Sbapt NO_SPACE(plhs); 1332234949Sbapt 1333234949Sbapt plhs[0] = 0; 1334234949Sbapt plhs[1] = 0; 1335234949Sbapt plhs[2] = 0; 1336234949Sbapt 1337234949Sbapt rprec = (short *)MALLOC((unsigned)maxrules * sizeof(short)); 1338234949Sbapt NO_SPACE(rprec); 1339234949Sbapt 1340234949Sbapt rprec[0] = 0; 1341234949Sbapt rprec[1] = 0; 1342234949Sbapt rprec[2] = 0; 1343234949Sbapt 1344234949Sbapt rassoc = (char *)MALLOC((unsigned)maxrules * sizeof(char)); 1345234949Sbapt NO_SPACE(rassoc); 1346234949Sbapt 1347234949Sbapt rassoc[0] = TOKEN; 1348234949Sbapt rassoc[1] = TOKEN; 1349234949Sbapt rassoc[2] = TOKEN; 1350234949Sbapt} 1351234949Sbapt 1352234949Sbaptstatic void 1353234949Sbaptexpand_items(void) 1354234949Sbapt{ 1355234949Sbapt maxitems += 300; 1356234949Sbapt pitem = (bucket **)REALLOC(pitem, (unsigned)maxitems * sizeof(bucket *)); 1357234949Sbapt NO_SPACE(pitem); 1358234949Sbapt} 1359234949Sbapt 1360234949Sbaptstatic void 1361234949Sbaptexpand_rules(void) 1362234949Sbapt{ 1363234949Sbapt maxrules += 100; 1364234949Sbapt 1365234949Sbapt plhs = (bucket **)REALLOC(plhs, (unsigned)maxrules * sizeof(bucket *)); 1366234949Sbapt NO_SPACE(plhs); 1367234949Sbapt 1368234949Sbapt rprec = (short *)REALLOC(rprec, (unsigned)maxrules * sizeof(short)); 1369234949Sbapt NO_SPACE(rprec); 1370234949Sbapt 1371234949Sbapt rassoc = (char *)REALLOC(rassoc, (unsigned)maxrules * sizeof(char)); 1372234949Sbapt NO_SPACE(rassoc); 1373234949Sbapt} 1374234949Sbapt 1375234949Sbaptstatic void 1376234949Sbaptadvance_to_start(void) 1377234949Sbapt{ 1378234949Sbapt int c; 1379234949Sbapt bucket *bp; 1380234949Sbapt char *s_cptr; 1381234949Sbapt int s_lineno; 1382234949Sbapt 1383234949Sbapt for (;;) 1384234949Sbapt { 1385234949Sbapt c = nextc(); 1386234949Sbapt if (c != '%') 1387234949Sbapt break; 1388234949Sbapt s_cptr = cptr; 1389234949Sbapt switch (keyword()) 1390234949Sbapt { 1391234949Sbapt case MARK: 1392234949Sbapt no_grammar(); 1393234949Sbapt 1394234949Sbapt case TEXT: 1395234949Sbapt copy_text(); 1396234949Sbapt break; 1397234949Sbapt 1398234949Sbapt case START: 1399234949Sbapt declare_start(); 1400234949Sbapt break; 1401234949Sbapt 1402234949Sbapt default: 1403234949Sbapt syntax_error(lineno, line, s_cptr); 1404234949Sbapt } 1405234949Sbapt } 1406234949Sbapt 1407234949Sbapt c = nextc(); 1408234949Sbapt if (!isalpha(c) && c != '_' && c != '.' && c != '_') 1409234949Sbapt syntax_error(lineno, line, cptr); 1410234949Sbapt bp = get_name(); 1411234949Sbapt if (goal == 0) 1412234949Sbapt { 1413234949Sbapt if (bp->class == TERM) 1414234949Sbapt terminal_start(bp->name); 1415234949Sbapt goal = bp; 1416234949Sbapt } 1417234949Sbapt 1418234949Sbapt s_lineno = lineno; 1419234949Sbapt c = nextc(); 1420234949Sbapt if (c == EOF) 1421234949Sbapt unexpected_EOF(); 1422234949Sbapt if (c != ':') 1423234949Sbapt syntax_error(lineno, line, cptr); 1424234949Sbapt start_rule(bp, s_lineno); 1425234949Sbapt ++cptr; 1426234949Sbapt} 1427234949Sbapt 1428234949Sbaptstatic void 1429234949Sbaptstart_rule(bucket *bp, int s_lineno) 1430234949Sbapt{ 1431234949Sbapt if (bp->class == TERM) 1432234949Sbapt terminal_lhs(s_lineno); 1433234949Sbapt bp->class = NONTERM; 1434234949Sbapt if (nrules >= maxrules) 1435234949Sbapt expand_rules(); 1436234949Sbapt plhs[nrules] = bp; 1437234949Sbapt rprec[nrules] = UNDEFINED; 1438234949Sbapt rassoc[nrules] = TOKEN; 1439234949Sbapt} 1440234949Sbapt 1441234949Sbaptstatic void 1442234949Sbaptend_rule(void) 1443234949Sbapt{ 1444234949Sbapt int i; 1445234949Sbapt 1446234949Sbapt if (!last_was_action && plhs[nrules]->tag) 1447234949Sbapt { 1448234949Sbapt if (pitem[nitems - 1]) 1449234949Sbapt { 1450234949Sbapt for (i = nitems - 1; (i > 0) && pitem[i]; --i) 1451234949Sbapt continue; 1452234949Sbapt if (pitem[i + 1] == 0 || pitem[i + 1]->tag != plhs[nrules]->tag) 1453234949Sbapt default_action_warning(); 1454234949Sbapt } 1455234949Sbapt else 1456234949Sbapt { 1457234949Sbapt default_action_warning(); 1458234949Sbapt } 1459234949Sbapt } 1460234949Sbapt 1461234949Sbapt last_was_action = 0; 1462234949Sbapt if (nitems >= maxitems) 1463234949Sbapt expand_items(); 1464234949Sbapt pitem[nitems] = 0; 1465234949Sbapt ++nitems; 1466234949Sbapt ++nrules; 1467234949Sbapt} 1468234949Sbapt 1469234949Sbaptstatic void 1470234949Sbaptinsert_empty_rule(void) 1471234949Sbapt{ 1472234949Sbapt bucket *bp, **bpp; 1473234949Sbapt 1474234949Sbapt assert(cache); 1475234949Sbapt sprintf(cache, "$$%d", ++gensym); 1476234949Sbapt bp = make_bucket(cache); 1477234949Sbapt last_symbol->next = bp; 1478234949Sbapt last_symbol = bp; 1479234949Sbapt bp->tag = plhs[nrules]->tag; 1480234949Sbapt bp->class = NONTERM; 1481234949Sbapt 1482234949Sbapt if ((nitems += 2) > maxitems) 1483234949Sbapt expand_items(); 1484234949Sbapt bpp = pitem + nitems - 1; 1485234949Sbapt *bpp-- = bp; 1486234949Sbapt while ((bpp[0] = bpp[-1]) != 0) 1487234949Sbapt --bpp; 1488234949Sbapt 1489234949Sbapt if (++nrules >= maxrules) 1490234949Sbapt expand_rules(); 1491234949Sbapt plhs[nrules] = plhs[nrules - 1]; 1492234949Sbapt plhs[nrules - 1] = bp; 1493234949Sbapt rprec[nrules] = rprec[nrules - 1]; 1494234949Sbapt rprec[nrules - 1] = 0; 1495234949Sbapt rassoc[nrules] = rassoc[nrules - 1]; 1496234949Sbapt rassoc[nrules - 1] = TOKEN; 1497234949Sbapt} 1498234949Sbapt 1499234949Sbaptstatic void 1500234949Sbaptadd_symbol(void) 1501234949Sbapt{ 1502234949Sbapt int c; 1503234949Sbapt bucket *bp; 1504234949Sbapt int s_lineno = lineno; 1505234949Sbapt 1506234949Sbapt c = *cptr; 1507234949Sbapt if (c == '\'' || c == '"') 1508234949Sbapt bp = get_literal(); 1509234949Sbapt else 1510234949Sbapt bp = get_name(); 1511234949Sbapt 1512234949Sbapt c = nextc(); 1513234949Sbapt if (c == ':') 1514234949Sbapt { 1515234949Sbapt end_rule(); 1516234949Sbapt start_rule(bp, s_lineno); 1517234949Sbapt ++cptr; 1518234949Sbapt return; 1519234949Sbapt } 1520234949Sbapt 1521234949Sbapt if (last_was_action) 1522234949Sbapt insert_empty_rule(); 1523234949Sbapt last_was_action = 0; 1524234949Sbapt 1525234949Sbapt if (++nitems > maxitems) 1526234949Sbapt expand_items(); 1527234949Sbapt pitem[nitems - 1] = bp; 1528234949Sbapt} 1529234949Sbapt 1530234949Sbaptstatic char * 1531234949Sbaptafter_blanks(char *s) 1532234949Sbapt{ 1533234949Sbapt while (*s != '\0' && isspace(UCH(*s))) 1534234949Sbapt ++s; 1535234949Sbapt return s; 1536234949Sbapt} 1537234949Sbapt 1538234949Sbaptstatic void 1539234949Sbaptcopy_action(void) 1540234949Sbapt{ 1541234949Sbapt int c; 1542234949Sbapt int i, n; 1543234949Sbapt int depth; 1544234949Sbapt int quote; 1545234949Sbapt char *tag; 1546234949Sbapt FILE *f = action_file; 1547234949Sbapt int a_lineno = lineno; 1548234949Sbapt char *a_line = dup_line(); 1549234949Sbapt char *a_cptr = a_line + (cptr - line); 1550234949Sbapt 1551234949Sbapt if (last_was_action) 1552234949Sbapt insert_empty_rule(); 1553234949Sbapt last_was_action = 1; 1554234949Sbapt 1555234949Sbapt fprintf(f, "case %d:\n", nrules - 2); 1556234949Sbapt if (!lflag) 1557234949Sbapt fprintf(f, line_format, lineno, input_file_name); 1558234949Sbapt if (*cptr == '=') 1559234949Sbapt ++cptr; 1560234949Sbapt 1561234949Sbapt /* avoid putting curly-braces in first column, to ease editing */ 1562234949Sbapt if (*after_blanks(cptr) == L_CURL) 1563234949Sbapt { 1564234949Sbapt putc('\t', f); 1565234949Sbapt cptr = after_blanks(cptr); 1566234949Sbapt } 1567234949Sbapt 1568234949Sbapt n = 0; 1569234949Sbapt for (i = nitems - 1; pitem[i]; --i) 1570234949Sbapt ++n; 1571234949Sbapt 1572234949Sbapt depth = 0; 1573234949Sbapt loop: 1574234949Sbapt c = *cptr; 1575234949Sbapt if (c == '$') 1576234949Sbapt { 1577234949Sbapt if (cptr[1] == '<') 1578234949Sbapt { 1579234949Sbapt int d_lineno = lineno; 1580234949Sbapt char *d_line = dup_line(); 1581234949Sbapt char *d_cptr = d_line + (cptr - line); 1582234949Sbapt 1583234949Sbapt ++cptr; 1584234949Sbapt tag = get_tag(); 1585234949Sbapt c = *cptr; 1586234949Sbapt if (c == '$') 1587234949Sbapt { 1588234949Sbapt fprintf(f, "yyval.%s", tag); 1589234949Sbapt ++cptr; 1590234949Sbapt FREE(d_line); 1591234949Sbapt goto loop; 1592234949Sbapt } 1593234949Sbapt else if (isdigit(c)) 1594234949Sbapt { 1595234949Sbapt i = get_number(); 1596234949Sbapt if (i > n) 1597234949Sbapt dollar_warning(d_lineno, i); 1598234949Sbapt fprintf(f, "yystack.l_mark[%d].%s", i - n, tag); 1599234949Sbapt FREE(d_line); 1600234949Sbapt goto loop; 1601234949Sbapt } 1602234949Sbapt else if (c == '-' && isdigit(UCH(cptr[1]))) 1603234949Sbapt { 1604234949Sbapt ++cptr; 1605234949Sbapt i = -get_number() - n; 1606234949Sbapt fprintf(f, "yystack.l_mark[%d].%s", i, tag); 1607234949Sbapt FREE(d_line); 1608234949Sbapt goto loop; 1609234949Sbapt } 1610234949Sbapt else 1611234949Sbapt dollar_error(d_lineno, d_line, d_cptr); 1612234949Sbapt } 1613234949Sbapt else if (cptr[1] == '$') 1614234949Sbapt { 1615234949Sbapt if (ntags) 1616234949Sbapt { 1617234949Sbapt tag = plhs[nrules]->tag; 1618234949Sbapt if (tag == 0) 1619234949Sbapt untyped_lhs(); 1620234949Sbapt fprintf(f, "yyval.%s", tag); 1621234949Sbapt } 1622234949Sbapt else 1623234949Sbapt fprintf(f, "yyval"); 1624234949Sbapt cptr += 2; 1625234949Sbapt goto loop; 1626234949Sbapt } 1627234949Sbapt else if (isdigit(UCH(cptr[1]))) 1628234949Sbapt { 1629234949Sbapt ++cptr; 1630234949Sbapt i = get_number(); 1631234949Sbapt if (ntags) 1632234949Sbapt { 1633234949Sbapt if (i <= 0 || i > n) 1634234949Sbapt unknown_rhs(i); 1635234949Sbapt tag = pitem[nitems + i - n - 1]->tag; 1636234949Sbapt if (tag == 0) 1637234949Sbapt untyped_rhs(i, pitem[nitems + i - n - 1]->name); 1638234949Sbapt fprintf(f, "yystack.l_mark[%d].%s", i - n, tag); 1639234949Sbapt } 1640234949Sbapt else 1641234949Sbapt { 1642234949Sbapt if (i > n) 1643234949Sbapt dollar_warning(lineno, i); 1644234949Sbapt fprintf(f, "yystack.l_mark[%d]", i - n); 1645234949Sbapt } 1646234949Sbapt goto loop; 1647234949Sbapt } 1648234949Sbapt else if (cptr[1] == '-') 1649234949Sbapt { 1650234949Sbapt cptr += 2; 1651234949Sbapt i = get_number(); 1652234949Sbapt if (ntags) 1653234949Sbapt unknown_rhs(-i); 1654234949Sbapt fprintf(f, "yystack.l_mark[%d]", -i - n); 1655234949Sbapt goto loop; 1656234949Sbapt } 1657234949Sbapt } 1658234949Sbapt if (isalpha(c) || c == '_' || c == '$') 1659234949Sbapt { 1660234949Sbapt do 1661234949Sbapt { 1662234949Sbapt putc(c, f); 1663234949Sbapt c = *++cptr; 1664234949Sbapt } 1665234949Sbapt while (isalnum(c) || c == '_' || c == '$'); 1666234949Sbapt goto loop; 1667234949Sbapt } 1668234949Sbapt putc(c, f); 1669234949Sbapt ++cptr; 1670234949Sbapt switch (c) 1671234949Sbapt { 1672234949Sbapt case '\n': 1673234949Sbapt next_line: 1674234949Sbapt get_line(); 1675234949Sbapt if (line) 1676234949Sbapt goto loop; 1677234949Sbapt unterminated_action(a_lineno, a_line, a_cptr); 1678234949Sbapt 1679234949Sbapt case ';': 1680234949Sbapt if (depth > 0) 1681234949Sbapt goto loop; 1682234949Sbapt fprintf(f, "\nbreak;\n"); 1683234949Sbapt free(a_line); 1684234949Sbapt return; 1685234949Sbapt 1686234949Sbapt case L_CURL: 1687234949Sbapt ++depth; 1688234949Sbapt goto loop; 1689234949Sbapt 1690234949Sbapt case R_CURL: 1691234949Sbapt if (--depth > 0) 1692234949Sbapt goto loop; 1693234949Sbapt fprintf(f, "\nbreak;\n"); 1694234949Sbapt free(a_line); 1695234949Sbapt return; 1696234949Sbapt 1697234949Sbapt case '\'': 1698234949Sbapt case '"': 1699234949Sbapt { 1700234949Sbapt int s_lineno = lineno; 1701234949Sbapt char *s_line = dup_line(); 1702234949Sbapt char *s_cptr = s_line + (cptr - line - 1); 1703234949Sbapt 1704234949Sbapt quote = c; 1705234949Sbapt for (;;) 1706234949Sbapt { 1707234949Sbapt c = *cptr++; 1708234949Sbapt putc(c, f); 1709234949Sbapt if (c == quote) 1710234949Sbapt { 1711234949Sbapt FREE(s_line); 1712234949Sbapt goto loop; 1713234949Sbapt } 1714234949Sbapt if (c == '\n') 1715234949Sbapt unterminated_string(s_lineno, s_line, s_cptr); 1716234949Sbapt if (c == '\\') 1717234949Sbapt { 1718234949Sbapt c = *cptr++; 1719234949Sbapt putc(c, f); 1720234949Sbapt if (c == '\n') 1721234949Sbapt { 1722234949Sbapt get_line(); 1723234949Sbapt if (line == 0) 1724234949Sbapt unterminated_string(s_lineno, s_line, s_cptr); 1725234949Sbapt } 1726234949Sbapt } 1727234949Sbapt } 1728234949Sbapt } 1729234949Sbapt 1730234949Sbapt case '/': 1731234949Sbapt c = *cptr; 1732234949Sbapt if (c == '/') 1733234949Sbapt { 1734234949Sbapt putc('*', f); 1735234949Sbapt while ((c = *++cptr) != '\n') 1736234949Sbapt { 1737234949Sbapt if (c == '*' && cptr[1] == '/') 1738234949Sbapt fprintf(f, "* "); 1739234949Sbapt else 1740234949Sbapt putc(c, f); 1741234949Sbapt } 1742234949Sbapt fprintf(f, "*/\n"); 1743234949Sbapt goto next_line; 1744234949Sbapt } 1745234949Sbapt if (c == '*') 1746234949Sbapt { 1747234949Sbapt int c_lineno = lineno; 1748234949Sbapt char *c_line = dup_line(); 1749234949Sbapt char *c_cptr = c_line + (cptr - line - 1); 1750234949Sbapt 1751234949Sbapt putc('*', f); 1752234949Sbapt ++cptr; 1753234949Sbapt for (;;) 1754234949Sbapt { 1755234949Sbapt c = *cptr++; 1756234949Sbapt putc(c, f); 1757234949Sbapt if (c == '*' && *cptr == '/') 1758234949Sbapt { 1759234949Sbapt putc('/', f); 1760234949Sbapt ++cptr; 1761234949Sbapt FREE(c_line); 1762234949Sbapt goto loop; 1763234949Sbapt } 1764234949Sbapt if (c == '\n') 1765234949Sbapt { 1766234949Sbapt get_line(); 1767234949Sbapt if (line == 0) 1768234949Sbapt unterminated_comment(c_lineno, c_line, c_cptr); 1769234949Sbapt } 1770234949Sbapt } 1771234949Sbapt } 1772234949Sbapt goto loop; 1773234949Sbapt 1774234949Sbapt default: 1775234949Sbapt goto loop; 1776234949Sbapt } 1777234949Sbapt} 1778234949Sbapt 1779234949Sbaptstatic int 1780234949Sbaptmark_symbol(void) 1781234949Sbapt{ 1782234949Sbapt int c; 1783234949Sbapt bucket *bp; 1784234949Sbapt 1785235723Sbapt bp = NULL; 1786235723Sbapt 1787234949Sbapt c = cptr[1]; 1788234949Sbapt if (c == '%' || c == '\\') 1789234949Sbapt { 1790234949Sbapt cptr += 2; 1791234949Sbapt return (1); 1792234949Sbapt } 1793234949Sbapt 1794234949Sbapt if (c == '=') 1795234949Sbapt cptr += 2; 1796234949Sbapt else if ((c == 'p' || c == 'P') && 1797234949Sbapt ((c = cptr[2]) == 'r' || c == 'R') && 1798234949Sbapt ((c = cptr[3]) == 'e' || c == 'E') && 1799234949Sbapt ((c = cptr[4]) == 'c' || c == 'C') && 1800234949Sbapt ((c = cptr[5], !IS_IDENT(c)))) 1801234949Sbapt cptr += 5; 1802234949Sbapt else 1803234949Sbapt syntax_error(lineno, line, cptr); 1804234949Sbapt 1805234949Sbapt c = nextc(); 1806234949Sbapt if (isalpha(c) || c == '_' || c == '.' || c == '$') 1807234949Sbapt bp = get_name(); 1808234949Sbapt else if (c == '\'' || c == '"') 1809234949Sbapt bp = get_literal(); 1810234949Sbapt else 1811234949Sbapt { 1812234949Sbapt syntax_error(lineno, line, cptr); 1813234949Sbapt /*NOTREACHED */ 1814234949Sbapt } 1815234949Sbapt 1816234949Sbapt if (rprec[nrules] != UNDEFINED && bp->prec != rprec[nrules]) 1817234949Sbapt prec_redeclared(); 1818234949Sbapt 1819234949Sbapt rprec[nrules] = bp->prec; 1820234949Sbapt rassoc[nrules] = bp->assoc; 1821234949Sbapt return (0); 1822234949Sbapt} 1823234949Sbapt 1824234949Sbaptstatic void 1825234949Sbaptread_grammar(void) 1826234949Sbapt{ 1827234949Sbapt int c; 1828234949Sbapt 1829234949Sbapt initialize_grammar(); 1830234949Sbapt advance_to_start(); 1831234949Sbapt 1832234949Sbapt for (;;) 1833234949Sbapt { 1834234949Sbapt c = nextc(); 1835234949Sbapt if (c == EOF) 1836234949Sbapt break; 1837234949Sbapt if (isalpha(c) 1838234949Sbapt || c == '_' 1839234949Sbapt || c == '.' 1840234949Sbapt || c == '$' 1841234949Sbapt || c == '\'' 1842234949Sbapt || c == '"') 1843234949Sbapt add_symbol(); 1844234949Sbapt else if (c == L_CURL || c == '=') 1845234949Sbapt copy_action(); 1846234949Sbapt else if (c == '|') 1847234949Sbapt { 1848234949Sbapt end_rule(); 1849234949Sbapt start_rule(plhs[nrules - 1], 0); 1850234949Sbapt ++cptr; 1851234949Sbapt } 1852234949Sbapt else if (c == '%') 1853234949Sbapt { 1854234949Sbapt if (mark_symbol()) 1855234949Sbapt break; 1856234949Sbapt } 1857234949Sbapt else 1858234949Sbapt syntax_error(lineno, line, cptr); 1859234949Sbapt } 1860234949Sbapt end_rule(); 1861234949Sbapt} 1862234949Sbapt 1863234949Sbaptstatic void 1864234949Sbaptfree_tags(void) 1865234949Sbapt{ 1866234949Sbapt int i; 1867234949Sbapt 1868234949Sbapt if (tag_table == 0) 1869234949Sbapt return; 1870234949Sbapt 1871234949Sbapt for (i = 0; i < ntags; ++i) 1872234949Sbapt { 1873234949Sbapt assert(tag_table[i]); 1874234949Sbapt FREE(tag_table[i]); 1875234949Sbapt } 1876234949Sbapt FREE(tag_table); 1877234949Sbapt} 1878234949Sbapt 1879234949Sbaptstatic void 1880234949Sbaptpack_names(void) 1881234949Sbapt{ 1882234949Sbapt bucket *bp; 1883234949Sbapt char *p, *s, *t; 1884234949Sbapt 1885234949Sbapt name_pool_size = 13; /* 13 == sizeof("$end") + sizeof("$accept") */ 1886234949Sbapt for (bp = first_symbol; bp; bp = bp->next) 1887234949Sbapt name_pool_size += strlen(bp->name) + 1; 1888234949Sbapt 1889234949Sbapt name_pool = MALLOC(name_pool_size); 1890234949Sbapt NO_SPACE(name_pool); 1891234949Sbapt 1892234949Sbapt strcpy(name_pool, "$accept"); 1893234949Sbapt strcpy(name_pool + 8, "$end"); 1894234949Sbapt t = name_pool + 13; 1895234949Sbapt for (bp = first_symbol; bp; bp = bp->next) 1896234949Sbapt { 1897234949Sbapt p = t; 1898234949Sbapt s = bp->name; 1899234949Sbapt while ((*t++ = *s++) != 0) 1900234949Sbapt continue; 1901234949Sbapt FREE(bp->name); 1902234949Sbapt bp->name = p; 1903234949Sbapt } 1904234949Sbapt} 1905234949Sbapt 1906234949Sbaptstatic void 1907234949Sbaptcheck_symbols(void) 1908234949Sbapt{ 1909234949Sbapt bucket *bp; 1910234949Sbapt 1911234949Sbapt if (goal->class == UNKNOWN) 1912234949Sbapt undefined_goal(goal->name); 1913234949Sbapt 1914234949Sbapt for (bp = first_symbol; bp; bp = bp->next) 1915234949Sbapt { 1916234949Sbapt if (bp->class == UNKNOWN) 1917234949Sbapt { 1918234949Sbapt undefined_symbol_warning(bp->name); 1919234949Sbapt bp->class = TERM; 1920234949Sbapt } 1921234949Sbapt } 1922234949Sbapt} 1923234949Sbapt 1924234949Sbaptstatic void 1925234949Sbaptprotect_string(char *src, char **des) 1926234949Sbapt{ 1927234949Sbapt unsigned len; 1928234949Sbapt char *s; 1929234949Sbapt char *d; 1930234949Sbapt 1931234949Sbapt *des = src; 1932234949Sbapt if (src) 1933234949Sbapt { 1934234949Sbapt len = 1; 1935234949Sbapt s = src; 1936234949Sbapt while (*s) 1937234949Sbapt { 1938234949Sbapt if ('\\' == *s || '"' == *s) 1939234949Sbapt len++; 1940234949Sbapt s++; 1941234949Sbapt len++; 1942234949Sbapt } 1943234949Sbapt 1944234949Sbapt *des = d = (char *)MALLOC(len); 1945234949Sbapt NO_SPACE(d); 1946234949Sbapt 1947234949Sbapt s = src; 1948234949Sbapt while (*s) 1949234949Sbapt { 1950234949Sbapt if ('\\' == *s || '"' == *s) 1951234949Sbapt *d++ = '\\'; 1952234949Sbapt *d++ = *s++; 1953234949Sbapt } 1954234949Sbapt *d = '\0'; 1955234949Sbapt } 1956234949Sbapt} 1957234949Sbapt 1958234949Sbaptstatic void 1959234949Sbaptpack_symbols(void) 1960234949Sbapt{ 1961234949Sbapt bucket *bp; 1962234949Sbapt bucket **v; 1963234949Sbapt Value_t i, j, k, n; 1964234949Sbapt 1965234949Sbapt nsyms = 2; 1966234949Sbapt ntokens = 1; 1967234949Sbapt for (bp = first_symbol; bp; bp = bp->next) 1968234949Sbapt { 1969234949Sbapt ++nsyms; 1970234949Sbapt if (bp->class == TERM) 1971234949Sbapt ++ntokens; 1972234949Sbapt } 1973234949Sbapt start_symbol = (Value_t) ntokens; 1974234949Sbapt nvars = nsyms - ntokens; 1975234949Sbapt 1976234949Sbapt symbol_name = (char **)MALLOC((unsigned)nsyms * sizeof(char *)); 1977234949Sbapt NO_SPACE(symbol_name); 1978234949Sbapt 1979234949Sbapt symbol_value = (short *)MALLOC((unsigned)nsyms * sizeof(short)); 1980234949Sbapt NO_SPACE(symbol_value); 1981234949Sbapt 1982234949Sbapt symbol_prec = (short *)MALLOC((unsigned)nsyms * sizeof(short)); 1983234949Sbapt NO_SPACE(symbol_prec); 1984234949Sbapt 1985234949Sbapt symbol_assoc = MALLOC(nsyms); 1986234949Sbapt NO_SPACE(symbol_assoc); 1987234949Sbapt 1988234949Sbapt v = (bucket **)MALLOC((unsigned)nsyms * sizeof(bucket *)); 1989234949Sbapt NO_SPACE(v); 1990234949Sbapt 1991234949Sbapt v[0] = 0; 1992234949Sbapt v[start_symbol] = 0; 1993234949Sbapt 1994234949Sbapt i = 1; 1995234949Sbapt j = (Value_t) (start_symbol + 1); 1996234949Sbapt for (bp = first_symbol; bp; bp = bp->next) 1997234949Sbapt { 1998234949Sbapt if (bp->class == TERM) 1999234949Sbapt v[i++] = bp; 2000234949Sbapt else 2001234949Sbapt v[j++] = bp; 2002234949Sbapt } 2003234949Sbapt assert(i == ntokens && j == nsyms); 2004234949Sbapt 2005234949Sbapt for (i = 1; i < ntokens; ++i) 2006234949Sbapt v[i]->index = i; 2007234949Sbapt 2008234949Sbapt goal->index = (Index_t) (start_symbol + 1); 2009234949Sbapt k = (Value_t) (start_symbol + 2); 2010234949Sbapt while (++i < nsyms) 2011234949Sbapt if (v[i] != goal) 2012234949Sbapt { 2013234949Sbapt v[i]->index = k; 2014234949Sbapt ++k; 2015234949Sbapt } 2016234949Sbapt 2017234949Sbapt goal->value = 0; 2018234949Sbapt k = 1; 2019234949Sbapt for (i = (Value_t) (start_symbol + 1); i < nsyms; ++i) 2020234949Sbapt { 2021234949Sbapt if (v[i] != goal) 2022234949Sbapt { 2023234949Sbapt v[i]->value = k; 2024234949Sbapt ++k; 2025234949Sbapt } 2026234949Sbapt } 2027234949Sbapt 2028234949Sbapt k = 0; 2029234949Sbapt for (i = 1; i < ntokens; ++i) 2030234949Sbapt { 2031234949Sbapt n = v[i]->value; 2032234949Sbapt if (n > 256) 2033234949Sbapt { 2034234949Sbapt for (j = k++; j > 0 && symbol_value[j - 1] > n; --j) 2035234949Sbapt symbol_value[j] = symbol_value[j - 1]; 2036234949Sbapt symbol_value[j] = n; 2037234949Sbapt } 2038234949Sbapt } 2039234949Sbapt 2040234949Sbapt assert(v[1] != 0); 2041234949Sbapt 2042234949Sbapt if (v[1]->value == UNDEFINED) 2043234949Sbapt v[1]->value = 256; 2044234949Sbapt 2045234949Sbapt j = 0; 2046234949Sbapt n = 257; 2047234949Sbapt for (i = 2; i < ntokens; ++i) 2048234949Sbapt { 2049234949Sbapt if (v[i]->value == UNDEFINED) 2050234949Sbapt { 2051234949Sbapt while (j < k && n == symbol_value[j]) 2052234949Sbapt { 2053234949Sbapt while (++j < k && n == symbol_value[j]) 2054234949Sbapt continue; 2055234949Sbapt ++n; 2056234949Sbapt } 2057234949Sbapt v[i]->value = n; 2058234949Sbapt ++n; 2059234949Sbapt } 2060234949Sbapt } 2061234949Sbapt 2062234949Sbapt symbol_name[0] = name_pool + 8; 2063234949Sbapt symbol_value[0] = 0; 2064234949Sbapt symbol_prec[0] = 0; 2065234949Sbapt symbol_assoc[0] = TOKEN; 2066234949Sbapt for (i = 1; i < ntokens; ++i) 2067234949Sbapt { 2068234949Sbapt symbol_name[i] = v[i]->name; 2069234949Sbapt symbol_value[i] = v[i]->value; 2070234949Sbapt symbol_prec[i] = v[i]->prec; 2071234949Sbapt symbol_assoc[i] = v[i]->assoc; 2072234949Sbapt } 2073234949Sbapt symbol_name[start_symbol] = name_pool; 2074234949Sbapt symbol_value[start_symbol] = -1; 2075234949Sbapt symbol_prec[start_symbol] = 0; 2076234949Sbapt symbol_assoc[start_symbol] = TOKEN; 2077234949Sbapt for (++i; i < nsyms; ++i) 2078234949Sbapt { 2079234949Sbapt k = v[i]->index; 2080234949Sbapt symbol_name[k] = v[i]->name; 2081234949Sbapt symbol_value[k] = v[i]->value; 2082234949Sbapt symbol_prec[k] = v[i]->prec; 2083234949Sbapt symbol_assoc[k] = v[i]->assoc; 2084234949Sbapt } 2085234949Sbapt 2086234949Sbapt if (gflag) 2087234949Sbapt { 2088234949Sbapt symbol_pname = (char **)MALLOC((unsigned)nsyms * sizeof(char *)); 2089234949Sbapt NO_SPACE(symbol_pname); 2090234949Sbapt 2091234949Sbapt for (i = 0; i < nsyms; ++i) 2092234949Sbapt protect_string(symbol_name[i], &(symbol_pname[i])); 2093234949Sbapt } 2094234949Sbapt 2095234949Sbapt FREE(v); 2096234949Sbapt} 2097234949Sbapt 2098234949Sbaptstatic void 2099234949Sbaptpack_grammar(void) 2100234949Sbapt{ 2101234949Sbapt int i; 2102234949Sbapt Value_t j; 2103234949Sbapt Assoc_t assoc; 2104234949Sbapt Value_t prec2; 2105234949Sbapt 2106234949Sbapt ritem = (short *)MALLOC((unsigned)nitems * sizeof(short)); 2107234949Sbapt NO_SPACE(ritem); 2108234949Sbapt 2109234949Sbapt rlhs = (short *)MALLOC((unsigned)nrules * sizeof(short)); 2110234949Sbapt NO_SPACE(rlhs); 2111234949Sbapt 2112234949Sbapt rrhs = (short *)MALLOC((unsigned)(nrules + 1) * sizeof(short)); 2113234949Sbapt NO_SPACE(rrhs); 2114234949Sbapt 2115234949Sbapt rprec = (short *)REALLOC(rprec, (unsigned)nrules * sizeof(short)); 2116234949Sbapt NO_SPACE(rprec); 2117234949Sbapt 2118234949Sbapt rassoc = REALLOC(rassoc, nrules); 2119234949Sbapt NO_SPACE(rassoc); 2120234949Sbapt 2121234949Sbapt ritem[0] = -1; 2122234949Sbapt ritem[1] = goal->index; 2123234949Sbapt ritem[2] = 0; 2124234949Sbapt ritem[3] = -2; 2125234949Sbapt rlhs[0] = 0; 2126234949Sbapt rlhs[1] = 0; 2127234949Sbapt rlhs[2] = start_symbol; 2128234949Sbapt rrhs[0] = 0; 2129234949Sbapt rrhs[1] = 0; 2130234949Sbapt rrhs[2] = 1; 2131234949Sbapt 2132234949Sbapt j = 4; 2133234949Sbapt for (i = 3; i < nrules; ++i) 2134234949Sbapt { 2135234949Sbapt rlhs[i] = plhs[i]->index; 2136234949Sbapt rrhs[i] = j; 2137234949Sbapt assoc = TOKEN; 2138234949Sbapt prec2 = 0; 2139234949Sbapt while (pitem[j]) 2140234949Sbapt { 2141234949Sbapt ritem[j] = pitem[j]->index; 2142234949Sbapt if (pitem[j]->class == TERM) 2143234949Sbapt { 2144234949Sbapt prec2 = pitem[j]->prec; 2145234949Sbapt assoc = pitem[j]->assoc; 2146234949Sbapt } 2147234949Sbapt ++j; 2148234949Sbapt } 2149234949Sbapt ritem[j] = (Value_t) - i; 2150234949Sbapt ++j; 2151234949Sbapt if (rprec[i] == UNDEFINED) 2152234949Sbapt { 2153234949Sbapt rprec[i] = prec2; 2154234949Sbapt rassoc[i] = assoc; 2155234949Sbapt } 2156234949Sbapt } 2157234949Sbapt rrhs[i] = j; 2158234949Sbapt 2159234949Sbapt FREE(plhs); 2160234949Sbapt FREE(pitem); 2161234949Sbapt} 2162234949Sbapt 2163234949Sbaptstatic void 2164234949Sbaptprint_grammar(void) 2165234949Sbapt{ 2166234949Sbapt int i, k; 2167234949Sbapt size_t j, spacing = 0; 2168234949Sbapt FILE *f = verbose_file; 2169234949Sbapt 2170234949Sbapt if (!vflag) 2171234949Sbapt return; 2172234949Sbapt 2173234949Sbapt k = 1; 2174234949Sbapt for (i = 2; i < nrules; ++i) 2175234949Sbapt { 2176234949Sbapt if (rlhs[i] != rlhs[i - 1]) 2177234949Sbapt { 2178234949Sbapt if (i != 2) 2179234949Sbapt fprintf(f, "\n"); 2180234949Sbapt fprintf(f, "%4d %s :", i - 2, symbol_name[rlhs[i]]); 2181234949Sbapt spacing = strlen(symbol_name[rlhs[i]]) + 1; 2182234949Sbapt } 2183234949Sbapt else 2184234949Sbapt { 2185234949Sbapt fprintf(f, "%4d ", i - 2); 2186234949Sbapt j = spacing; 2187234949Sbapt while (j-- != 0) 2188234949Sbapt putc(' ', f); 2189234949Sbapt putc('|', f); 2190234949Sbapt } 2191234949Sbapt 2192234949Sbapt while (ritem[k] >= 0) 2193234949Sbapt { 2194234949Sbapt fprintf(f, " %s", symbol_name[ritem[k]]); 2195234949Sbapt ++k; 2196234949Sbapt } 2197234949Sbapt ++k; 2198234949Sbapt putc('\n', f); 2199234949Sbapt } 2200234949Sbapt} 2201234949Sbapt 2202234949Sbaptvoid 2203234949Sbaptreader(void) 2204234949Sbapt{ 2205234949Sbapt write_section(code_file, banner); 2206234949Sbapt create_symbol_table(); 2207234949Sbapt read_declarations(); 2208234949Sbapt read_grammar(); 2209234949Sbapt free_symbol_table(); 2210234949Sbapt free_tags(); 2211234949Sbapt pack_names(); 2212234949Sbapt check_symbols(); 2213234949Sbapt pack_symbols(); 2214234949Sbapt pack_grammar(); 2215234949Sbapt free_symbols(); 2216234949Sbapt print_grammar(); 2217234949Sbapt} 2218234949Sbapt 2219234949Sbapt#ifdef NO_LEAKS 2220234949Sbaptstatic param * 2221234949Sbaptfree_declarations(param * list) 2222234949Sbapt{ 2223234949Sbapt while (list != 0) 2224234949Sbapt { 2225234949Sbapt param *next = list->next; 2226234949Sbapt free(list->type); 2227234949Sbapt free(list->name); 2228234949Sbapt free(list->type2); 2229234949Sbapt free(list); 2230234949Sbapt list = next; 2231234949Sbapt } 2232234949Sbapt return list; 2233234949Sbapt} 2234234949Sbapt 2235234949Sbaptvoid 2236234949Sbaptreader_leaks(void) 2237234949Sbapt{ 2238234949Sbapt lex_param = free_declarations(lex_param); 2239234949Sbapt parse_param = free_declarations(parse_param); 2240234949Sbapt 2241234949Sbapt DO_FREE(line); 2242234949Sbapt DO_FREE(rrhs); 2243234949Sbapt DO_FREE(rlhs); 2244234949Sbapt DO_FREE(rprec); 2245234949Sbapt DO_FREE(ritem); 2246234949Sbapt DO_FREE(rassoc); 2247234949Sbapt DO_FREE(cache); 2248234949Sbapt DO_FREE(name_pool); 2249234949Sbapt DO_FREE(symbol_name); 2250234949Sbapt DO_FREE(symbol_prec); 2251234949Sbapt DO_FREE(symbol_assoc); 2252234949Sbapt DO_FREE(symbol_value); 2253234949Sbapt} 2254234949Sbapt#endif 2255