11590Srgrimes/* 21590Srgrimes * Copyright (c) 1989 The Regents of the University of California. 31590Srgrimes * All rights reserved. 41590Srgrimes * 51590Srgrimes * This code is derived from software contributed to Berkeley by 61590Srgrimes * Robert Paul Corbett. 71590Srgrimes * 81590Srgrimes * Redistribution and use in source and binary forms, with or without 91590Srgrimes * modification, are permitted provided that the following conditions 101590Srgrimes * are met: 111590Srgrimes * 1. Redistributions of source code must retain the above copyright 121590Srgrimes * notice, this list of conditions and the following disclaimer. 131590Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 141590Srgrimes * notice, this list of conditions and the following disclaimer in the 151590Srgrimes * documentation and/or other materials provided with the distribution. 161590Srgrimes * 4. Neither the name of the University nor the names of its contributors 171590Srgrimes * may be used to endorse or promote products derived from this software 181590Srgrimes * without specific prior written permission. 191590Srgrimes * 201590Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 211590Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 221590Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 231590Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 241590Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 251590Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 261590Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 271590Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 281590Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 291590Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 301590Srgrimes * SUCH DAMAGE. 311590Srgrimes */ 321590Srgrimes 3387628Sdwmalone#if 0 3487628Sdwmalone#ifndef lint 3587628Sdwmalonestatic char sccsid[] = "@(#)reader.c 5.7 (Berkeley) 1/20/91"; 3687628Sdwmalone#endif 3787628Sdwmalone#endif 3887628Sdwmalone 3987234Smarkm#include <sys/cdefs.h> 4087234Smarkm__FBSDID("$FreeBSD$"); 4187234Smarkm 4298116Srobert#include <limits.h> 4321622Ssteve#include <stdlib.h> 4421622Ssteve#include <string.h> 451590Srgrimes#include "defs.h" 461590Srgrimes 471590Srgrimes/* The line size must be a positive integer. One hundred was chosen */ 481590Srgrimes/* because few lines in Yacc input grammars exceed 100 characters. */ 491590Srgrimes/* Note that if a line exceeds LINESIZE characters, the line buffer */ 501590Srgrimes/* will be expanded to accomodate it. */ 511590Srgrimes 521590Srgrimes#define LINESIZE 100 531590Srgrimes 541590Srgrimeschar *cache; 551590Srgrimesint cinc, cache_size; 561590Srgrimes 571590Srgrimesint ntags, tagmax; 581590Srgrimeschar **tag_table; 591590Srgrimes 601590Srgrimeschar saw_eof, unionized; 611590Srgrimeschar *cptr, *line; 621590Srgrimesint linesize; 631590Srgrimes 641590Srgrimesbucket *goal; 651590Srgrimesint prec; 661590Srgrimesint gensym; 671590Srgrimeschar last_was_action; 681590Srgrimes 691590Srgrimesint maxitems; 701590Srgrimesbucket **pitem; 711590Srgrimes 721590Srgrimesint maxrules; 731590Srgrimesbucket **plhs; 741590Srgrimes 751590Srgrimesint name_pool_size; 761590Srgrimeschar *name_pool; 771590Srgrimes 7869204Skrisstatic const char line_format[] = "#line %d \"%s\"\n"; 791590Srgrimes 8092922Simpstatic void add_symbol(void); 8192922Simpstatic void advance_to_start(void); 8292922Simpstatic void cachec(int); 8392922Simpstatic void check_symbols(void); 8492922Simpstatic void copy_action(void); 8592922Simpstatic void copy_ident(void); 8692922Simpstatic void copy_text(void); 8792922Simpstatic void copy_union(void); 8892922Simpstatic void declare_expect(int); 8992922Simpstatic void declare_start(void); 9092922Simpstatic void declare_tokens(int); 9192922Simpstatic void declare_types(void); 9292922Simpstatic char *dup_line(void); 9392922Simpstatic void end_rule(void); 9492922Simpstatic void expand_items(void); 9592922Simpstatic void expand_rules(void); 9692922Simpstatic void free_tags(void); 9792922Simpstatic void get_line(void); 9892922Simpstatic bucket *get_literal(void); 9992922Simpstatic bucket *get_name(void); 10092922Simpstatic int get_number(void); 10192922Simpstatic char *get_tag(void); 10292922Simpstatic int hexval(int); 10392922Simpstatic void initialize_grammar(void); 10492922Simpstatic void insert_empty_rule(void); 10592922Simpstatic int is_reserved(char *); 10692922Simpstatic int keyword(void); 10792922Simpstatic int mark_symbol(void); 10892922Simpstatic int nextc(void); 10992922Simpstatic void pack_grammar(void); 11092922Simpstatic void pack_names(void); 11192922Simpstatic void pack_symbols(void); 11292922Simpstatic void print_grammar(void); 11392922Simpstatic void read_declarations(void); 11492922Simpstatic void read_grammar(void); 11592922Simpstatic void skip_comment(void); 11692922Simpstatic void start_rule(bucket *, int); 1171590Srgrimes 11821622Sstevestatic void 119214959Sobriencachec(int c) 1201590Srgrimes{ 1211590Srgrimes assert(cinc >= 0); 1221590Srgrimes if (cinc >= cache_size) 1231590Srgrimes { 1241590Srgrimes cache_size += 256; 125214961Sobrien cache = realloc(cache, cache_size); 1261590Srgrimes if (cache == 0) no_space(); 1271590Srgrimes } 1281590Srgrimes cache[cinc] = c; 1291590Srgrimes ++cinc; 1301590Srgrimes} 1311590Srgrimes 1321590Srgrimes 13321622Sstevestatic void 134214959Sobrienget_line(void) 1351590Srgrimes{ 13687171Smarkm FILE *f = input_file; 13787171Smarkm int c; 13887171Smarkm int i; 1391590Srgrimes 1401590Srgrimes if (saw_eof || (c = getc(f)) == EOF) 1411590Srgrimes { 142214961Sobrien if (line) { free(line); line = 0; } 1431590Srgrimes cptr = 0; 1441590Srgrimes saw_eof = 1; 1451590Srgrimes return; 1461590Srgrimes } 1471590Srgrimes 1481590Srgrimes if (line == 0 || linesize != (LINESIZE + 1)) 1491590Srgrimes { 150214961Sobrien if (line) free(line); 1511590Srgrimes linesize = LINESIZE + 1; 152214961Sobrien line = malloc(linesize); 1531590Srgrimes if (line == 0) no_space(); 1541590Srgrimes } 1551590Srgrimes 1561590Srgrimes i = 0; 1571590Srgrimes ++lineno; 1581590Srgrimes for (;;) 1591590Srgrimes { 1601590Srgrimes line[i] = c; 1611590Srgrimes if (c == '\n') { cptr = line; return; } 1621590Srgrimes if (++i >= linesize) 1631590Srgrimes { 1641590Srgrimes linesize += LINESIZE; 165214961Sobrien line = realloc(line, linesize); 1661590Srgrimes if (line == 0) no_space(); 1671590Srgrimes } 1681590Srgrimes c = getc(f); 1691590Srgrimes if (c == EOF) 1701590Srgrimes { 1711590Srgrimes line[i] = '\n'; 1721590Srgrimes saw_eof = 1; 1731590Srgrimes cptr = line; 1741590Srgrimes return; 1751590Srgrimes } 1761590Srgrimes } 1771590Srgrimes} 1781590Srgrimes 1791590Srgrimes 18021622Sstevestatic char * 181214959Sobriendup_line(void) 1821590Srgrimes{ 18387171Smarkm char *p, *s, *t; 1841590Srgrimes 1851590Srgrimes if (line == 0) return (0); 1861590Srgrimes s = line; 1871590Srgrimes while (*s != '\n') ++s; 188214961Sobrien p = malloc(s - line + 1); 1891590Srgrimes if (p == 0) no_space(); 1901590Srgrimes 1911590Srgrimes s = line; 1921590Srgrimes t = p; 1931590Srgrimes while ((*t++ = *s++) != '\n') continue; 1941590Srgrimes return (p); 1951590Srgrimes} 1961590Srgrimes 1971590Srgrimes 19821622Sstevestatic void 199214959Sobrienskip_comment(void) 2001590Srgrimes{ 20187171Smarkm char *s; 2021590Srgrimes 2031590Srgrimes int st_lineno = lineno; 2041590Srgrimes char *st_line = dup_line(); 2051590Srgrimes char *st_cptr = st_line + (cptr - line); 2061590Srgrimes 2071590Srgrimes s = cptr + 2; 2081590Srgrimes for (;;) 2091590Srgrimes { 2101590Srgrimes if (*s == '*' && s[1] == '/') 2111590Srgrimes { 2121590Srgrimes cptr = s + 2; 213214961Sobrien free(st_line); 2141590Srgrimes return; 2151590Srgrimes } 2161590Srgrimes if (*s == '\n') 2171590Srgrimes { 2181590Srgrimes get_line(); 2191590Srgrimes if (line == 0) 2201590Srgrimes unterminated_comment(st_lineno, st_line, st_cptr); 2211590Srgrimes s = cptr; 2221590Srgrimes } 2231590Srgrimes else 2241590Srgrimes ++s; 2251590Srgrimes } 2261590Srgrimes} 2271590Srgrimes 2281590Srgrimes 22921622Sstevestatic int 230214959Sobriennextc(void) 2311590Srgrimes{ 23287171Smarkm char *s; 2331590Srgrimes 2341590Srgrimes if (line == 0) 2351590Srgrimes { 2361590Srgrimes get_line(); 2371590Srgrimes if (line == 0) 2381590Srgrimes return (EOF); 2391590Srgrimes } 2401590Srgrimes 2411590Srgrimes s = cptr; 2421590Srgrimes for (;;) 2431590Srgrimes { 2441590Srgrimes switch (*s) 2451590Srgrimes { 2461590Srgrimes case '\n': 2471590Srgrimes get_line(); 2481590Srgrimes if (line == 0) return (EOF); 2491590Srgrimes s = cptr; 2501590Srgrimes break; 2511590Srgrimes 2521590Srgrimes case ' ': 2531590Srgrimes case '\t': 2541590Srgrimes case '\f': 2551590Srgrimes case '\r': 2561590Srgrimes case '\v': 2571590Srgrimes case ',': 2581590Srgrimes case ';': 2591590Srgrimes ++s; 2601590Srgrimes break; 2611590Srgrimes 2621590Srgrimes case '\\': 2631590Srgrimes cptr = s; 2641590Srgrimes return ('%'); 2651590Srgrimes 2661590Srgrimes case '/': 2671590Srgrimes if (s[1] == '*') 2681590Srgrimes { 2691590Srgrimes cptr = s; 2701590Srgrimes skip_comment(); 2711590Srgrimes s = cptr; 2721590Srgrimes break; 2731590Srgrimes } 2741590Srgrimes else if (s[1] == '/') 2751590Srgrimes { 2761590Srgrimes get_line(); 2771590Srgrimes if (line == 0) return (EOF); 2781590Srgrimes s = cptr; 2791590Srgrimes break; 2801590Srgrimes } 281102412Scharnier /* FALLTHROUGH */ 2821590Srgrimes 2831590Srgrimes default: 2841590Srgrimes cptr = s; 2851590Srgrimes return (*s); 2861590Srgrimes } 2871590Srgrimes } 2881590Srgrimes} 2891590Srgrimes 2901590Srgrimes 29121622Sstevestatic int 292214959Sobrienkeyword(void) 2931590Srgrimes{ 29487171Smarkm int c; 2951590Srgrimes char *t_cptr = cptr; 2961590Srgrimes 2971590Srgrimes c = *++cptr; 2981590Srgrimes if (isalpha(c)) 2991590Srgrimes { 3001590Srgrimes cinc = 0; 3011590Srgrimes for (;;) 3021590Srgrimes { 3031590Srgrimes if (isalpha(c)) 3041590Srgrimes { 3051590Srgrimes if (isupper(c)) c = tolower(c); 3061590Srgrimes cachec(c); 3071590Srgrimes } 3081590Srgrimes else if (isdigit(c) || c == '_' || c == '.' || c == '$') 3091590Srgrimes cachec(c); 3101590Srgrimes else 3111590Srgrimes break; 3121590Srgrimes c = *++cptr; 3131590Srgrimes } 3141590Srgrimes cachec(NUL); 3151590Srgrimes 3161590Srgrimes if (strcmp(cache, "token") == 0 || strcmp(cache, "term") == 0) 3171590Srgrimes return (TOKEN); 3181590Srgrimes if (strcmp(cache, "type") == 0) 3191590Srgrimes return (TYPE); 3201590Srgrimes if (strcmp(cache, "left") == 0) 3211590Srgrimes return (LEFT); 3221590Srgrimes if (strcmp(cache, "right") == 0) 3231590Srgrimes return (RIGHT); 3241590Srgrimes if (strcmp(cache, "nonassoc") == 0 || strcmp(cache, "binary") == 0) 3251590Srgrimes return (NONASSOC); 3261590Srgrimes if (strcmp(cache, "start") == 0) 3271590Srgrimes return (START); 3281590Srgrimes if (strcmp(cache, "union") == 0) 3291590Srgrimes return (UNION); 3301590Srgrimes if (strcmp(cache, "ident") == 0) 3311590Srgrimes return (IDENT); 33249208Sobrien if (strcmp(cache, "expect") == 0) 33349208Sobrien return (EXPECT); 3341590Srgrimes } 3351590Srgrimes else 3361590Srgrimes { 3371590Srgrimes ++cptr; 3381590Srgrimes if (c == '{') 3391590Srgrimes return (TEXT); 3401590Srgrimes if (c == '%' || c == '\\') 3411590Srgrimes return (MARK); 3421590Srgrimes if (c == '<') 3431590Srgrimes return (LEFT); 3441590Srgrimes if (c == '>') 3451590Srgrimes return (RIGHT); 3461590Srgrimes if (c == '0') 3471590Srgrimes return (TOKEN); 3481590Srgrimes if (c == '2') 3491590Srgrimes return (NONASSOC); 3501590Srgrimes } 3511590Srgrimes syntax_error(lineno, line, t_cptr); 3521590Srgrimes /*NOTREACHED*/ 35321622Ssteve return (0); 3541590Srgrimes} 3551590Srgrimes 3561590Srgrimes 35721622Sstevestatic void 358214959Sobriencopy_ident(void) 3591590Srgrimes{ 36087171Smarkm int c; 36187171Smarkm FILE *f = output_file; 3621590Srgrimes 3631590Srgrimes c = nextc(); 3641590Srgrimes if (c == EOF) unexpected_EOF(); 3651590Srgrimes if (c != '"') syntax_error(lineno, line, cptr); 3661590Srgrimes ++outline; 3671590Srgrimes fprintf(f, "#ident \""); 3681590Srgrimes for (;;) 3691590Srgrimes { 3701590Srgrimes c = *++cptr; 3711590Srgrimes if (c == '\n') 3721590Srgrimes { 3731590Srgrimes fprintf(f, "\"\n"); 3741590Srgrimes return; 3751590Srgrimes } 3761590Srgrimes putc(c, f); 3771590Srgrimes if (c == '"') 3781590Srgrimes { 3791590Srgrimes putc('\n', f); 3801590Srgrimes ++cptr; 3811590Srgrimes return; 3821590Srgrimes } 3831590Srgrimes } 3841590Srgrimes} 3851590Srgrimes 3861590Srgrimes 38721622Sstevestatic void 388214959Sobriencopy_text(void) 3891590Srgrimes{ 39087171Smarkm int c; 3911590Srgrimes int quote; 39287171Smarkm FILE *f = text_file; 3931590Srgrimes int need_newline = 0; 3941590Srgrimes int t_lineno = lineno; 3951590Srgrimes char *t_line = dup_line(); 3961590Srgrimes char *t_cptr = t_line + (cptr - line - 2); 3971590Srgrimes 3981590Srgrimes if (*cptr == '\n') 3991590Srgrimes { 4001590Srgrimes get_line(); 4011590Srgrimes if (line == 0) 4021590Srgrimes unterminated_text(t_lineno, t_line, t_cptr); 4031590Srgrimes } 4041590Srgrimes if (!lflag) fprintf(f, line_format, lineno, input_file_name); 4051590Srgrimes 4061590Srgrimesloop: 4071590Srgrimes c = *cptr++; 4081590Srgrimes switch (c) 4091590Srgrimes { 4101590Srgrimes case '\n': 4111590Srgrimes next_line: 4121590Srgrimes putc('\n', f); 4131590Srgrimes need_newline = 0; 4141590Srgrimes get_line(); 4151590Srgrimes if (line) goto loop; 4161590Srgrimes unterminated_text(t_lineno, t_line, t_cptr); 4171590Srgrimes 4181590Srgrimes case '\'': 4191590Srgrimes case '"': 4201590Srgrimes { 4211590Srgrimes int s_lineno = lineno; 4221590Srgrimes char *s_line = dup_line(); 4231590Srgrimes char *s_cptr = s_line + (cptr - line - 1); 4241590Srgrimes 4251590Srgrimes quote = c; 4261590Srgrimes putc(c, f); 4271590Srgrimes for (;;) 4281590Srgrimes { 4291590Srgrimes c = *cptr++; 4301590Srgrimes putc(c, f); 4311590Srgrimes if (c == quote) 4321590Srgrimes { 4331590Srgrimes need_newline = 1; 434214961Sobrien free(s_line); 4351590Srgrimes goto loop; 4361590Srgrimes } 4371590Srgrimes if (c == '\n') 4381590Srgrimes unterminated_string(s_lineno, s_line, s_cptr); 4391590Srgrimes if (c == '\\') 4401590Srgrimes { 4411590Srgrimes c = *cptr++; 4421590Srgrimes putc(c, f); 4431590Srgrimes if (c == '\n') 4441590Srgrimes { 4451590Srgrimes get_line(); 4461590Srgrimes if (line == 0) 4471590Srgrimes unterminated_string(s_lineno, s_line, s_cptr); 4481590Srgrimes } 4491590Srgrimes } 4501590Srgrimes } 4511590Srgrimes } 4521590Srgrimes 4531590Srgrimes case '/': 4541590Srgrimes putc(c, f); 4551590Srgrimes need_newline = 1; 4561590Srgrimes c = *cptr; 4571590Srgrimes if (c == '/') 4581590Srgrimes { 4591590Srgrimes putc('*', f); 4601590Srgrimes while ((c = *++cptr) != '\n') 4611590Srgrimes { 4621590Srgrimes if (c == '*' && cptr[1] == '/') 4631590Srgrimes fprintf(f, "* "); 4641590Srgrimes else 4651590Srgrimes putc(c, f); 4661590Srgrimes } 4671590Srgrimes fprintf(f, "*/"); 4681590Srgrimes goto next_line; 4691590Srgrimes } 4701590Srgrimes if (c == '*') 4711590Srgrimes { 4721590Srgrimes int c_lineno = lineno; 4731590Srgrimes char *c_line = dup_line(); 4741590Srgrimes char *c_cptr = c_line + (cptr - line - 1); 4751590Srgrimes 4761590Srgrimes putc('*', f); 4771590Srgrimes ++cptr; 4781590Srgrimes for (;;) 4791590Srgrimes { 4801590Srgrimes c = *cptr++; 4811590Srgrimes putc(c, f); 4821590Srgrimes if (c == '*' && *cptr == '/') 4831590Srgrimes { 4841590Srgrimes putc('/', f); 4851590Srgrimes ++cptr; 486214961Sobrien free(c_line); 4871590Srgrimes goto loop; 4881590Srgrimes } 4891590Srgrimes if (c == '\n') 4901590Srgrimes { 4911590Srgrimes get_line(); 4921590Srgrimes if (line == 0) 4931590Srgrimes unterminated_comment(c_lineno, c_line, c_cptr); 4941590Srgrimes } 4951590Srgrimes } 4961590Srgrimes } 4971590Srgrimes need_newline = 1; 4981590Srgrimes goto loop; 4991590Srgrimes 5001590Srgrimes case '%': 5011590Srgrimes case '\\': 5021590Srgrimes if (*cptr == '}') 5031590Srgrimes { 5041590Srgrimes if (need_newline) putc('\n', f); 5051590Srgrimes ++cptr; 506214961Sobrien free(t_line); 5071590Srgrimes return; 5081590Srgrimes } 509102412Scharnier /* FALLTHROUGH */ 5101590Srgrimes 5111590Srgrimes default: 5121590Srgrimes putc(c, f); 5131590Srgrimes need_newline = 1; 5141590Srgrimes goto loop; 5151590Srgrimes } 5161590Srgrimes} 5171590Srgrimes 5181590Srgrimes 51921622Sstevestatic void 520214959Sobriencopy_union(void) 5211590Srgrimes{ 52287171Smarkm int c; 5231590Srgrimes int quote; 5241590Srgrimes int depth; 5251590Srgrimes int u_lineno = lineno; 5261590Srgrimes char *u_line = dup_line(); 5271590Srgrimes char *u_cptr = u_line + (cptr - line - 6); 5281590Srgrimes 5291590Srgrimes if (unionized) over_unionized(cptr - 6); 5301590Srgrimes unionized = 1; 5311590Srgrimes 5321590Srgrimes if (!lflag) 5331590Srgrimes fprintf(text_file, line_format, lineno, input_file_name); 5341590Srgrimes 5351590Srgrimes fprintf(text_file, "typedef union"); 5361590Srgrimes if (dflag) fprintf(union_file, "typedef union"); 5371590Srgrimes 5381590Srgrimes depth = 0; 5391590Srgrimesloop: 5401590Srgrimes c = *cptr++; 5411590Srgrimes putc(c, text_file); 5421590Srgrimes if (dflag) putc(c, union_file); 5431590Srgrimes switch (c) 5441590Srgrimes { 5451590Srgrimes case '\n': 5461590Srgrimes next_line: 5471590Srgrimes get_line(); 5481590Srgrimes if (line == 0) unterminated_union(u_lineno, u_line, u_cptr); 5491590Srgrimes goto loop; 5501590Srgrimes 5511590Srgrimes case '{': 5521590Srgrimes ++depth; 5531590Srgrimes goto loop; 5541590Srgrimes 5551590Srgrimes case '}': 5561590Srgrimes if (--depth == 0) 5571590Srgrimes { 5581590Srgrimes fprintf(text_file, " YYSTYPE;\n"); 559214961Sobrien free(u_line); 5601590Srgrimes return; 5611590Srgrimes } 5621590Srgrimes goto loop; 5631590Srgrimes 5641590Srgrimes case '\'': 5651590Srgrimes case '"': 5661590Srgrimes { 5671590Srgrimes int s_lineno = lineno; 5681590Srgrimes char *s_line = dup_line(); 5691590Srgrimes char *s_cptr = s_line + (cptr - line - 1); 5701590Srgrimes 5711590Srgrimes quote = c; 5721590Srgrimes for (;;) 5731590Srgrimes { 5741590Srgrimes c = *cptr++; 5751590Srgrimes putc(c, text_file); 5761590Srgrimes if (dflag) putc(c, union_file); 5771590Srgrimes if (c == quote) 5781590Srgrimes { 579214961Sobrien free(s_line); 5801590Srgrimes goto loop; 5811590Srgrimes } 5821590Srgrimes if (c == '\n') 5831590Srgrimes unterminated_string(s_lineno, s_line, s_cptr); 5841590Srgrimes if (c == '\\') 5851590Srgrimes { 5861590Srgrimes c = *cptr++; 5871590Srgrimes putc(c, text_file); 5881590Srgrimes if (dflag) putc(c, union_file); 5891590Srgrimes if (c == '\n') 5901590Srgrimes { 5911590Srgrimes get_line(); 5921590Srgrimes if (line == 0) 5931590Srgrimes unterminated_string(s_lineno, s_line, s_cptr); 5941590Srgrimes } 5951590Srgrimes } 5961590Srgrimes } 5971590Srgrimes } 5981590Srgrimes 5991590Srgrimes case '/': 6001590Srgrimes c = *cptr; 6011590Srgrimes if (c == '/') 6021590Srgrimes { 6031590Srgrimes putc('*', text_file); 6041590Srgrimes if (dflag) putc('*', union_file); 6051590Srgrimes while ((c = *++cptr) != '\n') 6061590Srgrimes { 6071590Srgrimes if (c == '*' && cptr[1] == '/') 6081590Srgrimes { 6091590Srgrimes fprintf(text_file, "* "); 6101590Srgrimes if (dflag) fprintf(union_file, "* "); 6111590Srgrimes } 6121590Srgrimes else 6131590Srgrimes { 6141590Srgrimes putc(c, text_file); 6151590Srgrimes if (dflag) putc(c, union_file); 6161590Srgrimes } 6171590Srgrimes } 6181590Srgrimes fprintf(text_file, "*/\n"); 6191590Srgrimes if (dflag) fprintf(union_file, "*/\n"); 6201590Srgrimes goto next_line; 6211590Srgrimes } 6221590Srgrimes if (c == '*') 6231590Srgrimes { 6241590Srgrimes int c_lineno = lineno; 6251590Srgrimes char *c_line = dup_line(); 6261590Srgrimes char *c_cptr = c_line + (cptr - line - 1); 6271590Srgrimes 6281590Srgrimes putc('*', text_file); 6291590Srgrimes if (dflag) putc('*', union_file); 6301590Srgrimes ++cptr; 6311590Srgrimes for (;;) 6321590Srgrimes { 6331590Srgrimes c = *cptr++; 6341590Srgrimes putc(c, text_file); 6351590Srgrimes if (dflag) putc(c, union_file); 6361590Srgrimes if (c == '*' && *cptr == '/') 6371590Srgrimes { 6381590Srgrimes putc('/', text_file); 6391590Srgrimes if (dflag) putc('/', union_file); 6401590Srgrimes ++cptr; 641214961Sobrien free(c_line); 6421590Srgrimes goto loop; 6431590Srgrimes } 6441590Srgrimes if (c == '\n') 6451590Srgrimes { 6461590Srgrimes get_line(); 6471590Srgrimes if (line == 0) 6481590Srgrimes unterminated_comment(c_lineno, c_line, c_cptr); 6491590Srgrimes } 6501590Srgrimes } 6511590Srgrimes } 6521590Srgrimes goto loop; 6531590Srgrimes 6541590Srgrimes default: 6551590Srgrimes goto loop; 6561590Srgrimes } 6571590Srgrimes} 6581590Srgrimes 6591590Srgrimes 66021622Sstevestatic int 661214959Sobrienhexval(int c) 6621590Srgrimes{ 6631590Srgrimes if (c >= '0' && c <= '9') 6641590Srgrimes return (c - '0'); 6651590Srgrimes if (c >= 'A' && c <= 'F') 6661590Srgrimes return (c - 'A' + 10); 6671590Srgrimes if (c >= 'a' && c <= 'f') 6681590Srgrimes return (c - 'a' + 10); 6691590Srgrimes return (-1); 6701590Srgrimes} 6711590Srgrimes 6721590Srgrimes 67321622Sstevestatic bucket * 674214959Sobrienget_literal(void) 6751590Srgrimes{ 67687171Smarkm int c, quote; 67787171Smarkm int i; 67887171Smarkm int n; 67987171Smarkm char *s; 68087171Smarkm bucket *bp; 6811590Srgrimes int s_lineno = lineno; 6821590Srgrimes char *s_line = dup_line(); 6831590Srgrimes char *s_cptr = s_line + (cptr - line); 6841590Srgrimes 6851590Srgrimes quote = *cptr++; 6861590Srgrimes cinc = 0; 6871590Srgrimes for (;;) 6881590Srgrimes { 6891590Srgrimes c = *cptr++; 6901590Srgrimes if (c == quote) break; 6911590Srgrimes if (c == '\n') unterminated_string(s_lineno, s_line, s_cptr); 6921590Srgrimes if (c == '\\') 6931590Srgrimes { 6941590Srgrimes char *c_cptr = cptr - 1; 6951590Srgrimes 6961590Srgrimes c = *cptr++; 6971590Srgrimes switch (c) 6981590Srgrimes { 6991590Srgrimes case '\n': 7001590Srgrimes get_line(); 7011590Srgrimes if (line == 0) unterminated_string(s_lineno, s_line, s_cptr); 7021590Srgrimes continue; 7031590Srgrimes 7041590Srgrimes case '0': case '1': case '2': case '3': 7051590Srgrimes case '4': case '5': case '6': case '7': 7061590Srgrimes n = c - '0'; 7071590Srgrimes c = *cptr; 7081590Srgrimes if (IS_OCTAL(c)) 7091590Srgrimes { 7101590Srgrimes n = (n << 3) + (c - '0'); 7111590Srgrimes c = *++cptr; 7121590Srgrimes if (IS_OCTAL(c)) 7131590Srgrimes { 7141590Srgrimes n = (n << 3) + (c - '0'); 7151590Srgrimes ++cptr; 7161590Srgrimes } 7171590Srgrimes } 718215027Sobrien if (n > (int)UCHAR_MAX) illegal_character(c_cptr); 7191590Srgrimes c = n; 7201590Srgrimes break; 7211590Srgrimes 7221590Srgrimes case 'x': 7231590Srgrimes c = *cptr++; 7241590Srgrimes n = hexval(c); 7251590Srgrimes if (n < 0 || n >= 16) 7261590Srgrimes illegal_character(c_cptr); 7271590Srgrimes for (;;) 7281590Srgrimes { 7291590Srgrimes c = *cptr; 7301590Srgrimes i = hexval(c); 7311590Srgrimes if (i < 0 || i >= 16) break; 7321590Srgrimes ++cptr; 7331590Srgrimes n = (n << 4) + i; 734215027Sobrien if (n > (int)UCHAR_MAX) illegal_character(c_cptr); 7351590Srgrimes } 7361590Srgrimes c = n; 7371590Srgrimes break; 7381590Srgrimes 7391590Srgrimes case 'a': c = 7; break; 7401590Srgrimes case 'b': c = '\b'; break; 7411590Srgrimes case 'f': c = '\f'; break; 7421590Srgrimes case 'n': c = '\n'; break; 7431590Srgrimes case 'r': c = '\r'; break; 7441590Srgrimes case 't': c = '\t'; break; 7451590Srgrimes case 'v': c = '\v'; break; 7461590Srgrimes } 7471590Srgrimes } 7481590Srgrimes cachec(c); 7491590Srgrimes } 750214961Sobrien free(s_line); 7511590Srgrimes 7521590Srgrimes n = cinc; 753214961Sobrien s = malloc(n); 7541590Srgrimes if (s == 0) no_space(); 7558874Srgrimes 7561590Srgrimes for (i = 0; i < n; ++i) 7571590Srgrimes s[i] = cache[i]; 7581590Srgrimes 7591590Srgrimes cinc = 0; 7601590Srgrimes if (n == 1) 7611590Srgrimes cachec('\''); 7621590Srgrimes else 7631590Srgrimes cachec('"'); 7641590Srgrimes 7651590Srgrimes for (i = 0; i < n; ++i) 7661590Srgrimes { 7671590Srgrimes c = ((unsigned char *)s)[i]; 7681590Srgrimes if (c == '\\' || c == cache[0]) 7691590Srgrimes { 7701590Srgrimes cachec('\\'); 7711590Srgrimes cachec(c); 7721590Srgrimes } 7731590Srgrimes else if (isprint(c)) 7741590Srgrimes cachec(c); 7751590Srgrimes else 7761590Srgrimes { 7771590Srgrimes cachec('\\'); 7781590Srgrimes switch (c) 7791590Srgrimes { 7801590Srgrimes case 7: cachec('a'); break; 7811590Srgrimes case '\b': cachec('b'); break; 7821590Srgrimes case '\f': cachec('f'); break; 7831590Srgrimes case '\n': cachec('n'); break; 7841590Srgrimes case '\r': cachec('r'); break; 7851590Srgrimes case '\t': cachec('t'); break; 7861590Srgrimes case '\v': cachec('v'); break; 7871590Srgrimes default: 7881590Srgrimes cachec(((c >> 6) & 7) + '0'); 7891590Srgrimes cachec(((c >> 3) & 7) + '0'); 7901590Srgrimes cachec((c & 7) + '0'); 7911590Srgrimes break; 7921590Srgrimes } 7931590Srgrimes } 7941590Srgrimes } 7951590Srgrimes 7961590Srgrimes if (n == 1) 7971590Srgrimes cachec('\''); 7981590Srgrimes else 7991590Srgrimes cachec('"'); 8001590Srgrimes 8011590Srgrimes cachec(NUL); 8021590Srgrimes bp = lookup(cache); 8031590Srgrimes bp->class = TERM; 8041590Srgrimes if (n == 1 && bp->value == UNDEFINED) 8051590Srgrimes bp->value = *(unsigned char *)s; 806214961Sobrien free(s); 8071590Srgrimes 8081590Srgrimes return (bp); 8091590Srgrimes} 8101590Srgrimes 8111590Srgrimes 81221622Sstevestatic int 813214959Sobrienis_reserved(char *name) 8141590Srgrimes{ 8151590Srgrimes char *s; 8161590Srgrimes 8171590Srgrimes if (strcmp(name, ".") == 0 || 8181590Srgrimes strcmp(name, "$accept") == 0 || 8191590Srgrimes strcmp(name, "$end") == 0) 8201590Srgrimes return (1); 8211590Srgrimes 8221590Srgrimes if (name[0] == '$' && name[1] == '$' && isdigit(name[2])) 8231590Srgrimes { 8241590Srgrimes s = name + 3; 8251590Srgrimes while (isdigit(*s)) ++s; 8261590Srgrimes if (*s == NUL) return (1); 8271590Srgrimes } 8281590Srgrimes 8291590Srgrimes return (0); 8301590Srgrimes} 8311590Srgrimes 8321590Srgrimes 83321622Sstevestatic bucket * 834214959Sobrienget_name(void) 8351590Srgrimes{ 83687171Smarkm int c; 8371590Srgrimes 8381590Srgrimes cinc = 0; 8391590Srgrimes for (c = *cptr; IS_IDENT(c); c = *++cptr) 8401590Srgrimes cachec(c); 8411590Srgrimes cachec(NUL); 8421590Srgrimes 8431590Srgrimes if (is_reserved(cache)) used_reserved(cache); 8441590Srgrimes 8451590Srgrimes return (lookup(cache)); 8461590Srgrimes} 8471590Srgrimes 8481590Srgrimes 84921622Sstevestatic int 850214959Sobrienget_number(void) 8511590Srgrimes{ 85287171Smarkm int c; 85387171Smarkm int n; 8541590Srgrimes 8551590Srgrimes n = 0; 8561590Srgrimes for (c = *cptr; isdigit(c); c = *++cptr) 8571590Srgrimes n = 10*n + (c - '0'); 8581590Srgrimes 8591590Srgrimes return (n); 8601590Srgrimes} 8611590Srgrimes 8621590Srgrimes 86321622Sstevestatic char * 864214959Sobrienget_tag(void) 8651590Srgrimes{ 86687171Smarkm int c; 86787171Smarkm int i; 86887171Smarkm char *s; 8691590Srgrimes int t_lineno = lineno; 8701590Srgrimes char *t_line = dup_line(); 8711590Srgrimes char *t_cptr = t_line + (cptr - line); 8721590Srgrimes 8731590Srgrimes ++cptr; 8741590Srgrimes c = nextc(); 8751590Srgrimes if (c == EOF) unexpected_EOF(); 8761590Srgrimes if (!isalpha(c) && c != '_' && c != '$') 8771590Srgrimes illegal_tag(t_lineno, t_line, t_cptr); 8781590Srgrimes 8791590Srgrimes cinc = 0; 8801590Srgrimes do { cachec(c); c = *++cptr; } while (IS_IDENT(c)); 8811590Srgrimes cachec(NUL); 8821590Srgrimes 8831590Srgrimes c = nextc(); 8841590Srgrimes if (c == EOF) unexpected_EOF(); 8851590Srgrimes if (c != '>') 8861590Srgrimes illegal_tag(t_lineno, t_line, t_cptr); 8871590Srgrimes ++cptr; 8881590Srgrimes 8891590Srgrimes for (i = 0; i < ntags; ++i) 8901590Srgrimes { 8911590Srgrimes if (strcmp(cache, tag_table[i]) == 0) 8921590Srgrimes return (tag_table[i]); 8931590Srgrimes } 8941590Srgrimes 8951590Srgrimes if (ntags >= tagmax) 8961590Srgrimes { 8971590Srgrimes tagmax += 16; 8981590Srgrimes tag_table = (char **) 899214961Sobrien (tag_table ? realloc(tag_table, tagmax*sizeof(char *)) 900214961Sobrien : malloc(tagmax*sizeof(char *))); 9011590Srgrimes if (tag_table == 0) no_space(); 9021590Srgrimes } 9031590Srgrimes 904214961Sobrien s = malloc(cinc); 9051590Srgrimes if (s == 0) no_space(); 9061590Srgrimes strcpy(s, cache); 9071590Srgrimes tag_table[ntags] = s; 9081590Srgrimes ++ntags; 909214961Sobrien free(t_line); 9101590Srgrimes return (s); 9111590Srgrimes} 9121590Srgrimes 9131590Srgrimes 91421622Sstevestatic void 915214959Sobriendeclare_tokens(int assoc) 9161590Srgrimes{ 91787171Smarkm int c; 91887171Smarkm bucket *bp; 9191590Srgrimes int value; 9201590Srgrimes char *tag = 0; 9211590Srgrimes 9221590Srgrimes if (assoc != TOKEN) ++prec; 9231590Srgrimes 9241590Srgrimes c = nextc(); 9251590Srgrimes if (c == EOF) unexpected_EOF(); 9261590Srgrimes if (c == '<') 9271590Srgrimes { 9281590Srgrimes tag = get_tag(); 9291590Srgrimes c = nextc(); 9301590Srgrimes if (c == EOF) unexpected_EOF(); 9311590Srgrimes } 9321590Srgrimes 9331590Srgrimes for (;;) 9341590Srgrimes { 9351590Srgrimes if (isalpha(c) || c == '_' || c == '.' || c == '$') 9361590Srgrimes bp = get_name(); 9371590Srgrimes else if (c == '\'' || c == '"') 9381590Srgrimes bp = get_literal(); 9391590Srgrimes else 9401590Srgrimes return; 9411590Srgrimes 9421590Srgrimes if (bp == goal) tokenized_start(bp->name); 9431590Srgrimes bp->class = TERM; 9441590Srgrimes 9451590Srgrimes if (tag) 9461590Srgrimes { 9471590Srgrimes if (bp->tag && tag != bp->tag) 9481590Srgrimes retyped_warning(bp->name); 9491590Srgrimes bp->tag = tag; 9501590Srgrimes } 9511590Srgrimes 9521590Srgrimes if (assoc != TOKEN) 9531590Srgrimes { 9541590Srgrimes if (bp->prec && prec != bp->prec) 9551590Srgrimes reprec_warning(bp->name); 9561590Srgrimes bp->assoc = assoc; 9571590Srgrimes bp->prec = prec; 9581590Srgrimes } 9591590Srgrimes 9601590Srgrimes c = nextc(); 9611590Srgrimes if (c == EOF) unexpected_EOF(); 9621590Srgrimes value = UNDEFINED; 9631590Srgrimes if (isdigit(c)) 9641590Srgrimes { 9651590Srgrimes value = get_number(); 9661590Srgrimes if (bp->value != UNDEFINED && value != bp->value) 9671590Srgrimes revalued_warning(bp->name); 9681590Srgrimes bp->value = value; 9691590Srgrimes c = nextc(); 9701590Srgrimes if (c == EOF) unexpected_EOF(); 9711590Srgrimes } 9721590Srgrimes } 9731590Srgrimes} 9741590Srgrimes 9751590Srgrimes 97649208Sobrien/* 97749208Sobrien * %expect requires special handling 97849208Sobrien * as it really isn't part of the yacc 97949208Sobrien * grammar only a flag for yacc proper. 98049208Sobrien */ 98121622Sstevestatic void 982214959Sobriendeclare_expect(int assoc) 98349208Sobrien{ 98487171Smarkm int c; 98549208Sobrien 98649208Sobrien if (assoc != EXPECT) ++prec; 98749208Sobrien 98849208Sobrien /* 98949208Sobrien * Stay away from nextc - doesn't 99049208Sobrien * detect EOL and will read to EOF. 99149208Sobrien */ 99249208Sobrien c = *++cptr; 99349208Sobrien if (c == EOF) unexpected_EOF(); 99449208Sobrien 99549208Sobrien for(;;) 99649208Sobrien { 99749208Sobrien if (isdigit(c)) 99849208Sobrien { 99949208Sobrien SRexpect = get_number(); 100049208Sobrien break; 100149208Sobrien } 100249208Sobrien /* 100349208Sobrien * Looking for number before EOL. 100449208Sobrien * Spaces, tabs, and numbers are ok, 100549208Sobrien * words, punc., etc. are syntax errors. 100649208Sobrien */ 100749208Sobrien else if (c == '\n' || isalpha(c) || !isspace(c)) 100849208Sobrien { 100949208Sobrien syntax_error(lineno, line, cptr); 101049208Sobrien } 101149208Sobrien else 101249208Sobrien { 101349208Sobrien c = *++cptr; 101449208Sobrien if (c == EOF) unexpected_EOF(); 101549208Sobrien } 101649208Sobrien } 101749208Sobrien} 101849208Sobrien 101949208Sobrien 102049208Sobrienstatic void 1021214959Sobriendeclare_types(void) 10221590Srgrimes{ 102387171Smarkm int c; 102487171Smarkm bucket *bp; 10251590Srgrimes char *tag; 10261590Srgrimes 10271590Srgrimes c = nextc(); 10281590Srgrimes if (c == EOF) unexpected_EOF(); 10291590Srgrimes if (c != '<') syntax_error(lineno, line, cptr); 10301590Srgrimes tag = get_tag(); 10311590Srgrimes 10321590Srgrimes for (;;) 10331590Srgrimes { 10341590Srgrimes c = nextc(); 10351590Srgrimes if (isalpha(c) || c == '_' || c == '.' || c == '$') 10361590Srgrimes bp = get_name(); 10371590Srgrimes else if (c == '\'' || c == '"') 10381590Srgrimes bp = get_literal(); 10391590Srgrimes else 10401590Srgrimes return; 10411590Srgrimes 10421590Srgrimes if (bp->tag && tag != bp->tag) 10431590Srgrimes retyped_warning(bp->name); 10441590Srgrimes bp->tag = tag; 10451590Srgrimes } 10461590Srgrimes} 10471590Srgrimes 10481590Srgrimes 104921622Sstevestatic void 1050214959Sobriendeclare_start(void) 10511590Srgrimes{ 105287171Smarkm int c; 105387171Smarkm bucket *bp; 10541590Srgrimes 10551590Srgrimes c = nextc(); 10561590Srgrimes if (c == EOF) unexpected_EOF(); 10571590Srgrimes if (!isalpha(c) && c != '_' && c != '.' && c != '$') 10581590Srgrimes syntax_error(lineno, line, cptr); 10591590Srgrimes bp = get_name(); 10601590Srgrimes if (bp->class == TERM) 10611590Srgrimes terminal_start(bp->name); 10621590Srgrimes if (goal && goal != bp) 10631590Srgrimes restarted_warning(); 10641590Srgrimes goal = bp; 10651590Srgrimes} 10661590Srgrimes 10671590Srgrimes 106821622Sstevestatic void 1069214959Sobrienread_declarations(void) 10701590Srgrimes{ 107187171Smarkm int c, k; 10721590Srgrimes 10731590Srgrimes cache_size = 256; 1074214961Sobrien cache = malloc(cache_size); 10751590Srgrimes if (cache == 0) no_space(); 10761590Srgrimes 10771590Srgrimes for (;;) 10781590Srgrimes { 10791590Srgrimes c = nextc(); 10801590Srgrimes if (c == EOF) unexpected_EOF(); 10811590Srgrimes if (c != '%') syntax_error(lineno, line, cptr); 10821590Srgrimes switch (k = keyword()) 10831590Srgrimes { 10841590Srgrimes case MARK: 10851590Srgrimes return; 10861590Srgrimes 10871590Srgrimes case IDENT: 10881590Srgrimes copy_ident(); 10891590Srgrimes break; 10901590Srgrimes 10911590Srgrimes case TEXT: 10921590Srgrimes copy_text(); 10931590Srgrimes break; 10941590Srgrimes 10951590Srgrimes case UNION: 10961590Srgrimes copy_union(); 10971590Srgrimes break; 10981590Srgrimes 10991590Srgrimes case TOKEN: 11001590Srgrimes case LEFT: 11011590Srgrimes case RIGHT: 11021590Srgrimes case NONASSOC: 11031590Srgrimes declare_tokens(k); 11041590Srgrimes break; 11051590Srgrimes 110649208Sobrien case EXPECT: 110749208Sobrien declare_expect(k); 110849208Sobrien break; 110949208Sobrien 11101590Srgrimes case TYPE: 11111590Srgrimes declare_types(); 11121590Srgrimes break; 11131590Srgrimes 11141590Srgrimes case START: 11151590Srgrimes declare_start(); 11161590Srgrimes break; 11171590Srgrimes } 11181590Srgrimes } 11191590Srgrimes} 11201590Srgrimes 11211590Srgrimes 112221622Sstevestatic void 1123214959Sobrieninitialize_grammar(void) 11241590Srgrimes{ 11251590Srgrimes nitems = 4; 11261590Srgrimes maxitems = 300; 1127214961Sobrien pitem = malloc(maxitems*sizeof(bucket *)); 11281590Srgrimes if (pitem == 0) no_space(); 11291590Srgrimes pitem[0] = 0; 11301590Srgrimes pitem[1] = 0; 11311590Srgrimes pitem[2] = 0; 11321590Srgrimes pitem[3] = 0; 11331590Srgrimes 11341590Srgrimes nrules = 3; 11351590Srgrimes maxrules = 100; 1136214961Sobrien plhs = malloc(maxrules*sizeof(bucket *)); 11371590Srgrimes if (plhs == 0) no_space(); 11381590Srgrimes plhs[0] = 0; 11391590Srgrimes plhs[1] = 0; 11401590Srgrimes plhs[2] = 0; 1141214961Sobrien rprec = malloc(maxrules*sizeof(short)); 11421590Srgrimes if (rprec == 0) no_space(); 11431590Srgrimes rprec[0] = 0; 11441590Srgrimes rprec[1] = 0; 11451590Srgrimes rprec[2] = 0; 1146214961Sobrien rassoc = malloc(maxrules*sizeof(char)); 11471590Srgrimes if (rassoc == 0) no_space(); 11481590Srgrimes rassoc[0] = TOKEN; 11491590Srgrimes rassoc[1] = TOKEN; 11501590Srgrimes rassoc[2] = TOKEN; 11511590Srgrimes} 11521590Srgrimes 11531590Srgrimes 115421622Sstevestatic void 1155214959Sobrienexpand_items(void) 11561590Srgrimes{ 11571590Srgrimes maxitems += 300; 1158214961Sobrien pitem = realloc(pitem, maxitems*sizeof(bucket *)); 11591590Srgrimes if (pitem == 0) no_space(); 11601590Srgrimes} 11611590Srgrimes 11621590Srgrimes 116321622Sstevestatic void 1164214959Sobrienexpand_rules(void) 11651590Srgrimes{ 11661590Srgrimes maxrules += 100; 1167214961Sobrien plhs = realloc(plhs, maxrules*sizeof(bucket *)); 11681590Srgrimes if (plhs == 0) no_space(); 1169214961Sobrien rprec = realloc(rprec, maxrules*sizeof(short)); 11701590Srgrimes if (rprec == 0) no_space(); 1171214961Sobrien rassoc = realloc(rassoc, maxrules*sizeof(char)); 11721590Srgrimes if (rassoc == 0) no_space(); 11731590Srgrimes} 11741590Srgrimes 11751590Srgrimes 117621622Sstevestatic void 1177214959Sobrienadvance_to_start(void) 11781590Srgrimes{ 117987171Smarkm int c; 118087171Smarkm bucket *bp; 11811590Srgrimes char *s_cptr; 11821590Srgrimes int s_lineno; 11831590Srgrimes 11841590Srgrimes for (;;) 11851590Srgrimes { 11861590Srgrimes c = nextc(); 11871590Srgrimes if (c != '%') break; 11881590Srgrimes s_cptr = cptr; 11891590Srgrimes switch (keyword()) 11901590Srgrimes { 11911590Srgrimes case MARK: 11921590Srgrimes no_grammar(); 11931590Srgrimes 11941590Srgrimes case TEXT: 11951590Srgrimes copy_text(); 11961590Srgrimes break; 11971590Srgrimes 11981590Srgrimes case START: 11991590Srgrimes declare_start(); 12001590Srgrimes break; 12011590Srgrimes 12021590Srgrimes default: 12031590Srgrimes syntax_error(lineno, line, s_cptr); 12041590Srgrimes } 12051590Srgrimes } 12061590Srgrimes 12071590Srgrimes c = nextc(); 12081590Srgrimes if (!isalpha(c) && c != '_' && c != '.' && c != '_') 12091590Srgrimes syntax_error(lineno, line, cptr); 12101590Srgrimes bp = get_name(); 12111590Srgrimes if (goal == 0) 12121590Srgrimes { 12131590Srgrimes if (bp->class == TERM) 12141590Srgrimes terminal_start(bp->name); 12151590Srgrimes goal = bp; 12161590Srgrimes } 12171590Srgrimes 12181590Srgrimes s_lineno = lineno; 12191590Srgrimes c = nextc(); 12201590Srgrimes if (c == EOF) unexpected_EOF(); 12211590Srgrimes if (c != ':') syntax_error(lineno, line, cptr); 12221590Srgrimes start_rule(bp, s_lineno); 12231590Srgrimes ++cptr; 12241590Srgrimes} 12251590Srgrimes 12261590Srgrimes 122721622Sstevestatic void 1228214959Sobrienstart_rule(bucket *bp, int s_lineno) 12291590Srgrimes{ 12301590Srgrimes if (bp->class == TERM) 12311590Srgrimes terminal_lhs(s_lineno); 12321590Srgrimes bp->class = NONTERM; 12331590Srgrimes if (nrules >= maxrules) 12341590Srgrimes expand_rules(); 12351590Srgrimes plhs[nrules] = bp; 12361590Srgrimes rprec[nrules] = UNDEFINED; 12371590Srgrimes rassoc[nrules] = TOKEN; 12381590Srgrimes} 12391590Srgrimes 12401590Srgrimes 124121622Sstevestatic void 1242214959Sobrienend_rule(void) 12431590Srgrimes{ 124487171Smarkm int i; 12451590Srgrimes 12461590Srgrimes if (!last_was_action && plhs[nrules]->tag) 12471590Srgrimes { 12481590Srgrimes for (i = nitems - 1; pitem[i]; --i) continue; 12491590Srgrimes if (pitem[i+1] == 0 || pitem[i+1]->tag != plhs[nrules]->tag) 12501590Srgrimes default_action_warning(); 12511590Srgrimes } 12521590Srgrimes 12531590Srgrimes last_was_action = 0; 12541590Srgrimes if (nitems >= maxitems) expand_items(); 12551590Srgrimes pitem[nitems] = 0; 12561590Srgrimes ++nitems; 12571590Srgrimes ++nrules; 12581590Srgrimes} 12591590Srgrimes 12601590Srgrimes 126121622Sstevestatic void 1262214959Sobrieninsert_empty_rule(void) 12631590Srgrimes{ 126487171Smarkm bucket *bp, **bpp; 12651590Srgrimes 12661590Srgrimes assert(cache); 12671590Srgrimes sprintf(cache, "$$%d", ++gensym); 12681590Srgrimes bp = make_bucket(cache); 12691590Srgrimes last_symbol->next = bp; 12701590Srgrimes last_symbol = bp; 12711590Srgrimes bp->tag = plhs[nrules]->tag; 12721590Srgrimes bp->class = NONTERM; 12731590Srgrimes 12741590Srgrimes if ((nitems += 2) > maxitems) 12751590Srgrimes expand_items(); 12761590Srgrimes bpp = pitem + nitems - 1; 12771590Srgrimes *bpp-- = bp; 127821622Ssteve while ((bpp[0] = bpp[-1])) --bpp; 12791590Srgrimes 12801590Srgrimes if (++nrules >= maxrules) 12811590Srgrimes expand_rules(); 12821590Srgrimes plhs[nrules] = plhs[nrules-1]; 12831590Srgrimes plhs[nrules-1] = bp; 12841590Srgrimes rprec[nrules] = rprec[nrules-1]; 12851590Srgrimes rprec[nrules-1] = 0; 12861590Srgrimes rassoc[nrules] = rassoc[nrules-1]; 12871590Srgrimes rassoc[nrules-1] = TOKEN; 12881590Srgrimes} 12891590Srgrimes 12901590Srgrimes 129121622Sstevestatic void 1292214959Sobrienadd_symbol(void) 12931590Srgrimes{ 129487171Smarkm int c; 129587171Smarkm bucket *bp; 12961590Srgrimes int s_lineno = lineno; 12971590Srgrimes 12981590Srgrimes c = *cptr; 12991590Srgrimes if (c == '\'' || c == '"') 13001590Srgrimes bp = get_literal(); 13011590Srgrimes else 13021590Srgrimes bp = get_name(); 13031590Srgrimes 13041590Srgrimes c = nextc(); 13051590Srgrimes if (c == ':') 13061590Srgrimes { 13071590Srgrimes end_rule(); 13081590Srgrimes start_rule(bp, s_lineno); 13091590Srgrimes ++cptr; 13101590Srgrimes return; 13111590Srgrimes } 13121590Srgrimes 13131590Srgrimes if (last_was_action) 13141590Srgrimes insert_empty_rule(); 13151590Srgrimes last_was_action = 0; 13161590Srgrimes 13171590Srgrimes if (++nitems > maxitems) 13181590Srgrimes expand_items(); 13191590Srgrimes pitem[nitems-1] = bp; 13201590Srgrimes} 13211590Srgrimes 13221590Srgrimes 132321622Sstevestatic void 1324214959Sobriencopy_action(void) 13251590Srgrimes{ 132687171Smarkm int c; 132787171Smarkm int i, n; 13281590Srgrimes int depth; 13291590Srgrimes int quote; 13301590Srgrimes char *tag; 133187171Smarkm FILE *f = action_file; 13321590Srgrimes int a_lineno = lineno; 13331590Srgrimes char *a_line = dup_line(); 13341590Srgrimes char *a_cptr = a_line + (cptr - line); 13351590Srgrimes 13361590Srgrimes if (last_was_action) 13371590Srgrimes insert_empty_rule(); 13381590Srgrimes last_was_action = 1; 13391590Srgrimes 13401590Srgrimes fprintf(f, "case %d:\n", nrules - 2); 13411590Srgrimes if (!lflag) 13421590Srgrimes fprintf(f, line_format, lineno, input_file_name); 13431590Srgrimes if (*cptr == '=') ++cptr; 13441590Srgrimes 13451590Srgrimes n = 0; 13461590Srgrimes for (i = nitems - 1; pitem[i]; --i) ++n; 13471590Srgrimes 13481590Srgrimes depth = 0; 13491590Srgrimesloop: 13501590Srgrimes c = *cptr; 13511590Srgrimes if (c == '$') 13521590Srgrimes { 13531590Srgrimes if (cptr[1] == '<') 13541590Srgrimes { 13551590Srgrimes int d_lineno = lineno; 13561590Srgrimes char *d_line = dup_line(); 13571590Srgrimes char *d_cptr = d_line + (cptr - line); 13581590Srgrimes 13591590Srgrimes ++cptr; 13601590Srgrimes tag = get_tag(); 13611590Srgrimes c = *cptr; 13621590Srgrimes if (c == '$') 13631590Srgrimes { 13641590Srgrimes fprintf(f, "yyval.%s", tag); 13651590Srgrimes ++cptr; 1366214961Sobrien free(d_line); 13671590Srgrimes goto loop; 13681590Srgrimes } 13691590Srgrimes else if (isdigit(c)) 13701590Srgrimes { 13711590Srgrimes i = get_number(); 13721590Srgrimes if (i > n) dollar_warning(d_lineno, i); 13731590Srgrimes fprintf(f, "yyvsp[%d].%s", i - n, tag); 1374214961Sobrien free(d_line); 13751590Srgrimes goto loop; 13761590Srgrimes } 13771590Srgrimes else if (c == '-' && isdigit(cptr[1])) 13781590Srgrimes { 13791590Srgrimes ++cptr; 13801590Srgrimes i = -get_number() - n; 13811590Srgrimes fprintf(f, "yyvsp[%d].%s", i, tag); 1382214961Sobrien free(d_line); 13831590Srgrimes goto loop; 13841590Srgrimes } 13851590Srgrimes else 13861590Srgrimes dollar_error(d_lineno, d_line, d_cptr); 13871590Srgrimes } 13881590Srgrimes else if (cptr[1] == '$') 13891590Srgrimes { 13901590Srgrimes if (ntags) 13911590Srgrimes { 13921590Srgrimes tag = plhs[nrules]->tag; 13931590Srgrimes if (tag == 0) untyped_lhs(); 13941590Srgrimes fprintf(f, "yyval.%s", tag); 13951590Srgrimes } 13961590Srgrimes else 13971590Srgrimes fprintf(f, "yyval"); 13981590Srgrimes cptr += 2; 13991590Srgrimes goto loop; 14001590Srgrimes } 14011590Srgrimes else if (isdigit(cptr[1])) 14021590Srgrimes { 14031590Srgrimes ++cptr; 14041590Srgrimes i = get_number(); 14051590Srgrimes if (ntags) 14061590Srgrimes { 14071590Srgrimes if (i <= 0 || i > n) 14081590Srgrimes unknown_rhs(i); 14091590Srgrimes tag = pitem[nitems + i - n - 1]->tag; 14101590Srgrimes if (tag == 0) untyped_rhs(i, pitem[nitems + i - n - 1]->name); 14111590Srgrimes fprintf(f, "yyvsp[%d].%s", i - n, tag); 14121590Srgrimes } 14131590Srgrimes else 14141590Srgrimes { 14151590Srgrimes if (i > n) 14161590Srgrimes dollar_warning(lineno, i); 14171590Srgrimes fprintf(f, "yyvsp[%d]", i - n); 14181590Srgrimes } 14191590Srgrimes goto loop; 14201590Srgrimes } 14211590Srgrimes else if (cptr[1] == '-') 14221590Srgrimes { 14231590Srgrimes cptr += 2; 14241590Srgrimes i = get_number(); 14251590Srgrimes if (ntags) 14261590Srgrimes unknown_rhs(-i); 14271590Srgrimes fprintf(f, "yyvsp[%d]", -i - n); 14281590Srgrimes goto loop; 14291590Srgrimes } 14301590Srgrimes } 14311590Srgrimes if (isalpha(c) || c == '_' || c == '$') 14321590Srgrimes { 14331590Srgrimes do 14341590Srgrimes { 14351590Srgrimes putc(c, f); 14361590Srgrimes c = *++cptr; 14371590Srgrimes } while (isalnum(c) || c == '_' || c == '$'); 14381590Srgrimes goto loop; 14391590Srgrimes } 14401590Srgrimes putc(c, f); 14411590Srgrimes ++cptr; 14421590Srgrimes switch (c) 14431590Srgrimes { 14441590Srgrimes case '\n': 14451590Srgrimes next_line: 14461590Srgrimes get_line(); 14471590Srgrimes if (line) goto loop; 14481590Srgrimes unterminated_action(a_lineno, a_line, a_cptr); 14491590Srgrimes 14501590Srgrimes case ';': 14511590Srgrimes if (depth > 0) goto loop; 14521590Srgrimes fprintf(f, "\nbreak;\n"); 14531590Srgrimes return; 14541590Srgrimes 14551590Srgrimes case '{': 14561590Srgrimes ++depth; 14571590Srgrimes goto loop; 14581590Srgrimes 14591590Srgrimes case '}': 14601590Srgrimes if (--depth > 0) goto loop; 14611590Srgrimes fprintf(f, "\nbreak;\n"); 14621590Srgrimes return; 14631590Srgrimes 14641590Srgrimes case '\'': 14651590Srgrimes case '"': 14661590Srgrimes { 14671590Srgrimes int s_lineno = lineno; 14681590Srgrimes char *s_line = dup_line(); 14691590Srgrimes char *s_cptr = s_line + (cptr - line - 1); 14701590Srgrimes 14711590Srgrimes quote = c; 14721590Srgrimes for (;;) 14731590Srgrimes { 14741590Srgrimes c = *cptr++; 14751590Srgrimes putc(c, f); 14761590Srgrimes if (c == quote) 14771590Srgrimes { 1478214961Sobrien free(s_line); 14791590Srgrimes goto loop; 14801590Srgrimes } 14811590Srgrimes if (c == '\n') 14821590Srgrimes unterminated_string(s_lineno, s_line, s_cptr); 14831590Srgrimes if (c == '\\') 14841590Srgrimes { 14851590Srgrimes c = *cptr++; 14861590Srgrimes putc(c, f); 14871590Srgrimes if (c == '\n') 14881590Srgrimes { 14891590Srgrimes get_line(); 14901590Srgrimes if (line == 0) 14911590Srgrimes unterminated_string(s_lineno, s_line, s_cptr); 14921590Srgrimes } 14931590Srgrimes } 14941590Srgrimes } 14951590Srgrimes } 14961590Srgrimes 14971590Srgrimes case '/': 14981590Srgrimes c = *cptr; 14991590Srgrimes if (c == '/') 15001590Srgrimes { 15011590Srgrimes putc('*', f); 15021590Srgrimes while ((c = *++cptr) != '\n') 15031590Srgrimes { 15041590Srgrimes if (c == '*' && cptr[1] == '/') 15051590Srgrimes fprintf(f, "* "); 15061590Srgrimes else 15071590Srgrimes putc(c, f); 15081590Srgrimes } 15091590Srgrimes fprintf(f, "*/\n"); 15101590Srgrimes goto next_line; 15111590Srgrimes } 15121590Srgrimes if (c == '*') 15131590Srgrimes { 15141590Srgrimes int c_lineno = lineno; 15151590Srgrimes char *c_line = dup_line(); 15161590Srgrimes char *c_cptr = c_line + (cptr - line - 1); 15171590Srgrimes 15181590Srgrimes putc('*', f); 15191590Srgrimes ++cptr; 15201590Srgrimes for (;;) 15211590Srgrimes { 15221590Srgrimes c = *cptr++; 15231590Srgrimes putc(c, f); 15241590Srgrimes if (c == '*' && *cptr == '/') 15251590Srgrimes { 15261590Srgrimes putc('/', f); 15271590Srgrimes ++cptr; 1528214961Sobrien free(c_line); 15291590Srgrimes goto loop; 15301590Srgrimes } 15311590Srgrimes if (c == '\n') 15321590Srgrimes { 15331590Srgrimes get_line(); 15341590Srgrimes if (line == 0) 15351590Srgrimes unterminated_comment(c_lineno, c_line, c_cptr); 15361590Srgrimes } 15371590Srgrimes } 15381590Srgrimes } 15391590Srgrimes goto loop; 15401590Srgrimes 15411590Srgrimes default: 15421590Srgrimes goto loop; 15431590Srgrimes } 15441590Srgrimes} 15451590Srgrimes 15461590Srgrimes 154721622Sstevestatic int 1548214959Sobrienmark_symbol(void) 15491590Srgrimes{ 155087171Smarkm int c; 155187171Smarkm bucket *bp = NULL; 15521590Srgrimes 15531590Srgrimes c = cptr[1]; 15541590Srgrimes if (c == '%' || c == '\\') 15551590Srgrimes { 15561590Srgrimes cptr += 2; 15571590Srgrimes return (1); 15581590Srgrimes } 15591590Srgrimes 15601590Srgrimes if (c == '=') 15611590Srgrimes cptr += 2; 15621590Srgrimes else if ((c == 'p' || c == 'P') && 15631590Srgrimes ((c = cptr[2]) == 'r' || c == 'R') && 15641590Srgrimes ((c = cptr[3]) == 'e' || c == 'E') && 15651590Srgrimes ((c = cptr[4]) == 'c' || c == 'C') && 15661590Srgrimes ((c = cptr[5], !IS_IDENT(c)))) 15671590Srgrimes cptr += 5; 15681590Srgrimes else 15691590Srgrimes syntax_error(lineno, line, cptr); 15701590Srgrimes 15711590Srgrimes c = nextc(); 15721590Srgrimes if (isalpha(c) || c == '_' || c == '.' || c == '$') 15731590Srgrimes bp = get_name(); 15741590Srgrimes else if (c == '\'' || c == '"') 15751590Srgrimes bp = get_literal(); 15761590Srgrimes else 15771590Srgrimes { 15781590Srgrimes syntax_error(lineno, line, cptr); 15791590Srgrimes /*NOTREACHED*/ 15801590Srgrimes } 15811590Srgrimes 15821590Srgrimes if (rprec[nrules] != UNDEFINED && bp->prec != rprec[nrules]) 15831590Srgrimes prec_redeclared(); 15841590Srgrimes 15851590Srgrimes rprec[nrules] = bp->prec; 15861590Srgrimes rassoc[nrules] = bp->assoc; 15871590Srgrimes return (0); 15881590Srgrimes} 15891590Srgrimes 15901590Srgrimes 159121622Sstevestatic void 1592214959Sobrienread_grammar(void) 15931590Srgrimes{ 159487171Smarkm int c; 15951590Srgrimes 15961590Srgrimes initialize_grammar(); 15971590Srgrimes advance_to_start(); 15981590Srgrimes 15991590Srgrimes for (;;) 16001590Srgrimes { 16011590Srgrimes c = nextc(); 16021590Srgrimes if (c == EOF) break; 16031590Srgrimes if (isalpha(c) || c == '_' || c == '.' || c == '$' || c == '\'' || 16041590Srgrimes c == '"') 16051590Srgrimes add_symbol(); 16061590Srgrimes else if (c == '{' || c == '=') 16071590Srgrimes copy_action(); 16081590Srgrimes else if (c == '|') 16091590Srgrimes { 16101590Srgrimes end_rule(); 16111590Srgrimes start_rule(plhs[nrules-1], 0); 16121590Srgrimes ++cptr; 16131590Srgrimes } 16141590Srgrimes else if (c == '%') 16151590Srgrimes { 16161590Srgrimes if (mark_symbol()) break; 16171590Srgrimes } 16181590Srgrimes else 16191590Srgrimes syntax_error(lineno, line, cptr); 16201590Srgrimes } 16211590Srgrimes end_rule(); 16221590Srgrimes} 16231590Srgrimes 16241590Srgrimes 162521622Sstevestatic void 1626214959Sobrienfree_tags(void) 16271590Srgrimes{ 162887171Smarkm int i; 16291590Srgrimes 16301590Srgrimes if (tag_table == 0) return; 16311590Srgrimes 16321590Srgrimes for (i = 0; i < ntags; ++i) 16331590Srgrimes { 16341590Srgrimes assert(tag_table[i]); 1635214961Sobrien free(tag_table[i]); 16361590Srgrimes } 1637214961Sobrien free(tag_table); 16381590Srgrimes} 16391590Srgrimes 16401590Srgrimes 164121622Sstevestatic void 1642214959Sobrienpack_names(void) 16431590Srgrimes{ 164487171Smarkm bucket *bp; 164587171Smarkm char *p, *s, *t; 16461590Srgrimes 16471590Srgrimes name_pool_size = 13; /* 13 == sizeof("$end") + sizeof("$accept") */ 16481590Srgrimes for (bp = first_symbol; bp; bp = bp->next) 16491590Srgrimes name_pool_size += strlen(bp->name) + 1; 1650214961Sobrien name_pool = malloc(name_pool_size); 16511590Srgrimes if (name_pool == 0) no_space(); 16521590Srgrimes 16531590Srgrimes strcpy(name_pool, "$accept"); 16541590Srgrimes strcpy(name_pool+8, "$end"); 16551590Srgrimes t = name_pool + 13; 16561590Srgrimes for (bp = first_symbol; bp; bp = bp->next) 16571590Srgrimes { 16581590Srgrimes p = t; 16591590Srgrimes s = bp->name; 166021622Ssteve while ((*t++ = *s++)) continue; 1661214961Sobrien free(bp->name); 16621590Srgrimes bp->name = p; 16631590Srgrimes } 16641590Srgrimes} 16651590Srgrimes 16661590Srgrimes 166721622Sstevestatic void 1668214959Sobriencheck_symbols(void) 16691590Srgrimes{ 167087171Smarkm bucket *bp; 16711590Srgrimes 16721590Srgrimes if (goal->class == UNKNOWN) 16731590Srgrimes undefined_goal(goal->name); 16741590Srgrimes 16751590Srgrimes for (bp = first_symbol; bp; bp = bp->next) 16761590Srgrimes { 16771590Srgrimes if (bp->class == UNKNOWN) 16781590Srgrimes { 16791590Srgrimes undefined_symbol_warning(bp->name); 16801590Srgrimes bp->class = TERM; 16811590Srgrimes } 16821590Srgrimes } 16831590Srgrimes} 16841590Srgrimes 16851590Srgrimes 168621622Sstevestatic void 1687214959Sobrienpack_symbols(void) 16881590Srgrimes{ 168987171Smarkm bucket *bp; 169087171Smarkm bucket **v; 169187171Smarkm int i, j, k, n; 16921590Srgrimes 16931590Srgrimes nsyms = 2; 16941590Srgrimes ntokens = 1; 16951590Srgrimes for (bp = first_symbol; bp; bp = bp->next) 16961590Srgrimes { 16971590Srgrimes ++nsyms; 16981590Srgrimes if (bp->class == TERM) ++ntokens; 16991590Srgrimes } 17001590Srgrimes start_symbol = ntokens; 17011590Srgrimes nvars = nsyms - ntokens; 17021590Srgrimes 1703214961Sobrien symbol_name = malloc(nsyms*sizeof(char *)); 17041590Srgrimes if (symbol_name == 0) no_space(); 1705214961Sobrien symbol_value = malloc(nsyms*sizeof(short)); 17061590Srgrimes if (symbol_value == 0) no_space(); 1707214961Sobrien symbol_prec = malloc(nsyms*sizeof(short)); 17081590Srgrimes if (symbol_prec == 0) no_space(); 1709214961Sobrien symbol_assoc = malloc(nsyms); 17101590Srgrimes if (symbol_assoc == 0) no_space(); 17111590Srgrimes 1712214961Sobrien v = malloc(nsyms*sizeof(bucket *)); 17131590Srgrimes if (v == 0) no_space(); 17141590Srgrimes 17151590Srgrimes v[0] = 0; 17161590Srgrimes v[start_symbol] = 0; 17171590Srgrimes 17181590Srgrimes i = 1; 17191590Srgrimes j = start_symbol + 1; 17201590Srgrimes for (bp = first_symbol; bp; bp = bp->next) 17211590Srgrimes { 17221590Srgrimes if (bp->class == TERM) 17231590Srgrimes v[i++] = bp; 17241590Srgrimes else 17251590Srgrimes v[j++] = bp; 17261590Srgrimes } 17271590Srgrimes assert(i == ntokens && j == nsyms); 17281590Srgrimes 17291590Srgrimes for (i = 1; i < ntokens; ++i) 17301590Srgrimes v[i]->index = i; 17311590Srgrimes 17321590Srgrimes goal->index = start_symbol + 1; 17331590Srgrimes k = start_symbol + 2; 17341590Srgrimes while (++i < nsyms) 17351590Srgrimes if (v[i] != goal) 17361590Srgrimes { 17371590Srgrimes v[i]->index = k; 17381590Srgrimes ++k; 17391590Srgrimes } 17401590Srgrimes 17411590Srgrimes goal->value = 0; 17421590Srgrimes k = 1; 17431590Srgrimes for (i = start_symbol + 1; i < nsyms; ++i) 17441590Srgrimes { 17451590Srgrimes if (v[i] != goal) 17461590Srgrimes { 17471590Srgrimes v[i]->value = k; 17481590Srgrimes ++k; 17491590Srgrimes } 17501590Srgrimes } 17511590Srgrimes 17521590Srgrimes k = 0; 17531590Srgrimes for (i = 1; i < ntokens; ++i) 17541590Srgrimes { 17551590Srgrimes n = v[i]->value; 17561590Srgrimes if (n > 256) 17571590Srgrimes { 17581590Srgrimes for (j = k++; j > 0 && symbol_value[j-1] > n; --j) 17591590Srgrimes symbol_value[j] = symbol_value[j-1]; 17601590Srgrimes symbol_value[j] = n; 17611590Srgrimes } 17621590Srgrimes } 17631590Srgrimes 17641590Srgrimes if (v[1]->value == UNDEFINED) 17651590Srgrimes v[1]->value = 256; 17661590Srgrimes 17671590Srgrimes j = 0; 17681590Srgrimes n = 257; 17691590Srgrimes for (i = 2; i < ntokens; ++i) 17701590Srgrimes { 17711590Srgrimes if (v[i]->value == UNDEFINED) 17721590Srgrimes { 17731590Srgrimes while (j < k && n == symbol_value[j]) 17741590Srgrimes { 17751590Srgrimes while (++j < k && n == symbol_value[j]) continue; 17761590Srgrimes ++n; 17771590Srgrimes } 17781590Srgrimes v[i]->value = n; 17791590Srgrimes ++n; 17801590Srgrimes } 17811590Srgrimes } 17821590Srgrimes 17831590Srgrimes symbol_name[0] = name_pool + 8; 17841590Srgrimes symbol_value[0] = 0; 17851590Srgrimes symbol_prec[0] = 0; 17861590Srgrimes symbol_assoc[0] = TOKEN; 17871590Srgrimes for (i = 1; i < ntokens; ++i) 17881590Srgrimes { 17891590Srgrimes symbol_name[i] = v[i]->name; 17901590Srgrimes symbol_value[i] = v[i]->value; 17911590Srgrimes symbol_prec[i] = v[i]->prec; 17921590Srgrimes symbol_assoc[i] = v[i]->assoc; 17931590Srgrimes } 17941590Srgrimes symbol_name[start_symbol] = name_pool; 17951590Srgrimes symbol_value[start_symbol] = -1; 17961590Srgrimes symbol_prec[start_symbol] = 0; 17971590Srgrimes symbol_assoc[start_symbol] = TOKEN; 17981590Srgrimes for (++i; i < nsyms; ++i) 17991590Srgrimes { 18001590Srgrimes k = v[i]->index; 18011590Srgrimes symbol_name[k] = v[i]->name; 18021590Srgrimes symbol_value[k] = v[i]->value; 18031590Srgrimes symbol_prec[k] = v[i]->prec; 18041590Srgrimes symbol_assoc[k] = v[i]->assoc; 18051590Srgrimes } 18061590Srgrimes 1807214961Sobrien free(v); 18081590Srgrimes} 18091590Srgrimes 18101590Srgrimes 181121622Sstevestatic void 1812214959Sobrienpack_grammar(void) 18131590Srgrimes{ 181487171Smarkm int i, j; 181587171Smarkm int assoc, preced; 18161590Srgrimes 1817214961Sobrien ritem = malloc(nitems*sizeof(short)); 18181590Srgrimes if (ritem == 0) no_space(); 1819214961Sobrien rlhs = malloc(nrules*sizeof(short)); 18201590Srgrimes if (rlhs == 0) no_space(); 1821214961Sobrien rrhs = malloc((nrules+1)*sizeof(short)); 18221590Srgrimes if (rrhs == 0) no_space(); 1823214961Sobrien rprec = realloc(rprec, nrules*sizeof(short)); 18241590Srgrimes if (rprec == 0) no_space(); 1825214961Sobrien rassoc = realloc(rassoc, nrules); 18261590Srgrimes if (rassoc == 0) no_space(); 18271590Srgrimes 18281590Srgrimes ritem[0] = -1; 18291590Srgrimes ritem[1] = goal->index; 18301590Srgrimes ritem[2] = 0; 18311590Srgrimes ritem[3] = -2; 18321590Srgrimes rlhs[0] = 0; 18331590Srgrimes rlhs[1] = 0; 18341590Srgrimes rlhs[2] = start_symbol; 18351590Srgrimes rrhs[0] = 0; 18361590Srgrimes rrhs[1] = 0; 18371590Srgrimes rrhs[2] = 1; 18381590Srgrimes 18391590Srgrimes j = 4; 18401590Srgrimes for (i = 3; i < nrules; ++i) 18411590Srgrimes { 18421590Srgrimes rlhs[i] = plhs[i]->index; 18431590Srgrimes rrhs[i] = j; 18441590Srgrimes assoc = TOKEN; 184587171Smarkm preced = 0; 18461590Srgrimes while (pitem[j]) 18471590Srgrimes { 18481590Srgrimes ritem[j] = pitem[j]->index; 18491590Srgrimes if (pitem[j]->class == TERM) 18501590Srgrimes { 185187171Smarkm preced = pitem[j]->prec; 18521590Srgrimes assoc = pitem[j]->assoc; 18531590Srgrimes } 18541590Srgrimes ++j; 18551590Srgrimes } 18561590Srgrimes ritem[j] = -i; 18571590Srgrimes ++j; 18581590Srgrimes if (rprec[i] == UNDEFINED) 18591590Srgrimes { 186087171Smarkm rprec[i] = preced; 18611590Srgrimes rassoc[i] = assoc; 18621590Srgrimes } 18631590Srgrimes } 18641590Srgrimes rrhs[i] = j; 18651590Srgrimes 1866214961Sobrien free(plhs); 1867214961Sobrien free(pitem); 18681590Srgrimes} 18691590Srgrimes 18701590Srgrimes 187121622Sstevestatic void 1872214959Sobrienprint_grammar(void) 18731590Srgrimes{ 187487171Smarkm int i, j, k; 187593830Sobrien int spacing; 187687171Smarkm FILE *f = verbose_file; 18771590Srgrimes 18781590Srgrimes if (!vflag) return; 18791590Srgrimes 18801590Srgrimes k = 1; 188194333Sobrien spacing = 0; 18821590Srgrimes for (i = 2; i < nrules; ++i) 18831590Srgrimes { 18841590Srgrimes if (rlhs[i] != rlhs[i-1]) 18851590Srgrimes { 18861590Srgrimes if (i != 2) fprintf(f, "\n"); 18871590Srgrimes fprintf(f, "%4d %s :", i - 2, symbol_name[rlhs[i]]); 18881590Srgrimes spacing = strlen(symbol_name[rlhs[i]]) + 1; 18891590Srgrimes } 18901590Srgrimes else 18911590Srgrimes { 18921590Srgrimes fprintf(f, "%4d ", i - 2); 18931590Srgrimes j = spacing; 18941590Srgrimes while (--j >= 0) putc(' ', f); 18951590Srgrimes putc('|', f); 18961590Srgrimes } 18971590Srgrimes 18981590Srgrimes while (ritem[k] >= 0) 18991590Srgrimes { 19001590Srgrimes fprintf(f, " %s", symbol_name[ritem[k]]); 19011590Srgrimes ++k; 19021590Srgrimes } 19031590Srgrimes ++k; 19041590Srgrimes putc('\n', f); 19051590Srgrimes } 19061590Srgrimes} 19071590Srgrimes 19081590Srgrimes 190921622Sstevevoid 1910214959Sobrienreader(void) 19111590Srgrimes{ 19121590Srgrimes write_section(banner); 19131590Srgrimes create_symbol_table(); 19141590Srgrimes read_declarations(); 19151590Srgrimes read_grammar(); 19161590Srgrimes free_symbol_table(); 19171590Srgrimes free_tags(); 19181590Srgrimes pack_names(); 19191590Srgrimes check_symbols(); 19201590Srgrimes pack_symbols(); 19211590Srgrimes pack_grammar(); 19221590Srgrimes free_symbols(); 19231590Srgrimes print_grammar(); 19241590Srgrimes} 1925