xref: /minix/external/bsd/byacc/dist/reader.c (revision 0a6a1f1d)
1*0a6a1f1dSLionel Sambuc /*	$NetBSD: reader.c,v 1.12 2015/01/04 19:30:26 joerg Exp $	*/
284d9c625SLionel Sambuc 
3*0a6a1f1dSLionel Sambuc /* Id: reader.c,v 1.58 2014/10/06 22:15:08 tom Exp  */
44a17663cSThomas Veerman 
54a17663cSThomas Veerman #include "defs.h"
64a17663cSThomas Veerman 
74a17663cSThomas Veerman #include <sys/cdefs.h>
8*0a6a1f1dSLionel Sambuc __RCSID("$NetBSD: reader.c,v 1.12 2015/01/04 19:30:26 joerg Exp $");
94a17663cSThomas Veerman 
104a17663cSThomas Veerman /*  The line size must be a positive integer.  One hundred was chosen	*/
114a17663cSThomas Veerman /*  because few lines in Yacc input grammars exceed 100 characters.	*/
124a17663cSThomas Veerman /*  Note that if a line exceeds LINESIZE characters, the line buffer	*/
134a17663cSThomas Veerman /*  will be expanded to accomodate it.					*/
144a17663cSThomas Veerman 
154a17663cSThomas Veerman #define LINESIZE 100
164a17663cSThomas Veerman 
174a17663cSThomas Veerman #define L_CURL  '{'
184a17663cSThomas Veerman #define R_CURL  '}'
19*0a6a1f1dSLionel Sambuc #define L_PAREN '('
20*0a6a1f1dSLionel Sambuc #define R_PAREN ')'
21*0a6a1f1dSLionel Sambuc #define L_BRAC  '['
22*0a6a1f1dSLionel Sambuc #define R_BRAC  ']'
23*0a6a1f1dSLionel Sambuc 
24*0a6a1f1dSLionel Sambuc /* the maximum number of arguments (inherited attributes) to a non-terminal */
25*0a6a1f1dSLionel Sambuc /* this is a hard limit, but seems more than adequate */
26*0a6a1f1dSLionel Sambuc #define MAXARGS	20
274a17663cSThomas Veerman 
284a17663cSThomas Veerman static void start_rule(bucket *bp, int s_lineno);
29*0a6a1f1dSLionel Sambuc #if defined(YYBTYACC)
30*0a6a1f1dSLionel Sambuc static void copy_initial_action(void);
31*0a6a1f1dSLionel Sambuc static void copy_destructor(void);
32*0a6a1f1dSLionel Sambuc static char *process_destructor_XX(char *code, char *tag);
33*0a6a1f1dSLionel Sambuc #endif
344a17663cSThomas Veerman 
354a17663cSThomas Veerman static char *cache;
364a17663cSThomas Veerman static int cinc, cache_size;
374a17663cSThomas Veerman 
384a17663cSThomas Veerman int ntags;
39*0a6a1f1dSLionel Sambuc static int tagmax, havetags;
404a17663cSThomas Veerman static char **tag_table;
414a17663cSThomas Veerman 
424a17663cSThomas Veerman static char saw_eof;
434a17663cSThomas Veerman char unionized;
444a17663cSThomas Veerman char *cptr, *line;
454a17663cSThomas Veerman static int linesize;
464a17663cSThomas Veerman 
474a17663cSThomas Veerman static bucket *goal;
484a17663cSThomas Veerman static Value_t prec;
494a17663cSThomas Veerman static int gensym;
504a17663cSThomas Veerman static char last_was_action;
514a17663cSThomas Veerman 
524a17663cSThomas Veerman static int maxitems;
534a17663cSThomas Veerman static bucket **pitem;
544a17663cSThomas Veerman 
554a17663cSThomas Veerman static int maxrules;
564a17663cSThomas Veerman static bucket **plhs;
574a17663cSThomas Veerman 
584a17663cSThomas Veerman static size_t name_pool_size;
594a17663cSThomas Veerman static char *name_pool;
604a17663cSThomas Veerman 
614a17663cSThomas Veerman char line_format[] = "#line %d \"%s\"\n";
624a17663cSThomas Veerman 
634a17663cSThomas Veerman param *lex_param;
644a17663cSThomas Veerman param *parse_param;
654a17663cSThomas Veerman 
66*0a6a1f1dSLionel Sambuc #if defined(YYBTYACC)
67*0a6a1f1dSLionel Sambuc int destructor = 0;	/* =1 if at least one %destructor */
68*0a6a1f1dSLionel Sambuc 
69*0a6a1f1dSLionel Sambuc static bucket *default_destructor[3] =
70*0a6a1f1dSLionel Sambuc {0, 0, 0};
71*0a6a1f1dSLionel Sambuc 
72*0a6a1f1dSLionel Sambuc #define UNTYPED_DEFAULT 0
73*0a6a1f1dSLionel Sambuc #define TYPED_DEFAULT   1
74*0a6a1f1dSLionel Sambuc #define TYPE_SPECIFIED  2
75*0a6a1f1dSLionel Sambuc 
76*0a6a1f1dSLionel Sambuc static bucket *
lookup_type_destructor(char * tag)77*0a6a1f1dSLionel Sambuc lookup_type_destructor(char *tag)
78*0a6a1f1dSLionel Sambuc {
79*0a6a1f1dSLionel Sambuc     const char fmt[] = "%.*s destructor";
80*0a6a1f1dSLionel Sambuc     char name[1024] = "\0";
81*0a6a1f1dSLionel Sambuc     bucket *bp, **bpp = &default_destructor[TYPE_SPECIFIED];
82*0a6a1f1dSLionel Sambuc 
83*0a6a1f1dSLionel Sambuc     while ((bp = *bpp) != NULL)
84*0a6a1f1dSLionel Sambuc     {
85*0a6a1f1dSLionel Sambuc 	if (bp->tag == tag)
86*0a6a1f1dSLionel Sambuc 	    return (bp);
87*0a6a1f1dSLionel Sambuc 	bpp = &bp->link;
88*0a6a1f1dSLionel Sambuc     }
89*0a6a1f1dSLionel Sambuc 
90*0a6a1f1dSLionel Sambuc     sprintf(name, fmt, (int)(sizeof(name) - sizeof(fmt)), tag);
91*0a6a1f1dSLionel Sambuc     *bpp = bp = make_bucket(name);
92*0a6a1f1dSLionel Sambuc     bp->tag = tag;
93*0a6a1f1dSLionel Sambuc 
94*0a6a1f1dSLionel Sambuc     return (bp);
95*0a6a1f1dSLionel Sambuc }
96*0a6a1f1dSLionel Sambuc #endif /* defined(YYBTYACC) */
97*0a6a1f1dSLionel Sambuc 
984a17663cSThomas Veerman static void
cachec(int c)994a17663cSThomas Veerman cachec(int c)
1004a17663cSThomas Veerman {
1014a17663cSThomas Veerman     assert(cinc >= 0);
1024a17663cSThomas Veerman     if (cinc >= cache_size)
1034a17663cSThomas Veerman     {
1044a17663cSThomas Veerman 	cache_size += 256;
10584d9c625SLionel Sambuc 	cache = TREALLOC(char, cache, cache_size);
1064a17663cSThomas Veerman 	NO_SPACE(cache);
1074a17663cSThomas Veerman     }
1084a17663cSThomas Veerman     cache[cinc] = (char)c;
1094a17663cSThomas Veerman     ++cinc;
1104a17663cSThomas Veerman }
1114a17663cSThomas Veerman 
1124a17663cSThomas Veerman static void
get_line(void)1134a17663cSThomas Veerman get_line(void)
1144a17663cSThomas Veerman {
1154a17663cSThomas Veerman     FILE *f = input_file;
1164a17663cSThomas Veerman     int c;
1174a17663cSThomas Veerman     int i;
1184a17663cSThomas Veerman 
1194a17663cSThomas Veerman     if (saw_eof || (c = getc(f)) == EOF)
1204a17663cSThomas Veerman     {
1214a17663cSThomas Veerman 	if (line)
1224a17663cSThomas Veerman 	{
1234a17663cSThomas Veerman 	    FREE(line);
1244a17663cSThomas Veerman 	    line = 0;
1254a17663cSThomas Veerman 	}
1264a17663cSThomas Veerman 	cptr = 0;
1274a17663cSThomas Veerman 	saw_eof = 1;
1284a17663cSThomas Veerman 	return;
1294a17663cSThomas Veerman     }
1304a17663cSThomas Veerman 
1314a17663cSThomas Veerman     if (line == 0 || linesize != (LINESIZE + 1))
1324a17663cSThomas Veerman     {
1334a17663cSThomas Veerman 	if (line)
1344a17663cSThomas Veerman 	    FREE(line);
1354a17663cSThomas Veerman 	linesize = LINESIZE + 1;
13684d9c625SLionel Sambuc 	line = TMALLOC(char, linesize);
1374a17663cSThomas Veerman 	NO_SPACE(line);
1384a17663cSThomas Veerman     }
1394a17663cSThomas Veerman 
1404a17663cSThomas Veerman     i = 0;
1414a17663cSThomas Veerman     ++lineno;
1424a17663cSThomas Veerman     for (;;)
1434a17663cSThomas Veerman     {
144*0a6a1f1dSLionel Sambuc 	line[i++] = (char)c;
1454a17663cSThomas Veerman 	if (c == '\n')
146*0a6a1f1dSLionel Sambuc 	    break;
147*0a6a1f1dSLionel Sambuc 	if ((i + 3) >= linesize)
1484a17663cSThomas Veerman 	{
1494a17663cSThomas Veerman 	    linesize += LINESIZE;
15084d9c625SLionel Sambuc 	    line = TREALLOC(char, line, linesize);
1514a17663cSThomas Veerman 	    NO_SPACE(line);
1524a17663cSThomas Veerman 	}
1534a17663cSThomas Veerman 	c = getc(f);
1544a17663cSThomas Veerman 	if (c == EOF)
1554a17663cSThomas Veerman 	{
156*0a6a1f1dSLionel Sambuc 	    line[i++] = '\n';
1574a17663cSThomas Veerman 	    saw_eof = 1;
158*0a6a1f1dSLionel Sambuc 	    break;
159*0a6a1f1dSLionel Sambuc 	}
160*0a6a1f1dSLionel Sambuc     }
161*0a6a1f1dSLionel Sambuc     line[i] = '\0';
1624a17663cSThomas Veerman     cptr = line;
1634a17663cSThomas Veerman     return;
1644a17663cSThomas Veerman }
1654a17663cSThomas Veerman 
1664a17663cSThomas Veerman static char *
dup_line(void)1674a17663cSThomas Veerman dup_line(void)
1684a17663cSThomas Veerman {
1694a17663cSThomas Veerman     char *p, *s, *t;
1704a17663cSThomas Veerman 
1714a17663cSThomas Veerman     if (line == 0)
1724a17663cSThomas Veerman 	return (0);
1734a17663cSThomas Veerman     s = line;
1744a17663cSThomas Veerman     while (*s != '\n')
1754a17663cSThomas Veerman 	++s;
17684d9c625SLionel Sambuc     p = TMALLOC(char, s - line + 1);
1774a17663cSThomas Veerman     NO_SPACE(p);
1784a17663cSThomas Veerman 
1794a17663cSThomas Veerman     s = line;
1804a17663cSThomas Veerman     t = p;
1814a17663cSThomas Veerman     while ((*t++ = *s++) != '\n')
1824a17663cSThomas Veerman 	continue;
1834a17663cSThomas Veerman     return (p);
1844a17663cSThomas Veerman }
1854a17663cSThomas Veerman 
1864a17663cSThomas Veerman static void
skip_comment(void)1874a17663cSThomas Veerman skip_comment(void)
1884a17663cSThomas Veerman {
1894a17663cSThomas Veerman     char *s;
190*0a6a1f1dSLionel Sambuc     struct ainfo a;
191*0a6a1f1dSLionel Sambuc     a.a_lineno = lineno;
192*0a6a1f1dSLionel Sambuc     a.a_line = dup_line();
193*0a6a1f1dSLionel Sambuc     a.a_cptr = a.a_line + (cptr - line);
1944a17663cSThomas Veerman 
1954a17663cSThomas Veerman     s = cptr + 2;
1964a17663cSThomas Veerman     for (;;)
1974a17663cSThomas Veerman     {
1984a17663cSThomas Veerman 	if (*s == '*' && s[1] == '/')
1994a17663cSThomas Veerman 	{
2004a17663cSThomas Veerman 	    cptr = s + 2;
201*0a6a1f1dSLionel Sambuc 	    FREE(a.a_line);
2024a17663cSThomas Veerman 	    return;
2034a17663cSThomas Veerman 	}
2044a17663cSThomas Veerman 	if (*s == '\n')
2054a17663cSThomas Veerman 	{
2064a17663cSThomas Veerman 	    get_line();
2074a17663cSThomas Veerman 	    if (line == 0)
208*0a6a1f1dSLionel Sambuc 		unterminated_comment(&a);
2094a17663cSThomas Veerman 	    s = cptr;
2104a17663cSThomas Veerman 	}
2114a17663cSThomas Veerman 	else
2124a17663cSThomas Veerman 	    ++s;
2134a17663cSThomas Veerman     }
2144a17663cSThomas Veerman }
2154a17663cSThomas Veerman 
2164a17663cSThomas Veerman static int
next_inline(void)217*0a6a1f1dSLionel Sambuc next_inline(void)
2184a17663cSThomas Veerman {
2194a17663cSThomas Veerman     char *s;
2204a17663cSThomas Veerman 
2214a17663cSThomas Veerman     if (line == 0)
2224a17663cSThomas Veerman     {
2234a17663cSThomas Veerman 	get_line();
2244a17663cSThomas Veerman 	if (line == 0)
2254a17663cSThomas Veerman 	    return (EOF);
2264a17663cSThomas Veerman     }
2274a17663cSThomas Veerman 
2284a17663cSThomas Veerman     s = cptr;
2294a17663cSThomas Veerman     for (;;)
2304a17663cSThomas Veerman     {
2314a17663cSThomas Veerman 	switch (*s)
2324a17663cSThomas Veerman 	{
2334a17663cSThomas Veerman 	case '/':
2344a17663cSThomas Veerman 	    if (s[1] == '*')
2354a17663cSThomas Veerman 	    {
2364a17663cSThomas Veerman 		cptr = s;
2374a17663cSThomas Veerman 		skip_comment();
2384a17663cSThomas Veerman 		s = cptr;
2394a17663cSThomas Veerman 		break;
2404a17663cSThomas Veerman 	    }
2414a17663cSThomas Veerman 	    else if (s[1] == '/')
2424a17663cSThomas Veerman 	    {
2434a17663cSThomas Veerman 		get_line();
2444a17663cSThomas Veerman 		if (line == 0)
2454a17663cSThomas Veerman 		    return (EOF);
2464a17663cSThomas Veerman 		s = cptr;
2474a17663cSThomas Veerman 		break;
2484a17663cSThomas Veerman 	    }
2494a17663cSThomas Veerman 	    /* FALLTHRU */
2504a17663cSThomas Veerman 
2514a17663cSThomas Veerman 	default:
2524a17663cSThomas Veerman 	    cptr = s;
2534a17663cSThomas Veerman 	    return (*s);
2544a17663cSThomas Veerman 	}
2554a17663cSThomas Veerman     }
2564a17663cSThomas Veerman }
2574a17663cSThomas Veerman 
2584a17663cSThomas Veerman static int
nextc(void)259*0a6a1f1dSLionel Sambuc nextc(void)
2604a17663cSThomas Veerman {
261*0a6a1f1dSLionel Sambuc     int ch;
262*0a6a1f1dSLionel Sambuc     int finish = 0;
2634a17663cSThomas Veerman 
264*0a6a1f1dSLionel Sambuc     do
2654a17663cSThomas Veerman     {
266*0a6a1f1dSLionel Sambuc 	switch (ch = next_inline())
267*0a6a1f1dSLionel Sambuc 	{
268*0a6a1f1dSLionel Sambuc 	case '\n':
269*0a6a1f1dSLionel Sambuc 	    get_line();
2704a17663cSThomas Veerman 	    break;
271*0a6a1f1dSLionel Sambuc 	case ' ':
272*0a6a1f1dSLionel Sambuc 	case '\t':
273*0a6a1f1dSLionel Sambuc 	case '\f':
274*0a6a1f1dSLionel Sambuc 	case '\r':
275*0a6a1f1dSLionel Sambuc 	case '\v':
276*0a6a1f1dSLionel Sambuc 	case ',':
277*0a6a1f1dSLionel Sambuc 	case ';':
278*0a6a1f1dSLionel Sambuc 	    ++cptr;
279*0a6a1f1dSLionel Sambuc 	    break;
280*0a6a1f1dSLionel Sambuc 	case '\\':
281*0a6a1f1dSLionel Sambuc 	    ch = '%';
282*0a6a1f1dSLionel Sambuc 	    /* FALLTHRU */
283*0a6a1f1dSLionel Sambuc 	default:
284*0a6a1f1dSLionel Sambuc 	    finish = 1;
2854a17663cSThomas Veerman 	    break;
2864a17663cSThomas Veerman 	}
2874a17663cSThomas Veerman     }
288*0a6a1f1dSLionel Sambuc     while (!finish);
289*0a6a1f1dSLionel Sambuc 
290*0a6a1f1dSLionel Sambuc     return ch;
291*0a6a1f1dSLionel Sambuc }
292*0a6a1f1dSLionel Sambuc /* *INDENT-OFF* */
293*0a6a1f1dSLionel Sambuc static struct keyword
294*0a6a1f1dSLionel Sambuc {
295*0a6a1f1dSLionel Sambuc     char name[14];
296*0a6a1f1dSLionel Sambuc     int token;
297*0a6a1f1dSLionel Sambuc }
298*0a6a1f1dSLionel Sambuc keywords[] = {
299*0a6a1f1dSLionel Sambuc     { "binary",      NONASSOC },
300*0a6a1f1dSLionel Sambuc     { "debug",	     XXXDEBUG },
301*0a6a1f1dSLionel Sambuc #if defined(YYBTYACC)
302*0a6a1f1dSLionel Sambuc     { "destructor",  DESTRUCTOR },
303*0a6a1f1dSLionel Sambuc #endif
304*0a6a1f1dSLionel Sambuc     { "error-verbose",ERROR_VERBOSE },
305*0a6a1f1dSLionel Sambuc     { "expect",      EXPECT },
306*0a6a1f1dSLionel Sambuc     { "expect-rr",   EXPECT_RR },
307*0a6a1f1dSLionel Sambuc     { "ident",       IDENT },
308*0a6a1f1dSLionel Sambuc #if defined(YYBTYACC)
309*0a6a1f1dSLionel Sambuc     { "initial-action", INITIAL_ACTION },
310*0a6a1f1dSLionel Sambuc #endif
311*0a6a1f1dSLionel Sambuc     { "left",        LEFT },
312*0a6a1f1dSLionel Sambuc     { "lex-param",   LEX_PARAM },
313*0a6a1f1dSLionel Sambuc #if defined(YYBTYACC)
314*0a6a1f1dSLionel Sambuc     { "locations",   LOCATIONS },
315*0a6a1f1dSLionel Sambuc #endif
316*0a6a1f1dSLionel Sambuc     { "nonassoc",    NONASSOC },
317*0a6a1f1dSLionel Sambuc     { "parse-param", PARSE_PARAM },
318*0a6a1f1dSLionel Sambuc     { "pure-parser", PURE_PARSER },
319*0a6a1f1dSLionel Sambuc     { "right",       RIGHT },
320*0a6a1f1dSLionel Sambuc     { "start",       START },
321*0a6a1f1dSLionel Sambuc     { "term",        TOKEN },
322*0a6a1f1dSLionel Sambuc     { "token",       TOKEN },
323*0a6a1f1dSLionel Sambuc     { "token-table", TOKEN_TABLE },
324*0a6a1f1dSLionel Sambuc     { "type",        TYPE },
325*0a6a1f1dSLionel Sambuc     { "union",       UNION },
326*0a6a1f1dSLionel Sambuc     { "yacc",        POSIX_YACC },
327*0a6a1f1dSLionel Sambuc };
328*0a6a1f1dSLionel Sambuc /* *INDENT-ON* */
329*0a6a1f1dSLionel Sambuc 
330*0a6a1f1dSLionel Sambuc static int
compare_keys(const void * a,const void * b)331*0a6a1f1dSLionel Sambuc compare_keys(const void *a, const void *b)
332*0a6a1f1dSLionel Sambuc {
333*0a6a1f1dSLionel Sambuc     const struct keyword *p = (const struct keyword *)a;
334*0a6a1f1dSLionel Sambuc     const struct keyword *q = (const struct keyword *)b;
335*0a6a1f1dSLionel Sambuc     return strcmp(p->name, q->name);
3364a17663cSThomas Veerman }
3374a17663cSThomas Veerman 
3384a17663cSThomas Veerman static int
keyword(void)3394a17663cSThomas Veerman keyword(void)
3404a17663cSThomas Veerman {
3414a17663cSThomas Veerman     int c;
3424a17663cSThomas Veerman     char *t_cptr = cptr;
343*0a6a1f1dSLionel Sambuc     struct keyword *key;
3444a17663cSThomas Veerman 
3454a17663cSThomas Veerman     c = *++cptr;
3464a17663cSThomas Veerman     if (isalpha(c))
3474a17663cSThomas Veerman     {
3484a17663cSThomas Veerman 	cinc = 0;
3494a17663cSThomas Veerman 	for (;;)
3504a17663cSThomas Veerman 	{
3514a17663cSThomas Veerman 	    if (isalpha(c))
3524a17663cSThomas Veerman 	    {
3534a17663cSThomas Veerman 		if (isupper(c))
3544a17663cSThomas Veerman 		    c = tolower(c);
3554a17663cSThomas Veerman 		cachec(c);
3564a17663cSThomas Veerman 	    }
3574a17663cSThomas Veerman 	    else if (isdigit(c)
3584a17663cSThomas Veerman 		     || c == '-'
3594a17663cSThomas Veerman 		     || c == '.'
3604a17663cSThomas Veerman 		     || c == '$')
3614a17663cSThomas Veerman 	    {
3624a17663cSThomas Veerman 		cachec(c);
3634a17663cSThomas Veerman 	    }
364*0a6a1f1dSLionel Sambuc 	    else if (c == '_')
365*0a6a1f1dSLionel Sambuc 	    {
366*0a6a1f1dSLionel Sambuc 		/* treat keywords spelled with '_' as if it were '-' */
367*0a6a1f1dSLionel Sambuc 		cachec('-');
368*0a6a1f1dSLionel Sambuc 	    }
3694a17663cSThomas Veerman 	    else
3704a17663cSThomas Veerman 	    {
3714a17663cSThomas Veerman 		break;
3724a17663cSThomas Veerman 	    }
3734a17663cSThomas Veerman 	    c = *++cptr;
3744a17663cSThomas Veerman 	}
3754a17663cSThomas Veerman 	cachec(NUL);
3764a17663cSThomas Veerman 
377*0a6a1f1dSLionel Sambuc 	if ((key = bsearch(cache, keywords,
378*0a6a1f1dSLionel Sambuc 			   sizeof(keywords) / sizeof(*key),
379*0a6a1f1dSLionel Sambuc 			   sizeof(*key), compare_keys)))
380*0a6a1f1dSLionel Sambuc 	    return key->token;
3814a17663cSThomas Veerman     }
3824a17663cSThomas Veerman     else
3834a17663cSThomas Veerman     {
3844a17663cSThomas Veerman 	++cptr;
3854a17663cSThomas Veerman 	if (c == L_CURL)
3864a17663cSThomas Veerman 	    return (TEXT);
3874a17663cSThomas Veerman 	if (c == '%' || c == '\\')
3884a17663cSThomas Veerman 	    return (MARK);
3894a17663cSThomas Veerman 	if (c == '<')
3904a17663cSThomas Veerman 	    return (LEFT);
3914a17663cSThomas Veerman 	if (c == '>')
3924a17663cSThomas Veerman 	    return (RIGHT);
3934a17663cSThomas Veerman 	if (c == '0')
3944a17663cSThomas Veerman 	    return (TOKEN);
3954a17663cSThomas Veerman 	if (c == '2')
3964a17663cSThomas Veerman 	    return (NONASSOC);
3974a17663cSThomas Veerman     }
3984a17663cSThomas Veerman     syntax_error(lineno, line, t_cptr);
3994a17663cSThomas Veerman }
4004a17663cSThomas Veerman 
4014a17663cSThomas Veerman 
4024a17663cSThomas Veerman static void
copy_ident(void)4034a17663cSThomas Veerman copy_ident(void)
4044a17663cSThomas Veerman {
4054a17663cSThomas Veerman     int c;
4064a17663cSThomas Veerman     FILE *f = output_file;
4074a17663cSThomas Veerman 
4084a17663cSThomas Veerman     c = nextc();
4094a17663cSThomas Veerman     if (c == EOF)
4104a17663cSThomas Veerman 	unexpected_EOF();
4114a17663cSThomas Veerman     if (c != '"')
4124a17663cSThomas Veerman 	syntax_error(lineno, line, cptr);
4134a17663cSThomas Veerman     ++outline;
4144a17663cSThomas Veerman     fprintf(f, "#ident \"");
4154a17663cSThomas Veerman     for (;;)
4164a17663cSThomas Veerman     {
4174a17663cSThomas Veerman 	c = *++cptr;
4184a17663cSThomas Veerman 	if (c == '\n')
4194a17663cSThomas Veerman 	{
4204a17663cSThomas Veerman 	    fprintf(f, "\"\n");
4214a17663cSThomas Veerman 	    return;
4224a17663cSThomas Veerman 	}
4234a17663cSThomas Veerman 	putc(c, f);
4244a17663cSThomas Veerman 	if (c == '"')
4254a17663cSThomas Veerman 	{
4264a17663cSThomas Veerman 	    putc('\n', f);
4274a17663cSThomas Veerman 	    ++cptr;
4284a17663cSThomas Veerman 	    return;
4294a17663cSThomas Veerman 	}
4304a17663cSThomas Veerman     }
4314a17663cSThomas Veerman }
4324a17663cSThomas Veerman 
433*0a6a1f1dSLionel Sambuc static char *
copy_string(int quote)434*0a6a1f1dSLionel Sambuc copy_string(int quote)
435*0a6a1f1dSLionel Sambuc {
436*0a6a1f1dSLionel Sambuc     struct mstring *temp = msnew();
437*0a6a1f1dSLionel Sambuc     int c;
438*0a6a1f1dSLionel Sambuc     struct ainfo a;
439*0a6a1f1dSLionel Sambuc     a.a_lineno = lineno;
440*0a6a1f1dSLionel Sambuc     a.a_line = dup_line();
441*0a6a1f1dSLionel Sambuc     a.a_cptr = a.a_line + (cptr - line - 1);
442*0a6a1f1dSLionel Sambuc 
443*0a6a1f1dSLionel Sambuc     for (;;)
444*0a6a1f1dSLionel Sambuc     {
445*0a6a1f1dSLionel Sambuc 	c = *cptr++;
446*0a6a1f1dSLionel Sambuc 	mputc(temp, c);
447*0a6a1f1dSLionel Sambuc 	if (c == quote)
448*0a6a1f1dSLionel Sambuc 	{
449*0a6a1f1dSLionel Sambuc 	    FREE(a.a_line);
450*0a6a1f1dSLionel Sambuc 	    return msdone(temp);
451*0a6a1f1dSLionel Sambuc 	}
452*0a6a1f1dSLionel Sambuc 	if (c == '\n')
453*0a6a1f1dSLionel Sambuc 	    unterminated_string(&a);
454*0a6a1f1dSLionel Sambuc 	if (c == '\\')
455*0a6a1f1dSLionel Sambuc 	{
456*0a6a1f1dSLionel Sambuc 	    c = *cptr++;
457*0a6a1f1dSLionel Sambuc 	    mputc(temp, c);
458*0a6a1f1dSLionel Sambuc 	    if (c == '\n')
459*0a6a1f1dSLionel Sambuc 	    {
460*0a6a1f1dSLionel Sambuc 		get_line();
461*0a6a1f1dSLionel Sambuc 		if (line == 0)
462*0a6a1f1dSLionel Sambuc 		    unterminated_string(&a);
463*0a6a1f1dSLionel Sambuc 	    }
464*0a6a1f1dSLionel Sambuc 	}
465*0a6a1f1dSLionel Sambuc     }
466*0a6a1f1dSLionel Sambuc }
467*0a6a1f1dSLionel Sambuc 
468*0a6a1f1dSLionel Sambuc static char *
copy_comment(void)469*0a6a1f1dSLionel Sambuc copy_comment(void)
470*0a6a1f1dSLionel Sambuc {
471*0a6a1f1dSLionel Sambuc     struct mstring *temp = msnew();
472*0a6a1f1dSLionel Sambuc     int c;
473*0a6a1f1dSLionel Sambuc 
474*0a6a1f1dSLionel Sambuc     c = *cptr;
475*0a6a1f1dSLionel Sambuc     if (c == '/')
476*0a6a1f1dSLionel Sambuc     {
477*0a6a1f1dSLionel Sambuc 	mputc(temp, '*');
478*0a6a1f1dSLionel Sambuc 	while ((c = *++cptr) != '\n')
479*0a6a1f1dSLionel Sambuc 	{
480*0a6a1f1dSLionel Sambuc 	    mputc(temp, c);
481*0a6a1f1dSLionel Sambuc 	    if (c == '*' && cptr[1] == '/')
482*0a6a1f1dSLionel Sambuc 		mputc(temp, ' ');
483*0a6a1f1dSLionel Sambuc 	}
484*0a6a1f1dSLionel Sambuc 	mputc(temp, '*');
485*0a6a1f1dSLionel Sambuc 	mputc(temp, '/');
486*0a6a1f1dSLionel Sambuc     }
487*0a6a1f1dSLionel Sambuc     else if (c == '*')
488*0a6a1f1dSLionel Sambuc     {
489*0a6a1f1dSLionel Sambuc 	struct ainfo a;
490*0a6a1f1dSLionel Sambuc 	a.a_lineno = lineno;
491*0a6a1f1dSLionel Sambuc 	a.a_line = dup_line();
492*0a6a1f1dSLionel Sambuc 	a.a_cptr = a.a_line + (cptr - line - 1);
493*0a6a1f1dSLionel Sambuc 
494*0a6a1f1dSLionel Sambuc 	mputc(temp, c);
495*0a6a1f1dSLionel Sambuc 	++cptr;
496*0a6a1f1dSLionel Sambuc 	for (;;)
497*0a6a1f1dSLionel Sambuc 	{
498*0a6a1f1dSLionel Sambuc 	    c = *cptr++;
499*0a6a1f1dSLionel Sambuc 	    mputc(temp, c);
500*0a6a1f1dSLionel Sambuc 	    if (c == '*' && *cptr == '/')
501*0a6a1f1dSLionel Sambuc 	    {
502*0a6a1f1dSLionel Sambuc 		mputc(temp, '/');
503*0a6a1f1dSLionel Sambuc 		++cptr;
504*0a6a1f1dSLionel Sambuc 		FREE(a.a_line);
505*0a6a1f1dSLionel Sambuc 		return msdone(temp);
506*0a6a1f1dSLionel Sambuc 	    }
507*0a6a1f1dSLionel Sambuc 	    if (c == '\n')
508*0a6a1f1dSLionel Sambuc 	    {
509*0a6a1f1dSLionel Sambuc 		get_line();
510*0a6a1f1dSLionel Sambuc 		if (line == 0)
511*0a6a1f1dSLionel Sambuc 		    unterminated_comment(&a);
512*0a6a1f1dSLionel Sambuc 	    }
513*0a6a1f1dSLionel Sambuc 	}
514*0a6a1f1dSLionel Sambuc     }
515*0a6a1f1dSLionel Sambuc     return msdone(temp);
516*0a6a1f1dSLionel Sambuc }
517*0a6a1f1dSLionel Sambuc 
5184a17663cSThomas Veerman static void
copy_text(void)5194a17663cSThomas Veerman copy_text(void)
5204a17663cSThomas Veerman {
5214a17663cSThomas Veerman     int c;
5224a17663cSThomas Veerman     FILE *f = text_file;
5234a17663cSThomas Veerman     int need_newline = 0;
524*0a6a1f1dSLionel Sambuc     struct ainfo a;
525*0a6a1f1dSLionel Sambuc     a.a_lineno = lineno;
526*0a6a1f1dSLionel Sambuc     a.a_line = dup_line();
527*0a6a1f1dSLionel Sambuc     a.a_cptr = a.a_line + (cptr - line - 2);
5284a17663cSThomas Veerman 
5294a17663cSThomas Veerman     if (*cptr == '\n')
5304a17663cSThomas Veerman     {
5314a17663cSThomas Veerman 	get_line();
5324a17663cSThomas Veerman 	if (line == 0)
533*0a6a1f1dSLionel Sambuc 	    unterminated_text(&a);
5344a17663cSThomas Veerman     }
5354a17663cSThomas Veerman     if (!lflag)
5364a17663cSThomas Veerman 	fprintf(f, line_format, lineno, input_file_name);
5374a17663cSThomas Veerman 
5384a17663cSThomas Veerman   loop:
5394a17663cSThomas Veerman     c = *cptr++;
5404a17663cSThomas Veerman     switch (c)
5414a17663cSThomas Veerman     {
5424a17663cSThomas Veerman     case '\n':
5434a17663cSThomas Veerman 	putc('\n', f);
5444a17663cSThomas Veerman 	need_newline = 0;
5454a17663cSThomas Veerman 	get_line();
5464a17663cSThomas Veerman 	if (line)
5474a17663cSThomas Veerman 	    goto loop;
548*0a6a1f1dSLionel Sambuc 	unterminated_text(&a);
5494a17663cSThomas Veerman 
5504a17663cSThomas Veerman     case '\'':
5514a17663cSThomas Veerman     case '"':
5524a17663cSThomas Veerman 	putc(c, f);
5534a17663cSThomas Veerman 	{
554*0a6a1f1dSLionel Sambuc 	    char *s = copy_string(c);
555*0a6a1f1dSLionel Sambuc 	    fputs(s, f);
556*0a6a1f1dSLionel Sambuc 	    free(s);
557*0a6a1f1dSLionel Sambuc 	}
5584a17663cSThomas Veerman 	need_newline = 1;
5594a17663cSThomas Veerman 	goto loop;
5604a17663cSThomas Veerman 
5614a17663cSThomas Veerman     case '/':
5624a17663cSThomas Veerman 	putc(c, f);
5634a17663cSThomas Veerman 	{
564*0a6a1f1dSLionel Sambuc 	    char *s = copy_comment();
565*0a6a1f1dSLionel Sambuc 	    fputs(s, f);
566*0a6a1f1dSLionel Sambuc 	    free(s);
5674a17663cSThomas Veerman 	}
5684a17663cSThomas Veerman 	need_newline = 1;
5694a17663cSThomas Veerman 	goto loop;
5704a17663cSThomas Veerman 
5714a17663cSThomas Veerman     case '%':
5724a17663cSThomas Veerman     case '\\':
5734a17663cSThomas Veerman 	if (*cptr == R_CURL)
5744a17663cSThomas Veerman 	{
5754a17663cSThomas Veerman 	    if (need_newline)
5764a17663cSThomas Veerman 		putc('\n', f);
5774a17663cSThomas Veerman 	    ++cptr;
578*0a6a1f1dSLionel Sambuc 	    FREE(a.a_line);
5794a17663cSThomas Veerman 	    return;
5804a17663cSThomas Veerman 	}
5814a17663cSThomas Veerman 	/* FALLTHRU */
5824a17663cSThomas Veerman 
5834a17663cSThomas Veerman     default:
5844a17663cSThomas Veerman 	putc(c, f);
5854a17663cSThomas Veerman 	need_newline = 1;
5864a17663cSThomas Veerman 	goto loop;
5874a17663cSThomas Veerman     }
5884a17663cSThomas Veerman }
5894a17663cSThomas Veerman 
5904a17663cSThomas Veerman static void
puts_both(const char * s)5914a17663cSThomas Veerman puts_both(const char *s)
5924a17663cSThomas Veerman {
5934a17663cSThomas Veerman     fputs(s, text_file);
5944a17663cSThomas Veerman     if (dflag)
5954a17663cSThomas Veerman 	fputs(s, union_file);
5964a17663cSThomas Veerman }
5974a17663cSThomas Veerman 
5984a17663cSThomas Veerman static void
putc_both(int c)5994a17663cSThomas Veerman putc_both(int c)
6004a17663cSThomas Veerman {
6014a17663cSThomas Veerman     putc(c, text_file);
6024a17663cSThomas Veerman     if (dflag)
6034a17663cSThomas Veerman 	putc(c, union_file);
6044a17663cSThomas Veerman }
6054a17663cSThomas Veerman 
6064a17663cSThomas Veerman static void
copy_union(void)6074a17663cSThomas Veerman copy_union(void)
6084a17663cSThomas Veerman {
6094a17663cSThomas Veerman     int c;
6104a17663cSThomas Veerman     int depth;
611*0a6a1f1dSLionel Sambuc     struct ainfo a;
612*0a6a1f1dSLionel Sambuc     a.a_lineno = lineno;
613*0a6a1f1dSLionel Sambuc     a.a_line = dup_line();
614*0a6a1f1dSLionel Sambuc     a.a_cptr = a.a_line + (cptr - line - 6);
6154a17663cSThomas Veerman 
6164a17663cSThomas Veerman     if (unionized)
6174a17663cSThomas Veerman 	over_unionized(cptr - 6);
6184a17663cSThomas Veerman     unionized = 1;
6194a17663cSThomas Veerman 
6204a17663cSThomas Veerman     if (!lflag)
6214a17663cSThomas Veerman 	fprintf(text_file, line_format, lineno, input_file_name);
6224a17663cSThomas Veerman 
6234a17663cSThomas Veerman     puts_both("#ifdef YYSTYPE\n");
6244a17663cSThomas Veerman     puts_both("#undef  YYSTYPE_IS_DECLARED\n");
6254a17663cSThomas Veerman     puts_both("#define YYSTYPE_IS_DECLARED 1\n");
6264a17663cSThomas Veerman     puts_both("#endif\n");
6274a17663cSThomas Veerman     puts_both("#ifndef YYSTYPE_IS_DECLARED\n");
6284a17663cSThomas Veerman     puts_both("#define YYSTYPE_IS_DECLARED 1\n");
6294a17663cSThomas Veerman     puts_both("typedef union");
6304a17663cSThomas Veerman 
6314a17663cSThomas Veerman     depth = 0;
6324a17663cSThomas Veerman   loop:
6334a17663cSThomas Veerman     c = *cptr++;
6344a17663cSThomas Veerman     putc_both(c);
6354a17663cSThomas Veerman     switch (c)
6364a17663cSThomas Veerman     {
6374a17663cSThomas Veerman     case '\n':
6384a17663cSThomas Veerman 	get_line();
6394a17663cSThomas Veerman 	if (line == 0)
640*0a6a1f1dSLionel Sambuc 	    unterminated_union(&a);
6414a17663cSThomas Veerman 	goto loop;
6424a17663cSThomas Veerman 
6434a17663cSThomas Veerman     case L_CURL:
6444a17663cSThomas Veerman 	++depth;
6454a17663cSThomas Veerman 	goto loop;
6464a17663cSThomas Veerman 
6474a17663cSThomas Veerman     case R_CURL:
6484a17663cSThomas Veerman 	if (--depth == 0)
6494a17663cSThomas Veerman 	{
6504a17663cSThomas Veerman 	    puts_both(" YYSTYPE;\n");
6514a17663cSThomas Veerman 	    puts_both("#endif /* !YYSTYPE_IS_DECLARED */\n");
652*0a6a1f1dSLionel Sambuc 	    FREE(a.a_line);
6534a17663cSThomas Veerman 	    return;
6544a17663cSThomas Veerman 	}
6554a17663cSThomas Veerman 	goto loop;
6564a17663cSThomas Veerman 
6574a17663cSThomas Veerman     case '\'':
6584a17663cSThomas Veerman     case '"':
6594a17663cSThomas Veerman 	{
660*0a6a1f1dSLionel Sambuc 	    char *s = copy_string(c);
661*0a6a1f1dSLionel Sambuc 	    puts_both(s);
662*0a6a1f1dSLionel Sambuc 	    free(s);
663*0a6a1f1dSLionel Sambuc 	}
6644a17663cSThomas Veerman 	goto loop;
6654a17663cSThomas Veerman 
6664a17663cSThomas Veerman     case '/':
6674a17663cSThomas Veerman 	{
668*0a6a1f1dSLionel Sambuc 	    char *s = copy_comment();
669*0a6a1f1dSLionel Sambuc 	    puts_both(s);
670*0a6a1f1dSLionel Sambuc 	    free(s);
6714a17663cSThomas Veerman 	}
6724a17663cSThomas Veerman 	goto loop;
6734a17663cSThomas Veerman 
6744a17663cSThomas Veerman     default:
6754a17663cSThomas Veerman 	goto loop;
6764a17663cSThomas Veerman     }
6774a17663cSThomas Veerman }
6784a17663cSThomas Veerman 
679*0a6a1f1dSLionel Sambuc static char *
after_blanks(char * s)680*0a6a1f1dSLionel Sambuc after_blanks(char *s)
681*0a6a1f1dSLionel Sambuc {
682*0a6a1f1dSLionel Sambuc     while (*s != '\0' && isspace(UCH(*s)))
683*0a6a1f1dSLionel Sambuc 	++s;
684*0a6a1f1dSLionel Sambuc     return s;
685*0a6a1f1dSLionel Sambuc }
686*0a6a1f1dSLionel Sambuc 
6874a17663cSThomas Veerman /*
688*0a6a1f1dSLionel Sambuc  * Trim leading/trailing blanks, and collapse multiple embedded blanks to a
689*0a6a1f1dSLionel Sambuc  * single space.  Return index to last character in the buffer.
6904a17663cSThomas Veerman  */
691*0a6a1f1dSLionel Sambuc static int
trim_blanks(char * buffer)692*0a6a1f1dSLionel Sambuc trim_blanks(char *buffer)
693*0a6a1f1dSLionel Sambuc {
694*0a6a1f1dSLionel Sambuc     if (*buffer != '\0')
695*0a6a1f1dSLionel Sambuc     {
696*0a6a1f1dSLionel Sambuc 	char *d = buffer;
697*0a6a1f1dSLionel Sambuc 	char *s = after_blanks(d);
698*0a6a1f1dSLionel Sambuc 
699*0a6a1f1dSLionel Sambuc 	while ((*d++ = *s++) != '\0')
700*0a6a1f1dSLionel Sambuc 	{
701*0a6a1f1dSLionel Sambuc 	    ;
702*0a6a1f1dSLionel Sambuc 	}
703*0a6a1f1dSLionel Sambuc 
704*0a6a1f1dSLionel Sambuc 	--d;
705*0a6a1f1dSLionel Sambuc 	while ((--d != buffer) && isspace(UCH(*d)))
706*0a6a1f1dSLionel Sambuc 	    *d = '\0';
707*0a6a1f1dSLionel Sambuc 
708*0a6a1f1dSLionel Sambuc 	for (s = d = buffer; (*d++ = *s++) != '\0';)
709*0a6a1f1dSLionel Sambuc 	{
710*0a6a1f1dSLionel Sambuc 	    if (isspace(UCH(*s)))
711*0a6a1f1dSLionel Sambuc 	    {
712*0a6a1f1dSLionel Sambuc 		*s = ' ';
713*0a6a1f1dSLionel Sambuc 		while (isspace(UCH(*s)))
714*0a6a1f1dSLionel Sambuc 		{
715*0a6a1f1dSLionel Sambuc 		    *s++ = ' ';
716*0a6a1f1dSLionel Sambuc 		}
717*0a6a1f1dSLionel Sambuc 		--s;
718*0a6a1f1dSLionel Sambuc 	    }
719*0a6a1f1dSLionel Sambuc 	}
720*0a6a1f1dSLionel Sambuc     }
721*0a6a1f1dSLionel Sambuc 
722*0a6a1f1dSLionel Sambuc     return (int)strlen(buffer) - 1;
723*0a6a1f1dSLionel Sambuc }
724*0a6a1f1dSLionel Sambuc 
725*0a6a1f1dSLionel Sambuc /*
726*0a6a1f1dSLionel Sambuc  * Scan forward in the current line-buffer looking for a right-curly bracket.
727*0a6a1f1dSLionel Sambuc  *
728*0a6a1f1dSLionel Sambuc  * Parameters begin with a left-curly bracket, and continue until there are no
729*0a6a1f1dSLionel Sambuc  * more interesting characters after the last right-curly bracket on the
730*0a6a1f1dSLionel Sambuc  * current line.  Bison documents parameters as separated like this:
731*0a6a1f1dSLionel Sambuc  *	{type param1} {type2 param2}
732*0a6a1f1dSLionel Sambuc  * but also accepts commas (although some versions of bison mishandle this)
733*0a6a1f1dSLionel Sambuc  *	{type param1,  type2 param2}
734*0a6a1f1dSLionel Sambuc  */
735*0a6a1f1dSLionel Sambuc static int
more_curly(void)736*0a6a1f1dSLionel Sambuc more_curly(void)
737*0a6a1f1dSLionel Sambuc {
738*0a6a1f1dSLionel Sambuc     char *save = cptr;
739*0a6a1f1dSLionel Sambuc     int result = 0;
740*0a6a1f1dSLionel Sambuc     int finish = 0;
741*0a6a1f1dSLionel Sambuc     do
742*0a6a1f1dSLionel Sambuc     {
743*0a6a1f1dSLionel Sambuc 	switch (next_inline())
744*0a6a1f1dSLionel Sambuc 	{
745*0a6a1f1dSLionel Sambuc 	case 0:
746*0a6a1f1dSLionel Sambuc 	case '\n':
747*0a6a1f1dSLionel Sambuc 	    finish = 1;
748*0a6a1f1dSLionel Sambuc 	    break;
749*0a6a1f1dSLionel Sambuc 	case R_CURL:
750*0a6a1f1dSLionel Sambuc 	    finish = 1;
751*0a6a1f1dSLionel Sambuc 	    result = 1;
752*0a6a1f1dSLionel Sambuc 	    break;
753*0a6a1f1dSLionel Sambuc 	}
754*0a6a1f1dSLionel Sambuc 	++cptr;
755*0a6a1f1dSLionel Sambuc     }
756*0a6a1f1dSLionel Sambuc     while (!finish);
757*0a6a1f1dSLionel Sambuc     cptr = save;
758*0a6a1f1dSLionel Sambuc     return result;
759*0a6a1f1dSLionel Sambuc }
760*0a6a1f1dSLionel Sambuc 
7614a17663cSThomas Veerman static void
save_param(int k,char * buffer,int name,int type2)762*0a6a1f1dSLionel Sambuc save_param(int k, char *buffer, int name, int type2)
7634a17663cSThomas Veerman {
7644a17663cSThomas Veerman     param *head, *p;
7654a17663cSThomas Veerman 
76684d9c625SLionel Sambuc     p = TMALLOC(param, 1);
7674a17663cSThomas Veerman     NO_SPACE(p);
7684a17663cSThomas Veerman 
769*0a6a1f1dSLionel Sambuc     p->type2 = strdup(buffer + type2);
7704a17663cSThomas Veerman     NO_SPACE(p->type2);
771*0a6a1f1dSLionel Sambuc     buffer[type2] = '\0';
772*0a6a1f1dSLionel Sambuc     (void)trim_blanks(p->type2);
7734a17663cSThomas Veerman 
774*0a6a1f1dSLionel Sambuc     p->name = strdup(buffer + name);
7754a17663cSThomas Veerman     NO_SPACE(p->name);
776*0a6a1f1dSLionel Sambuc     buffer[name] = '\0';
777*0a6a1f1dSLionel Sambuc     (void)trim_blanks(p->name);
7784a17663cSThomas Veerman 
779*0a6a1f1dSLionel Sambuc     p->type = strdup(buffer);
780*0a6a1f1dSLionel Sambuc     NO_SPACE(p->type);
781*0a6a1f1dSLionel Sambuc     (void)trim_blanks(p->type);
7824a17663cSThomas Veerman 
7834a17663cSThomas Veerman     if (k == LEX_PARAM)
7844a17663cSThomas Veerman 	head = lex_param;
7854a17663cSThomas Veerman     else
7864a17663cSThomas Veerman 	head = parse_param;
7874a17663cSThomas Veerman 
7884a17663cSThomas Veerman     if (head != NULL)
7894a17663cSThomas Veerman     {
7904a17663cSThomas Veerman 	while (head->next)
7914a17663cSThomas Veerman 	    head = head->next;
7924a17663cSThomas Veerman 	head->next = p;
7934a17663cSThomas Veerman     }
7944a17663cSThomas Veerman     else
7954a17663cSThomas Veerman     {
7964a17663cSThomas Veerman 	if (k == LEX_PARAM)
7974a17663cSThomas Veerman 	    lex_param = p;
7984a17663cSThomas Veerman 	else
7994a17663cSThomas Veerman 	    parse_param = p;
8004a17663cSThomas Veerman     }
8014a17663cSThomas Veerman     p->next = NULL;
802*0a6a1f1dSLionel Sambuc }
803*0a6a1f1dSLionel Sambuc 
804*0a6a1f1dSLionel Sambuc /*
805*0a6a1f1dSLionel Sambuc  * Keep a linked list of parameters.  This may be multi-line, if the trailing
806*0a6a1f1dSLionel Sambuc  * right-curly bracket is absent.
807*0a6a1f1dSLionel Sambuc  */
808*0a6a1f1dSLionel Sambuc static void
copy_param(int k)809*0a6a1f1dSLionel Sambuc copy_param(int k)
810*0a6a1f1dSLionel Sambuc {
811*0a6a1f1dSLionel Sambuc     int c;
812*0a6a1f1dSLionel Sambuc     int name, type2;
813*0a6a1f1dSLionel Sambuc     int curly = 0;
814*0a6a1f1dSLionel Sambuc     char *buf = 0;
815*0a6a1f1dSLionel Sambuc     int i = -1;
816*0a6a1f1dSLionel Sambuc     size_t buf_size = 0;
817*0a6a1f1dSLionel Sambuc     int st_lineno = lineno;
818*0a6a1f1dSLionel Sambuc     char *comma;
819*0a6a1f1dSLionel Sambuc 
820*0a6a1f1dSLionel Sambuc     do
821*0a6a1f1dSLionel Sambuc     {
822*0a6a1f1dSLionel Sambuc 	int state = curly;
823*0a6a1f1dSLionel Sambuc 	c = next_inline();
824*0a6a1f1dSLionel Sambuc 	switch (c)
825*0a6a1f1dSLionel Sambuc 	{
826*0a6a1f1dSLionel Sambuc 	case EOF:
827*0a6a1f1dSLionel Sambuc 	    unexpected_EOF();
828*0a6a1f1dSLionel Sambuc 	    break;
829*0a6a1f1dSLionel Sambuc 	case L_CURL:
830*0a6a1f1dSLionel Sambuc 	    if (curly == 1)
831*0a6a1f1dSLionel Sambuc 	    {
832*0a6a1f1dSLionel Sambuc 		goto oops;
833*0a6a1f1dSLionel Sambuc 	    }
834*0a6a1f1dSLionel Sambuc 	    curly = 1;
835*0a6a1f1dSLionel Sambuc 	    st_lineno = lineno;
836*0a6a1f1dSLionel Sambuc 	    break;
837*0a6a1f1dSLionel Sambuc 	case R_CURL:
838*0a6a1f1dSLionel Sambuc 	    if (curly != 1)
839*0a6a1f1dSLionel Sambuc 	    {
840*0a6a1f1dSLionel Sambuc 		goto oops;
841*0a6a1f1dSLionel Sambuc 	    }
842*0a6a1f1dSLionel Sambuc 	    curly = 2;
843*0a6a1f1dSLionel Sambuc 	    break;
844*0a6a1f1dSLionel Sambuc 	case '\n':
845*0a6a1f1dSLionel Sambuc 	    if (curly == 0)
846*0a6a1f1dSLionel Sambuc 	    {
847*0a6a1f1dSLionel Sambuc 		goto oops;
848*0a6a1f1dSLionel Sambuc 	    }
849*0a6a1f1dSLionel Sambuc 	    break;
850*0a6a1f1dSLionel Sambuc 	case '%':
851*0a6a1f1dSLionel Sambuc 	    if ((curly == 1) && (cptr == line))
852*0a6a1f1dSLionel Sambuc 	    {
853*0a6a1f1dSLionel Sambuc 		lineno = st_lineno;
854*0a6a1f1dSLionel Sambuc 		missing_brace();
855*0a6a1f1dSLionel Sambuc 	    }
856*0a6a1f1dSLionel Sambuc 	    /* FALLTHRU */
857*0a6a1f1dSLionel Sambuc 	case '"':
858*0a6a1f1dSLionel Sambuc 	case '\'':
859*0a6a1f1dSLionel Sambuc 	    goto oops;
860*0a6a1f1dSLionel Sambuc 	default:
861*0a6a1f1dSLionel Sambuc 	    if (curly == 0 && !isspace(UCH(c)))
862*0a6a1f1dSLionel Sambuc 	    {
863*0a6a1f1dSLionel Sambuc 		goto oops;
864*0a6a1f1dSLionel Sambuc 	    }
865*0a6a1f1dSLionel Sambuc 	    break;
866*0a6a1f1dSLionel Sambuc 	}
867*0a6a1f1dSLionel Sambuc 	if (buf == 0)
868*0a6a1f1dSLionel Sambuc 	{
869*0a6a1f1dSLionel Sambuc 	    buf_size = (size_t) linesize;
870*0a6a1f1dSLionel Sambuc 	    buf = TMALLOC(char, buf_size);
871*0a6a1f1dSLionel Sambuc 	}
872*0a6a1f1dSLionel Sambuc 	else if (c == '\n')
873*0a6a1f1dSLionel Sambuc 	{
874*0a6a1f1dSLionel Sambuc 	    get_line();
875*0a6a1f1dSLionel Sambuc 	    if (line == 0)
876*0a6a1f1dSLionel Sambuc 		unexpected_EOF();
877*0a6a1f1dSLionel Sambuc 	    --cptr;
878*0a6a1f1dSLionel Sambuc 	    buf_size += (size_t) linesize;
879*0a6a1f1dSLionel Sambuc 	    buf = TREALLOC(char, buf, buf_size);
880*0a6a1f1dSLionel Sambuc 	}
881*0a6a1f1dSLionel Sambuc 	NO_SPACE(buf);
882*0a6a1f1dSLionel Sambuc 	if (curly)
883*0a6a1f1dSLionel Sambuc 	{
884*0a6a1f1dSLionel Sambuc 	    if ((state == 2) && (c == L_CURL))
885*0a6a1f1dSLionel Sambuc 	    {
886*0a6a1f1dSLionel Sambuc 		buf[++i] = ',';
887*0a6a1f1dSLionel Sambuc 	    }
888*0a6a1f1dSLionel Sambuc 	    else if ((state == 2) && isspace(UCH(c)))
889*0a6a1f1dSLionel Sambuc 	    {
890*0a6a1f1dSLionel Sambuc 		;
891*0a6a1f1dSLionel Sambuc 	    }
892*0a6a1f1dSLionel Sambuc 	    else if ((c != L_CURL) && (c != R_CURL))
893*0a6a1f1dSLionel Sambuc 	    {
894*0a6a1f1dSLionel Sambuc 		buf[++i] = (char)c;
895*0a6a1f1dSLionel Sambuc 	    }
896*0a6a1f1dSLionel Sambuc 	}
897*0a6a1f1dSLionel Sambuc 	cptr++;
898*0a6a1f1dSLionel Sambuc     }
899*0a6a1f1dSLionel Sambuc     while (curly < 2 || more_curly());
900*0a6a1f1dSLionel Sambuc 
901*0a6a1f1dSLionel Sambuc     if (i == 0)
902*0a6a1f1dSLionel Sambuc     {
903*0a6a1f1dSLionel Sambuc 	if (curly == 1)
904*0a6a1f1dSLionel Sambuc 	{
905*0a6a1f1dSLionel Sambuc 	    lineno = st_lineno;
906*0a6a1f1dSLionel Sambuc 	    missing_brace();
907*0a6a1f1dSLionel Sambuc 	}
908*0a6a1f1dSLionel Sambuc 	goto oops;
909*0a6a1f1dSLionel Sambuc     }
910*0a6a1f1dSLionel Sambuc 
911*0a6a1f1dSLionel Sambuc     buf[++i] = '\0';
912*0a6a1f1dSLionel Sambuc     i = trim_blanks(buf);
913*0a6a1f1dSLionel Sambuc 
914*0a6a1f1dSLionel Sambuc     comma = buf - 1;
915*0a6a1f1dSLionel Sambuc     do
916*0a6a1f1dSLionel Sambuc     {
917*0a6a1f1dSLionel Sambuc 	char *parms = (comma + 1);
918*0a6a1f1dSLionel Sambuc 	comma = strchr(parms, ',');
919*0a6a1f1dSLionel Sambuc 	if (comma != 0)
920*0a6a1f1dSLionel Sambuc 	    *comma = '\0';
921*0a6a1f1dSLionel Sambuc 
922*0a6a1f1dSLionel Sambuc 	(void)trim_blanks(parms);
923*0a6a1f1dSLionel Sambuc 	i = (int)strlen(parms) - 1;
924*0a6a1f1dSLionel Sambuc 	if (i < 0)
925*0a6a1f1dSLionel Sambuc 	{
926*0a6a1f1dSLionel Sambuc 	    goto oops;
927*0a6a1f1dSLionel Sambuc 	}
928*0a6a1f1dSLionel Sambuc 
929*0a6a1f1dSLionel Sambuc 	if (parms[i] == ']')
930*0a6a1f1dSLionel Sambuc 	{
931*0a6a1f1dSLionel Sambuc 	    int level = 1;
932*0a6a1f1dSLionel Sambuc 	    while (i >= 0 && level > 0 && parms[i] != '[')
933*0a6a1f1dSLionel Sambuc 	    {
934*0a6a1f1dSLionel Sambuc 		if (parms[i] == ']')
935*0a6a1f1dSLionel Sambuc 		    ++level;
936*0a6a1f1dSLionel Sambuc 		else if (parms[i] == '[')
937*0a6a1f1dSLionel Sambuc 		    --level;
938*0a6a1f1dSLionel Sambuc 		i--;
939*0a6a1f1dSLionel Sambuc 	    }
940*0a6a1f1dSLionel Sambuc 	    if (i <= 0)
941*0a6a1f1dSLionel Sambuc 		unexpected_EOF();
942*0a6a1f1dSLionel Sambuc 	    type2 = i--;
943*0a6a1f1dSLionel Sambuc 	}
944*0a6a1f1dSLionel Sambuc 	else
945*0a6a1f1dSLionel Sambuc 	{
946*0a6a1f1dSLionel Sambuc 	    type2 = i + 1;
947*0a6a1f1dSLionel Sambuc 	}
948*0a6a1f1dSLionel Sambuc 
949*0a6a1f1dSLionel Sambuc 	while (i > 0 && (isalnum(UCH(parms[i])) || UCH(parms[i]) == '_'))
950*0a6a1f1dSLionel Sambuc 	    i--;
951*0a6a1f1dSLionel Sambuc 
952*0a6a1f1dSLionel Sambuc 	if (!isspace(UCH(parms[i])) && parms[i] != '*')
953*0a6a1f1dSLionel Sambuc 	    goto oops;
954*0a6a1f1dSLionel Sambuc 
955*0a6a1f1dSLionel Sambuc 	name = i + 1;
956*0a6a1f1dSLionel Sambuc 
957*0a6a1f1dSLionel Sambuc 	save_param(k, parms, name, type2);
958*0a6a1f1dSLionel Sambuc     }
959*0a6a1f1dSLionel Sambuc     while (comma != 0);
960*0a6a1f1dSLionel Sambuc     FREE(buf);
9614a17663cSThomas Veerman     return;
9624a17663cSThomas Veerman 
963*0a6a1f1dSLionel Sambuc   oops:
964*0a6a1f1dSLionel Sambuc     FREE(buf);
9654a17663cSThomas Veerman     syntax_error(lineno, line, cptr);
9664a17663cSThomas Veerman }
9674a17663cSThomas Veerman 
9684a17663cSThomas Veerman static int
hexval(int c)9694a17663cSThomas Veerman hexval(int c)
9704a17663cSThomas Veerman {
9714a17663cSThomas Veerman     if (c >= '0' && c <= '9')
9724a17663cSThomas Veerman 	return (c - '0');
9734a17663cSThomas Veerman     if (c >= 'A' && c <= 'F')
9744a17663cSThomas Veerman 	return (c - 'A' + 10);
9754a17663cSThomas Veerman     if (c >= 'a' && c <= 'f')
9764a17663cSThomas Veerman 	return (c - 'a' + 10);
9774a17663cSThomas Veerman     return (-1);
9784a17663cSThomas Veerman }
9794a17663cSThomas Veerman 
9804a17663cSThomas Veerman static bucket *
get_literal(void)9814a17663cSThomas Veerman get_literal(void)
9824a17663cSThomas Veerman {
9834a17663cSThomas Veerman     int c, quote;
9844a17663cSThomas Veerman     int i;
9854a17663cSThomas Veerman     int n;
9864a17663cSThomas Veerman     char *s;
9874a17663cSThomas Veerman     bucket *bp;
988*0a6a1f1dSLionel Sambuc     struct ainfo a;
989*0a6a1f1dSLionel Sambuc     a.a_lineno = lineno;
990*0a6a1f1dSLionel Sambuc     a.a_line = dup_line();
991*0a6a1f1dSLionel Sambuc     a.a_cptr = a.a_line + (cptr - line);
9924a17663cSThomas Veerman 
9934a17663cSThomas Veerman     quote = *cptr++;
9944a17663cSThomas Veerman     cinc = 0;
9954a17663cSThomas Veerman     for (;;)
9964a17663cSThomas Veerman     {
9974a17663cSThomas Veerman 	c = *cptr++;
9984a17663cSThomas Veerman 	if (c == quote)
9994a17663cSThomas Veerman 	    break;
10004a17663cSThomas Veerman 	if (c == '\n')
1001*0a6a1f1dSLionel Sambuc 	    unterminated_string(&a);
10024a17663cSThomas Veerman 	if (c == '\\')
10034a17663cSThomas Veerman 	{
10044a17663cSThomas Veerman 	    char *c_cptr = cptr - 1;
10054a17663cSThomas Veerman 
10064a17663cSThomas Veerman 	    c = *cptr++;
10074a17663cSThomas Veerman 	    switch (c)
10084a17663cSThomas Veerman 	    {
10094a17663cSThomas Veerman 	    case '\n':
10104a17663cSThomas Veerman 		get_line();
10114a17663cSThomas Veerman 		if (line == 0)
1012*0a6a1f1dSLionel Sambuc 		    unterminated_string(&a);
10134a17663cSThomas Veerman 		continue;
10144a17663cSThomas Veerman 
10154a17663cSThomas Veerman 	    case '0':
10164a17663cSThomas Veerman 	    case '1':
10174a17663cSThomas Veerman 	    case '2':
10184a17663cSThomas Veerman 	    case '3':
10194a17663cSThomas Veerman 	    case '4':
10204a17663cSThomas Veerman 	    case '5':
10214a17663cSThomas Veerman 	    case '6':
10224a17663cSThomas Veerman 	    case '7':
10234a17663cSThomas Veerman 		n = c - '0';
10244a17663cSThomas Veerman 		c = *cptr;
10254a17663cSThomas Veerman 		if (IS_OCTAL(c))
10264a17663cSThomas Veerman 		{
10274a17663cSThomas Veerman 		    n = (n << 3) + (c - '0');
10284a17663cSThomas Veerman 		    c = *++cptr;
10294a17663cSThomas Veerman 		    if (IS_OCTAL(c))
10304a17663cSThomas Veerman 		    {
10314a17663cSThomas Veerman 			n = (n << 3) + (c - '0');
10324a17663cSThomas Veerman 			++cptr;
10334a17663cSThomas Veerman 		    }
10344a17663cSThomas Veerman 		}
10354a17663cSThomas Veerman 		if (n > MAXCHAR)
10364a17663cSThomas Veerman 		    illegal_character(c_cptr);
10374a17663cSThomas Veerman 		c = n;
10384a17663cSThomas Veerman 		break;
10394a17663cSThomas Veerman 
10404a17663cSThomas Veerman 	    case 'x':
10414a17663cSThomas Veerman 		c = *cptr++;
10424a17663cSThomas Veerman 		n = hexval(c);
10434a17663cSThomas Veerman 		if (n < 0 || n >= 16)
10444a17663cSThomas Veerman 		    illegal_character(c_cptr);
10454a17663cSThomas Veerman 		for (;;)
10464a17663cSThomas Veerman 		{
10474a17663cSThomas Veerman 		    c = *cptr;
10484a17663cSThomas Veerman 		    i = hexval(c);
10494a17663cSThomas Veerman 		    if (i < 0 || i >= 16)
10504a17663cSThomas Veerman 			break;
10514a17663cSThomas Veerman 		    ++cptr;
10524a17663cSThomas Veerman 		    n = (n << 4) + i;
10534a17663cSThomas Veerman 		    if (n > MAXCHAR)
10544a17663cSThomas Veerman 			illegal_character(c_cptr);
10554a17663cSThomas Veerman 		}
10564a17663cSThomas Veerman 		c = n;
10574a17663cSThomas Veerman 		break;
10584a17663cSThomas Veerman 
10594a17663cSThomas Veerman 	    case 'a':
10604a17663cSThomas Veerman 		c = 7;
10614a17663cSThomas Veerman 		break;
10624a17663cSThomas Veerman 	    case 'b':
10634a17663cSThomas Veerman 		c = '\b';
10644a17663cSThomas Veerman 		break;
10654a17663cSThomas Veerman 	    case 'f':
10664a17663cSThomas Veerman 		c = '\f';
10674a17663cSThomas Veerman 		break;
10684a17663cSThomas Veerman 	    case 'n':
10694a17663cSThomas Veerman 		c = '\n';
10704a17663cSThomas Veerman 		break;
10714a17663cSThomas Veerman 	    case 'r':
10724a17663cSThomas Veerman 		c = '\r';
10734a17663cSThomas Veerman 		break;
10744a17663cSThomas Veerman 	    case 't':
10754a17663cSThomas Veerman 		c = '\t';
10764a17663cSThomas Veerman 		break;
10774a17663cSThomas Veerman 	    case 'v':
10784a17663cSThomas Veerman 		c = '\v';
10794a17663cSThomas Veerman 		break;
10804a17663cSThomas Veerman 	    }
10814a17663cSThomas Veerman 	}
10824a17663cSThomas Veerman 	cachec(c);
10834a17663cSThomas Veerman     }
1084*0a6a1f1dSLionel Sambuc     FREE(a.a_line);
10854a17663cSThomas Veerman 
10864a17663cSThomas Veerman     n = cinc;
108784d9c625SLionel Sambuc     s = TMALLOC(char, n);
10884a17663cSThomas Veerman     NO_SPACE(s);
10894a17663cSThomas Veerman 
10904a17663cSThomas Veerman     for (i = 0; i < n; ++i)
10914a17663cSThomas Veerman 	s[i] = cache[i];
10924a17663cSThomas Veerman 
10934a17663cSThomas Veerman     cinc = 0;
10944a17663cSThomas Veerman     if (n == 1)
10954a17663cSThomas Veerman 	cachec('\'');
10964a17663cSThomas Veerman     else
10974a17663cSThomas Veerman 	cachec('"');
10984a17663cSThomas Veerman 
10994a17663cSThomas Veerman     for (i = 0; i < n; ++i)
11004a17663cSThomas Veerman     {
11014a17663cSThomas Veerman 	c = UCH(s[i]);
11024a17663cSThomas Veerman 	if (c == '\\' || c == cache[0])
11034a17663cSThomas Veerman 	{
11044a17663cSThomas Veerman 	    cachec('\\');
11054a17663cSThomas Veerman 	    cachec(c);
11064a17663cSThomas Veerman 	}
11074a17663cSThomas Veerman 	else if (isprint(c))
11084a17663cSThomas Veerman 	    cachec(c);
11094a17663cSThomas Veerman 	else
11104a17663cSThomas Veerman 	{
11114a17663cSThomas Veerman 	    cachec('\\');
11124a17663cSThomas Veerman 	    switch (c)
11134a17663cSThomas Veerman 	    {
11144a17663cSThomas Veerman 	    case 7:
11154a17663cSThomas Veerman 		cachec('a');
11164a17663cSThomas Veerman 		break;
11174a17663cSThomas Veerman 	    case '\b':
11184a17663cSThomas Veerman 		cachec('b');
11194a17663cSThomas Veerman 		break;
11204a17663cSThomas Veerman 	    case '\f':
11214a17663cSThomas Veerman 		cachec('f');
11224a17663cSThomas Veerman 		break;
11234a17663cSThomas Veerman 	    case '\n':
11244a17663cSThomas Veerman 		cachec('n');
11254a17663cSThomas Veerman 		break;
11264a17663cSThomas Veerman 	    case '\r':
11274a17663cSThomas Veerman 		cachec('r');
11284a17663cSThomas Veerman 		break;
11294a17663cSThomas Veerman 	    case '\t':
11304a17663cSThomas Veerman 		cachec('t');
11314a17663cSThomas Veerman 		break;
11324a17663cSThomas Veerman 	    case '\v':
11334a17663cSThomas Veerman 		cachec('v');
11344a17663cSThomas Veerman 		break;
11354a17663cSThomas Veerman 	    default:
11364a17663cSThomas Veerman 		cachec(((c >> 6) & 7) + '0');
11374a17663cSThomas Veerman 		cachec(((c >> 3) & 7) + '0');
11384a17663cSThomas Veerman 		cachec((c & 7) + '0');
11394a17663cSThomas Veerman 		break;
11404a17663cSThomas Veerman 	    }
11414a17663cSThomas Veerman 	}
11424a17663cSThomas Veerman     }
11434a17663cSThomas Veerman 
11444a17663cSThomas Veerman     if (n == 1)
11454a17663cSThomas Veerman 	cachec('\'');
11464a17663cSThomas Veerman     else
11474a17663cSThomas Veerman 	cachec('"');
11484a17663cSThomas Veerman 
11494a17663cSThomas Veerman     cachec(NUL);
11504a17663cSThomas Veerman     bp = lookup(cache);
11514a17663cSThomas Veerman     bp->class = TERM;
11524a17663cSThomas Veerman     if (n == 1 && bp->value == UNDEFINED)
11534a17663cSThomas Veerman 	bp->value = UCH(*s);
11544a17663cSThomas Veerman     FREE(s);
11554a17663cSThomas Veerman 
11564a17663cSThomas Veerman     return (bp);
11574a17663cSThomas Veerman }
11584a17663cSThomas Veerman 
11594a17663cSThomas Veerman static int
is_reserved(char * name)11604a17663cSThomas Veerman is_reserved(char *name)
11614a17663cSThomas Veerman {
11624a17663cSThomas Veerman     char *s;
11634a17663cSThomas Veerman 
11644a17663cSThomas Veerman     if (strcmp(name, ".") == 0 ||
11654a17663cSThomas Veerman 	strcmp(name, "$accept") == 0 ||
11664a17663cSThomas Veerman 	strcmp(name, "$end") == 0)
11674a17663cSThomas Veerman 	return (1);
11684a17663cSThomas Veerman 
11694a17663cSThomas Veerman     if (name[0] == '$' && name[1] == '$' && isdigit(UCH(name[2])))
11704a17663cSThomas Veerman     {
11714a17663cSThomas Veerman 	s = name + 3;
11724a17663cSThomas Veerman 	while (isdigit(UCH(*s)))
11734a17663cSThomas Veerman 	    ++s;
11744a17663cSThomas Veerman 	if (*s == NUL)
11754a17663cSThomas Veerman 	    return (1);
11764a17663cSThomas Veerman     }
11774a17663cSThomas Veerman 
11784a17663cSThomas Veerman     return (0);
11794a17663cSThomas Veerman }
11804a17663cSThomas Veerman 
11814a17663cSThomas Veerman static bucket *
get_name(void)11824a17663cSThomas Veerman get_name(void)
11834a17663cSThomas Veerman {
11844a17663cSThomas Veerman     int c;
11854a17663cSThomas Veerman 
11864a17663cSThomas Veerman     cinc = 0;
11874a17663cSThomas Veerman     for (c = *cptr; IS_IDENT(c); c = *++cptr)
11884a17663cSThomas Veerman 	cachec(c);
11894a17663cSThomas Veerman     cachec(NUL);
11904a17663cSThomas Veerman 
11914a17663cSThomas Veerman     if (is_reserved(cache))
11924a17663cSThomas Veerman 	used_reserved(cache);
11934a17663cSThomas Veerman 
11944a17663cSThomas Veerman     return (lookup(cache));
11954a17663cSThomas Veerman }
11964a17663cSThomas Veerman 
11974a17663cSThomas Veerman static Value_t
get_number(void)11984a17663cSThomas Veerman get_number(void)
11994a17663cSThomas Veerman {
12004a17663cSThomas Veerman     int c;
12014a17663cSThomas Veerman     Value_t n;
12024a17663cSThomas Veerman 
12034a17663cSThomas Veerman     n = 0;
12044a17663cSThomas Veerman     for (c = *cptr; isdigit(c); c = *++cptr)
12054a17663cSThomas Veerman 	n = (Value_t) (10 * n + (c - '0'));
12064a17663cSThomas Veerman 
12074a17663cSThomas Veerman     return (n);
12084a17663cSThomas Veerman }
12094a17663cSThomas Veerman 
12104a17663cSThomas Veerman static char *
cache_tag(char * tag,size_t len)1211*0a6a1f1dSLionel Sambuc cache_tag(char *tag, size_t len)
1212*0a6a1f1dSLionel Sambuc {
1213*0a6a1f1dSLionel Sambuc     int i;
1214*0a6a1f1dSLionel Sambuc     char *s;
1215*0a6a1f1dSLionel Sambuc 
1216*0a6a1f1dSLionel Sambuc     for (i = 0; i < ntags; ++i)
1217*0a6a1f1dSLionel Sambuc     {
1218*0a6a1f1dSLionel Sambuc 	if (strncmp(tag, tag_table[i], len) == 0 &&
1219*0a6a1f1dSLionel Sambuc 	    tag_table[i][len] == NUL)
1220*0a6a1f1dSLionel Sambuc 	    return (tag_table[i]);
1221*0a6a1f1dSLionel Sambuc     }
1222*0a6a1f1dSLionel Sambuc 
1223*0a6a1f1dSLionel Sambuc     if (ntags >= tagmax)
1224*0a6a1f1dSLionel Sambuc     {
1225*0a6a1f1dSLionel Sambuc 	tagmax += 16;
1226*0a6a1f1dSLionel Sambuc 	tag_table =
1227*0a6a1f1dSLionel Sambuc 	    (tag_table
1228*0a6a1f1dSLionel Sambuc 	     ? TREALLOC(char *, tag_table, tagmax)
1229*0a6a1f1dSLionel Sambuc 	     : TMALLOC(char *, tagmax));
1230*0a6a1f1dSLionel Sambuc 	NO_SPACE(tag_table);
1231*0a6a1f1dSLionel Sambuc     }
1232*0a6a1f1dSLionel Sambuc 
1233*0a6a1f1dSLionel Sambuc     s = TMALLOC(char, len + 1);
1234*0a6a1f1dSLionel Sambuc     NO_SPACE(s);
1235*0a6a1f1dSLionel Sambuc 
1236*0a6a1f1dSLionel Sambuc     strncpy(s, tag, len);
1237*0a6a1f1dSLionel Sambuc     s[len] = 0;
1238*0a6a1f1dSLionel Sambuc     tag_table[ntags++] = s;
1239*0a6a1f1dSLionel Sambuc     return s;
1240*0a6a1f1dSLionel Sambuc }
1241*0a6a1f1dSLionel Sambuc 
1242*0a6a1f1dSLionel Sambuc static char *
get_tag(void)12434a17663cSThomas Veerman get_tag(void)
12444a17663cSThomas Veerman {
12454a17663cSThomas Veerman     int c;
12464a17663cSThomas Veerman     int t_lineno = lineno;
12474a17663cSThomas Veerman     char *t_line = dup_line();
12484a17663cSThomas Veerman     char *t_cptr = t_line + (cptr - line);
12494a17663cSThomas Veerman 
12504a17663cSThomas Veerman     ++cptr;
12514a17663cSThomas Veerman     c = nextc();
12524a17663cSThomas Veerman     if (c == EOF)
12534a17663cSThomas Veerman 	unexpected_EOF();
12544a17663cSThomas Veerman     if (!isalpha(c) && c != '_' && c != '$')
12554a17663cSThomas Veerman 	illegal_tag(t_lineno, t_line, t_cptr);
12564a17663cSThomas Veerman 
12574a17663cSThomas Veerman     cinc = 0;
12584a17663cSThomas Veerman     do
12594a17663cSThomas Veerman     {
12604a17663cSThomas Veerman 	cachec(c);
12614a17663cSThomas Veerman 	c = *++cptr;
12624a17663cSThomas Veerman     }
12634a17663cSThomas Veerman     while (IS_IDENT(c));
12644a17663cSThomas Veerman     cachec(NUL);
12654a17663cSThomas Veerman 
12664a17663cSThomas Veerman     c = nextc();
12674a17663cSThomas Veerman     if (c == EOF)
12684a17663cSThomas Veerman 	unexpected_EOF();
12694a17663cSThomas Veerman     if (c != '>')
12704a17663cSThomas Veerman 	illegal_tag(t_lineno, t_line, t_cptr);
12714a17663cSThomas Veerman     ++cptr;
12724a17663cSThomas Veerman 
12734a17663cSThomas Veerman     FREE(t_line);
1274*0a6a1f1dSLionel Sambuc     havetags = 1;
1275*0a6a1f1dSLionel Sambuc     return cache_tag(cache, (size_t) cinc);
12764a17663cSThomas Veerman }
12774a17663cSThomas Veerman 
1278*0a6a1f1dSLionel Sambuc #if defined(YYBTYACC)
1279*0a6a1f1dSLionel Sambuc static char *
scan_id(void)1280*0a6a1f1dSLionel Sambuc scan_id(void)
12814a17663cSThomas Veerman {
1282*0a6a1f1dSLionel Sambuc     char *b = cptr;
12834a17663cSThomas Veerman 
1284*0a6a1f1dSLionel Sambuc     while (isalnum((unsigned char)*cptr) || *cptr == '_' || *cptr == '$')
1285*0a6a1f1dSLionel Sambuc 	cptr++;
1286*0a6a1f1dSLionel Sambuc     return cache_tag(b, (size_t) (cptr - b));
12874a17663cSThomas Veerman }
1288*0a6a1f1dSLionel Sambuc #endif
12894a17663cSThomas Veerman 
12904a17663cSThomas Veerman static void
declare_tokens(int assoc)12914a17663cSThomas Veerman declare_tokens(int assoc)
12924a17663cSThomas Veerman {
12934a17663cSThomas Veerman     int c;
12944a17663cSThomas Veerman     bucket *bp;
12954a17663cSThomas Veerman     Value_t value;
12964a17663cSThomas Veerman     char *tag = 0;
12974a17663cSThomas Veerman 
12984a17663cSThomas Veerman     if (assoc != TOKEN)
12994a17663cSThomas Veerman 	++prec;
13004a17663cSThomas Veerman 
13014a17663cSThomas Veerman     c = nextc();
13024a17663cSThomas Veerman     if (c == EOF)
13034a17663cSThomas Veerman 	unexpected_EOF();
13044a17663cSThomas Veerman     if (c == '<')
13054a17663cSThomas Veerman     {
13064a17663cSThomas Veerman 	tag = get_tag();
13074a17663cSThomas Veerman 	c = nextc();
13084a17663cSThomas Veerman 	if (c == EOF)
13094a17663cSThomas Veerman 	    unexpected_EOF();
13104a17663cSThomas Veerman     }
13114a17663cSThomas Veerman 
13124a17663cSThomas Veerman     for (;;)
13134a17663cSThomas Veerman     {
13144a17663cSThomas Veerman 	if (isalpha(c) || c == '_' || c == '.' || c == '$')
13154a17663cSThomas Veerman 	    bp = get_name();
13164a17663cSThomas Veerman 	else if (c == '\'' || c == '"')
13174a17663cSThomas Veerman 	    bp = get_literal();
13184a17663cSThomas Veerman 	else
13194a17663cSThomas Veerman 	    return;
13204a17663cSThomas Veerman 
13214a17663cSThomas Veerman 	if (bp == goal)
13224a17663cSThomas Veerman 	    tokenized_start(bp->name);
13234a17663cSThomas Veerman 	bp->class = TERM;
13244a17663cSThomas Veerman 
13254a17663cSThomas Veerman 	if (tag)
13264a17663cSThomas Veerman 	{
13274a17663cSThomas Veerman 	    if (bp->tag && tag != bp->tag)
13284a17663cSThomas Veerman 		retyped_warning(bp->name);
13294a17663cSThomas Veerman 	    bp->tag = tag;
13304a17663cSThomas Veerman 	}
13314a17663cSThomas Veerman 
13324a17663cSThomas Veerman 	if (assoc != TOKEN)
13334a17663cSThomas Veerman 	{
13344a17663cSThomas Veerman 	    if (bp->prec && prec != bp->prec)
13354a17663cSThomas Veerman 		reprec_warning(bp->name);
13364a17663cSThomas Veerman 	    bp->assoc = (Assoc_t) assoc;
13374a17663cSThomas Veerman 	    bp->prec = prec;
13384a17663cSThomas Veerman 	}
13394a17663cSThomas Veerman 
13404a17663cSThomas Veerman 	c = nextc();
13414a17663cSThomas Veerman 	if (c == EOF)
13424a17663cSThomas Veerman 	    unexpected_EOF();
13434a17663cSThomas Veerman 
13444a17663cSThomas Veerman 	if (isdigit(c))
13454a17663cSThomas Veerman 	{
13464a17663cSThomas Veerman 	    value = get_number();
13474a17663cSThomas Veerman 	    if (bp->value != UNDEFINED && value != bp->value)
13484a17663cSThomas Veerman 		revalued_warning(bp->name);
13494a17663cSThomas Veerman 	    bp->value = value;
13504a17663cSThomas Veerman 	    c = nextc();
13514a17663cSThomas Veerman 	    if (c == EOF)
13524a17663cSThomas Veerman 		unexpected_EOF();
13534a17663cSThomas Veerman 	}
13544a17663cSThomas Veerman     }
13554a17663cSThomas Veerman }
13564a17663cSThomas Veerman 
13574a17663cSThomas Veerman /*
13584a17663cSThomas Veerman  * %expect requires special handling
13594a17663cSThomas Veerman  * as it really isn't part of the yacc
13604a17663cSThomas Veerman  * grammar only a flag for yacc proper.
13614a17663cSThomas Veerman  */
13624a17663cSThomas Veerman static void
declare_expect(int assoc)13634a17663cSThomas Veerman declare_expect(int assoc)
13644a17663cSThomas Veerman {
13654a17663cSThomas Veerman     int c;
13664a17663cSThomas Veerman 
13674a17663cSThomas Veerman     if (assoc != EXPECT && assoc != EXPECT_RR)
13684a17663cSThomas Veerman 	++prec;
13694a17663cSThomas Veerman 
13704a17663cSThomas Veerman     /*
13714a17663cSThomas Veerman      * Stay away from nextc - doesn't
13724a17663cSThomas Veerman      * detect EOL and will read to EOF.
13734a17663cSThomas Veerman      */
13744a17663cSThomas Veerman     c = *++cptr;
13754a17663cSThomas Veerman     if (c == EOF)
13764a17663cSThomas Veerman 	unexpected_EOF();
13774a17663cSThomas Veerman 
13784a17663cSThomas Veerman     for (;;)
13794a17663cSThomas Veerman     {
13804a17663cSThomas Veerman 	if (isdigit(c))
13814a17663cSThomas Veerman 	{
13824a17663cSThomas Veerman 	    if (assoc == EXPECT)
13834a17663cSThomas Veerman 		SRexpect = get_number();
13844a17663cSThomas Veerman 	    else
13854a17663cSThomas Veerman 		RRexpect = get_number();
13864a17663cSThomas Veerman 	    break;
13874a17663cSThomas Veerman 	}
13884a17663cSThomas Veerman 	/*
13894a17663cSThomas Veerman 	 * Looking for number before EOL.
13904a17663cSThomas Veerman 	 * Spaces, tabs, and numbers are ok,
13914a17663cSThomas Veerman 	 * words, punc., etc. are syntax errors.
13924a17663cSThomas Veerman 	 */
13934a17663cSThomas Veerman 	else if (c == '\n' || isalpha(c) || !isspace(c))
13944a17663cSThomas Veerman 	{
13954a17663cSThomas Veerman 	    syntax_error(lineno, line, cptr);
13964a17663cSThomas Veerman 	}
13974a17663cSThomas Veerman 	else
13984a17663cSThomas Veerman 	{
13994a17663cSThomas Veerman 	    c = *++cptr;
14004a17663cSThomas Veerman 	    if (c == EOF)
14014a17663cSThomas Veerman 		unexpected_EOF();
14024a17663cSThomas Veerman 	}
14034a17663cSThomas Veerman     }
14044a17663cSThomas Veerman }
14054a17663cSThomas Veerman 
1406*0a6a1f1dSLionel Sambuc #if defined(YYBTYACC)
14074a17663cSThomas Veerman static void
declare_argtypes(bucket * bp)1408*0a6a1f1dSLionel Sambuc declare_argtypes(bucket *bp)
14094a17663cSThomas Veerman {
1410*0a6a1f1dSLionel Sambuc     char *tags[MAXARGS];
1411*0a6a1f1dSLionel Sambuc     int args = 0, c;
14124a17663cSThomas Veerman 
1413*0a6a1f1dSLionel Sambuc     if (bp->args >= 0)
1414*0a6a1f1dSLionel Sambuc 	retyped_warning(bp->name);
1415*0a6a1f1dSLionel Sambuc     cptr++;			/* skip open paren */
1416*0a6a1f1dSLionel Sambuc     for (;;)
1417*0a6a1f1dSLionel Sambuc     {
14184a17663cSThomas Veerman 	c = nextc();
14194a17663cSThomas Veerman 	if (c == EOF)
14204a17663cSThomas Veerman 	    unexpected_EOF();
14214a17663cSThomas Veerman 	if (c != '<')
14224a17663cSThomas Veerman 	    syntax_error(lineno, line, cptr);
1423*0a6a1f1dSLionel Sambuc 	tags[args++] = get_tag();
1424*0a6a1f1dSLionel Sambuc 	c = nextc();
1425*0a6a1f1dSLionel Sambuc 	if (c == R_PAREN)
1426*0a6a1f1dSLionel Sambuc 	    break;
1427*0a6a1f1dSLionel Sambuc 	if (c == EOF)
1428*0a6a1f1dSLionel Sambuc 	    unexpected_EOF();
1429*0a6a1f1dSLionel Sambuc     }
1430*0a6a1f1dSLionel Sambuc     cptr++;			/* skip close paren */
1431*0a6a1f1dSLionel Sambuc     bp->args = args;
1432*0a6a1f1dSLionel Sambuc     bp->argnames = TMALLOC(char *, args);
1433*0a6a1f1dSLionel Sambuc     NO_SPACE(bp->argnames);
1434*0a6a1f1dSLionel Sambuc     bp->argtags = CALLOC(sizeof(char *), args + 1);
1435*0a6a1f1dSLionel Sambuc     NO_SPACE(bp->argtags);
1436*0a6a1f1dSLionel Sambuc     while (--args >= 0)
1437*0a6a1f1dSLionel Sambuc     {
1438*0a6a1f1dSLionel Sambuc 	bp->argtags[args] = tags[args];
1439*0a6a1f1dSLionel Sambuc 	bp->argnames[args] = NULL;
1440*0a6a1f1dSLionel Sambuc     }
1441*0a6a1f1dSLionel Sambuc }
1442*0a6a1f1dSLionel Sambuc #endif
1443*0a6a1f1dSLionel Sambuc 
1444*0a6a1f1dSLionel Sambuc static void
declare_types(void)1445*0a6a1f1dSLionel Sambuc declare_types(void)
1446*0a6a1f1dSLionel Sambuc {
1447*0a6a1f1dSLionel Sambuc     int c;
1448*0a6a1f1dSLionel Sambuc     bucket *bp;
1449*0a6a1f1dSLionel Sambuc     char *tag = NULL;
1450*0a6a1f1dSLionel Sambuc 
1451*0a6a1f1dSLionel Sambuc     c = nextc();
1452*0a6a1f1dSLionel Sambuc     if (c == EOF)
1453*0a6a1f1dSLionel Sambuc 	unexpected_EOF();
1454*0a6a1f1dSLionel Sambuc     if (c == '<')
14554a17663cSThomas Veerman 	tag = get_tag();
14564a17663cSThomas Veerman 
14574a17663cSThomas Veerman     for (;;)
14584a17663cSThomas Veerman     {
14594a17663cSThomas Veerman 	c = nextc();
1460*0a6a1f1dSLionel Sambuc 	if (c == EOF)
1461*0a6a1f1dSLionel Sambuc 	    unexpected_EOF();
14624a17663cSThomas Veerman 	if (isalpha(c) || c == '_' || c == '.' || c == '$')
1463*0a6a1f1dSLionel Sambuc 	{
14644a17663cSThomas Veerman 	    bp = get_name();
1465*0a6a1f1dSLionel Sambuc #if defined(YYBTYACC)
1466*0a6a1f1dSLionel Sambuc 	    if (nextc() == L_PAREN)
1467*0a6a1f1dSLionel Sambuc 		declare_argtypes(bp);
1468*0a6a1f1dSLionel Sambuc 	    else
1469*0a6a1f1dSLionel Sambuc 		bp->args = 0;
1470*0a6a1f1dSLionel Sambuc #endif
1471*0a6a1f1dSLionel Sambuc 	}
14724a17663cSThomas Veerman 	else if (c == '\'' || c == '"')
1473*0a6a1f1dSLionel Sambuc 	{
14744a17663cSThomas Veerman 	    bp = get_literal();
1475*0a6a1f1dSLionel Sambuc #if defined(YYBTYACC)
1476*0a6a1f1dSLionel Sambuc 	    bp->args = 0;
1477*0a6a1f1dSLionel Sambuc #endif
1478*0a6a1f1dSLionel Sambuc 	}
14794a17663cSThomas Veerman 	else
14804a17663cSThomas Veerman 	    return;
14814a17663cSThomas Veerman 
1482*0a6a1f1dSLionel Sambuc 	if (tag)
1483*0a6a1f1dSLionel Sambuc 	{
14844a17663cSThomas Veerman 	    if (bp->tag && tag != bp->tag)
14854a17663cSThomas Veerman 		retyped_warning(bp->name);
14864a17663cSThomas Veerman 	    bp->tag = tag;
14874a17663cSThomas Veerman 	}
14884a17663cSThomas Veerman     }
1489*0a6a1f1dSLionel Sambuc }
14904a17663cSThomas Veerman 
14914a17663cSThomas Veerman static void
declare_start(void)14924a17663cSThomas Veerman declare_start(void)
14934a17663cSThomas Veerman {
14944a17663cSThomas Veerman     int c;
14954a17663cSThomas Veerman     bucket *bp;
14964a17663cSThomas Veerman 
14974a17663cSThomas Veerman     c = nextc();
14984a17663cSThomas Veerman     if (c == EOF)
14994a17663cSThomas Veerman 	unexpected_EOF();
15004a17663cSThomas Veerman     if (!isalpha(c) && c != '_' && c != '.' && c != '$')
15014a17663cSThomas Veerman 	syntax_error(lineno, line, cptr);
15024a17663cSThomas Veerman     bp = get_name();
15034a17663cSThomas Veerman     if (bp->class == TERM)
15044a17663cSThomas Veerman 	terminal_start(bp->name);
15054a17663cSThomas Veerman     if (goal && goal != bp)
15064a17663cSThomas Veerman 	restarted_warning();
15074a17663cSThomas Veerman     goal = bp;
15084a17663cSThomas Veerman }
15094a17663cSThomas Veerman 
15104a17663cSThomas Veerman static void
read_declarations(void)15114a17663cSThomas Veerman read_declarations(void)
15124a17663cSThomas Veerman {
15134a17663cSThomas Veerman     int c, k;
15144a17663cSThomas Veerman 
15154a17663cSThomas Veerman     cache_size = 256;
151684d9c625SLionel Sambuc     cache = TMALLOC(char, cache_size);
15174a17663cSThomas Veerman     NO_SPACE(cache);
15184a17663cSThomas Veerman 
15194a17663cSThomas Veerman     for (;;)
15204a17663cSThomas Veerman     {
15214a17663cSThomas Veerman 	c = nextc();
15224a17663cSThomas Veerman 	if (c == EOF)
15234a17663cSThomas Veerman 	    unexpected_EOF();
15244a17663cSThomas Veerman 	if (c != '%')
15254a17663cSThomas Veerman 	    syntax_error(lineno, line, cptr);
15264a17663cSThomas Veerman 	switch (k = keyword())
15274a17663cSThomas Veerman 	{
15284a17663cSThomas Veerman 	case MARK:
15294a17663cSThomas Veerman 	    return;
15304a17663cSThomas Veerman 
15314a17663cSThomas Veerman 	case IDENT:
15324a17663cSThomas Veerman 	    copy_ident();
15334a17663cSThomas Veerman 	    break;
15344a17663cSThomas Veerman 
15354a17663cSThomas Veerman 	case TEXT:
15364a17663cSThomas Veerman 	    copy_text();
15374a17663cSThomas Veerman 	    break;
15384a17663cSThomas Veerman 
15394a17663cSThomas Veerman 	case UNION:
15404a17663cSThomas Veerman 	    copy_union();
15414a17663cSThomas Veerman 	    break;
15424a17663cSThomas Veerman 
15434a17663cSThomas Veerman 	case TOKEN:
15444a17663cSThomas Veerman 	case LEFT:
15454a17663cSThomas Veerman 	case RIGHT:
15464a17663cSThomas Veerman 	case NONASSOC:
15474a17663cSThomas Veerman 	    declare_tokens(k);
15484a17663cSThomas Veerman 	    break;
15494a17663cSThomas Veerman 
15504a17663cSThomas Veerman 	case EXPECT:
15514a17663cSThomas Veerman 	case EXPECT_RR:
15524a17663cSThomas Veerman 	    declare_expect(k);
15534a17663cSThomas Veerman 	    break;
15544a17663cSThomas Veerman 
15554a17663cSThomas Veerman 	case TYPE:
15564a17663cSThomas Veerman 	    declare_types();
15574a17663cSThomas Veerman 	    break;
15584a17663cSThomas Veerman 
15594a17663cSThomas Veerman 	case START:
15604a17663cSThomas Veerman 	    declare_start();
15614a17663cSThomas Veerman 	    break;
15624a17663cSThomas Veerman 
15634a17663cSThomas Veerman 	case PURE_PARSER:
15644a17663cSThomas Veerman 	    pure_parser = 1;
15654a17663cSThomas Veerman 	    break;
15664a17663cSThomas Veerman 
15674a17663cSThomas Veerman 	case PARSE_PARAM:
15684a17663cSThomas Veerman 	case LEX_PARAM:
15694a17663cSThomas Veerman 	    copy_param(k);
15704a17663cSThomas Veerman 	    break;
15714a17663cSThomas Veerman 
1572*0a6a1f1dSLionel Sambuc 	case TOKEN_TABLE:
1573*0a6a1f1dSLionel Sambuc 	    token_table = 1;
1574*0a6a1f1dSLionel Sambuc 	    break;
1575*0a6a1f1dSLionel Sambuc 
1576*0a6a1f1dSLionel Sambuc 	case ERROR_VERBOSE:
1577*0a6a1f1dSLionel Sambuc 	    error_verbose = 1;
1578*0a6a1f1dSLionel Sambuc 	    break;
1579*0a6a1f1dSLionel Sambuc 
1580*0a6a1f1dSLionel Sambuc #if defined(YYBTYACC)
1581*0a6a1f1dSLionel Sambuc 	case LOCATIONS:
1582*0a6a1f1dSLionel Sambuc 	    locations = 1;
1583*0a6a1f1dSLionel Sambuc 	    break;
1584*0a6a1f1dSLionel Sambuc 
1585*0a6a1f1dSLionel Sambuc 	case DESTRUCTOR:
1586*0a6a1f1dSLionel Sambuc 	    destructor = 1;
1587*0a6a1f1dSLionel Sambuc 	    copy_destructor();
1588*0a6a1f1dSLionel Sambuc 	    break;
1589*0a6a1f1dSLionel Sambuc 	case INITIAL_ACTION:
1590*0a6a1f1dSLionel Sambuc 	    copy_initial_action();
1591*0a6a1f1dSLionel Sambuc 	    break;
1592*0a6a1f1dSLionel Sambuc #endif
1593*0a6a1f1dSLionel Sambuc 
1594*0a6a1f1dSLionel Sambuc 	case XXXDEBUG:
1595*0a6a1f1dSLionel Sambuc 	    /* XXX: FIXME */
1596*0a6a1f1dSLionel Sambuc 	    break;
1597*0a6a1f1dSLionel Sambuc 
15984a17663cSThomas Veerman 	case POSIX_YACC:
15994a17663cSThomas Veerman 	    /* noop for bison compatibility. byacc is already designed to be posix
16004a17663cSThomas Veerman 	     * yacc compatible. */
16014a17663cSThomas Veerman 	    break;
16024a17663cSThomas Veerman 	}
16034a17663cSThomas Veerman     }
16044a17663cSThomas Veerman }
16054a17663cSThomas Veerman 
16064a17663cSThomas Veerman static void
initialize_grammar(void)16074a17663cSThomas Veerman initialize_grammar(void)
16084a17663cSThomas Veerman {
16094a17663cSThomas Veerman     nitems = 4;
16104a17663cSThomas Veerman     maxitems = 300;
16114a17663cSThomas Veerman 
161284d9c625SLionel Sambuc     pitem = TMALLOC(bucket *, maxitems);
16134a17663cSThomas Veerman     NO_SPACE(pitem);
16144a17663cSThomas Veerman 
16154a17663cSThomas Veerman     pitem[0] = 0;
16164a17663cSThomas Veerman     pitem[1] = 0;
16174a17663cSThomas Veerman     pitem[2] = 0;
16184a17663cSThomas Veerman     pitem[3] = 0;
16194a17663cSThomas Veerman 
16204a17663cSThomas Veerman     nrules = 3;
16214a17663cSThomas Veerman     maxrules = 100;
16224a17663cSThomas Veerman 
162384d9c625SLionel Sambuc     plhs = TMALLOC(bucket *, maxrules);
16244a17663cSThomas Veerman     NO_SPACE(plhs);
16254a17663cSThomas Veerman 
16264a17663cSThomas Veerman     plhs[0] = 0;
16274a17663cSThomas Veerman     plhs[1] = 0;
16284a17663cSThomas Veerman     plhs[2] = 0;
16294a17663cSThomas Veerman 
163084d9c625SLionel Sambuc     rprec = TMALLOC(Value_t, maxrules);
16314a17663cSThomas Veerman     NO_SPACE(rprec);
16324a17663cSThomas Veerman 
16334a17663cSThomas Veerman     rprec[0] = 0;
16344a17663cSThomas Veerman     rprec[1] = 0;
16354a17663cSThomas Veerman     rprec[2] = 0;
16364a17663cSThomas Veerman 
163784d9c625SLionel Sambuc     rassoc = TMALLOC(Assoc_t, maxrules);
16384a17663cSThomas Veerman     NO_SPACE(rassoc);
16394a17663cSThomas Veerman 
16404a17663cSThomas Veerman     rassoc[0] = TOKEN;
16414a17663cSThomas Veerman     rassoc[1] = TOKEN;
16424a17663cSThomas Veerman     rassoc[2] = TOKEN;
16434a17663cSThomas Veerman }
16444a17663cSThomas Veerman 
16454a17663cSThomas Veerman static void
expand_items(void)16464a17663cSThomas Veerman expand_items(void)
16474a17663cSThomas Veerman {
16484a17663cSThomas Veerman     maxitems += 300;
164984d9c625SLionel Sambuc     pitem = TREALLOC(bucket *, pitem, maxitems);
16504a17663cSThomas Veerman     NO_SPACE(pitem);
16514a17663cSThomas Veerman }
16524a17663cSThomas Veerman 
16534a17663cSThomas Veerman static void
expand_rules(void)16544a17663cSThomas Veerman expand_rules(void)
16554a17663cSThomas Veerman {
16564a17663cSThomas Veerman     maxrules += 100;
16574a17663cSThomas Veerman 
165884d9c625SLionel Sambuc     plhs = TREALLOC(bucket *, plhs, maxrules);
16594a17663cSThomas Veerman     NO_SPACE(plhs);
16604a17663cSThomas Veerman 
166184d9c625SLionel Sambuc     rprec = TREALLOC(Value_t, rprec, maxrules);
16624a17663cSThomas Veerman     NO_SPACE(rprec);
16634a17663cSThomas Veerman 
166484d9c625SLionel Sambuc     rassoc = TREALLOC(Assoc_t, rassoc, maxrules);
16654a17663cSThomas Veerman     NO_SPACE(rassoc);
16664a17663cSThomas Veerman }
16674a17663cSThomas Veerman 
1668*0a6a1f1dSLionel Sambuc /* set immediately prior to where copy_args() could be called, and incremented by
1669*0a6a1f1dSLionel Sambuc    the various routines that will rescan the argument list as appropriate */
1670*0a6a1f1dSLionel Sambuc static int rescan_lineno;
1671*0a6a1f1dSLionel Sambuc #if defined(YYBTYACC)
1672*0a6a1f1dSLionel Sambuc 
1673*0a6a1f1dSLionel Sambuc static char *
copy_args(int * alen)1674*0a6a1f1dSLionel Sambuc copy_args(int *alen)
1675*0a6a1f1dSLionel Sambuc {
1676*0a6a1f1dSLionel Sambuc     struct mstring *s = msnew();
1677*0a6a1f1dSLionel Sambuc     int depth = 0, len = 1;
1678*0a6a1f1dSLionel Sambuc     char c, quote = 0;
1679*0a6a1f1dSLionel Sambuc     struct ainfo a;
1680*0a6a1f1dSLionel Sambuc 
1681*0a6a1f1dSLionel Sambuc     a.a_lineno = lineno;
1682*0a6a1f1dSLionel Sambuc     a.a_line = dup_line();
1683*0a6a1f1dSLionel Sambuc     a.a_cptr = a.a_line + (cptr - line - 1);
1684*0a6a1f1dSLionel Sambuc 
1685*0a6a1f1dSLionel Sambuc     while ((c = *cptr++) != R_PAREN || depth || quote)
1686*0a6a1f1dSLionel Sambuc     {
1687*0a6a1f1dSLionel Sambuc 	if (c == ',' && !quote && !depth)
1688*0a6a1f1dSLionel Sambuc 	{
1689*0a6a1f1dSLionel Sambuc 	    len++;
1690*0a6a1f1dSLionel Sambuc 	    mputc(s, 0);
1691*0a6a1f1dSLionel Sambuc 	    continue;
1692*0a6a1f1dSLionel Sambuc 	}
1693*0a6a1f1dSLionel Sambuc 	mputc(s, c);
1694*0a6a1f1dSLionel Sambuc 	if (c == '\n')
1695*0a6a1f1dSLionel Sambuc 	{
1696*0a6a1f1dSLionel Sambuc 	    get_line();
1697*0a6a1f1dSLionel Sambuc 	    if (!line)
1698*0a6a1f1dSLionel Sambuc 	    {
1699*0a6a1f1dSLionel Sambuc 		if (quote)
1700*0a6a1f1dSLionel Sambuc 		    unterminated_string(&a);
1701*0a6a1f1dSLionel Sambuc 		else
1702*0a6a1f1dSLionel Sambuc 		    unterminated_arglist(&a);
1703*0a6a1f1dSLionel Sambuc 	    }
1704*0a6a1f1dSLionel Sambuc 	}
1705*0a6a1f1dSLionel Sambuc 	else if (quote)
1706*0a6a1f1dSLionel Sambuc 	{
1707*0a6a1f1dSLionel Sambuc 	    if (c == quote)
1708*0a6a1f1dSLionel Sambuc 		quote = 0;
1709*0a6a1f1dSLionel Sambuc 	    else if (c == '\\')
1710*0a6a1f1dSLionel Sambuc 	    {
1711*0a6a1f1dSLionel Sambuc 		if (*cptr != '\n')
1712*0a6a1f1dSLionel Sambuc 		    mputc(s, *cptr++);
1713*0a6a1f1dSLionel Sambuc 	    }
1714*0a6a1f1dSLionel Sambuc 	}
1715*0a6a1f1dSLionel Sambuc 	else
1716*0a6a1f1dSLionel Sambuc 	{
1717*0a6a1f1dSLionel Sambuc 	    if (c == L_PAREN)
1718*0a6a1f1dSLionel Sambuc 		depth++;
1719*0a6a1f1dSLionel Sambuc 	    else if (c == R_PAREN)
1720*0a6a1f1dSLionel Sambuc 		depth--;
1721*0a6a1f1dSLionel Sambuc 	    else if (c == '\"' || c == '\'')
1722*0a6a1f1dSLionel Sambuc 		quote = c;
1723*0a6a1f1dSLionel Sambuc 	}
1724*0a6a1f1dSLionel Sambuc     }
1725*0a6a1f1dSLionel Sambuc     if (alen)
1726*0a6a1f1dSLionel Sambuc 	*alen = len;
1727*0a6a1f1dSLionel Sambuc     FREE(a.a_line);
1728*0a6a1f1dSLionel Sambuc     return msdone(s);
1729*0a6a1f1dSLionel Sambuc }
1730*0a6a1f1dSLionel Sambuc 
1731*0a6a1f1dSLionel Sambuc static char *
parse_id(char * p,char ** save)1732*0a6a1f1dSLionel Sambuc parse_id(char *p, char **save)
1733*0a6a1f1dSLionel Sambuc {
1734*0a6a1f1dSLionel Sambuc     char *b;
1735*0a6a1f1dSLionel Sambuc 
1736*0a6a1f1dSLionel Sambuc     while (isspace((unsigned char)*p))
1737*0a6a1f1dSLionel Sambuc 	if (*p++ == '\n')
1738*0a6a1f1dSLionel Sambuc 	    rescan_lineno++;
1739*0a6a1f1dSLionel Sambuc     if (!isalpha((unsigned char)*p) && *p != '_')
1740*0a6a1f1dSLionel Sambuc 	return NULL;
1741*0a6a1f1dSLionel Sambuc     b = p;
1742*0a6a1f1dSLionel Sambuc     while (isalnum((unsigned char)*p) || *p == '_' || *p == '$')
1743*0a6a1f1dSLionel Sambuc 	p++;
1744*0a6a1f1dSLionel Sambuc     if (save)
1745*0a6a1f1dSLionel Sambuc     {
1746*0a6a1f1dSLionel Sambuc 	*save = cache_tag(b, (size_t) (p - b));
1747*0a6a1f1dSLionel Sambuc     }
1748*0a6a1f1dSLionel Sambuc     return p;
1749*0a6a1f1dSLionel Sambuc }
1750*0a6a1f1dSLionel Sambuc 
1751*0a6a1f1dSLionel Sambuc static char *
parse_int(char * p,int * save)1752*0a6a1f1dSLionel Sambuc parse_int(char *p, int *save)
1753*0a6a1f1dSLionel Sambuc {
1754*0a6a1f1dSLionel Sambuc     int neg = 0, val = 0;
1755*0a6a1f1dSLionel Sambuc 
1756*0a6a1f1dSLionel Sambuc     while (isspace((unsigned char)*p))
1757*0a6a1f1dSLionel Sambuc 	if (*p++ == '\n')
1758*0a6a1f1dSLionel Sambuc 	    rescan_lineno++;
1759*0a6a1f1dSLionel Sambuc     if (*p == '-')
1760*0a6a1f1dSLionel Sambuc     {
1761*0a6a1f1dSLionel Sambuc 	neg = 1;
1762*0a6a1f1dSLionel Sambuc 	p++;
1763*0a6a1f1dSLionel Sambuc     }
1764*0a6a1f1dSLionel Sambuc     if (!isdigit((unsigned char)*p))
1765*0a6a1f1dSLionel Sambuc 	return NULL;
1766*0a6a1f1dSLionel Sambuc     while (isdigit((unsigned char)*p))
1767*0a6a1f1dSLionel Sambuc 	val = val * 10 + *p++ - '0';
1768*0a6a1f1dSLionel Sambuc     if (neg)
1769*0a6a1f1dSLionel Sambuc 	val = -val;
1770*0a6a1f1dSLionel Sambuc     if (save)
1771*0a6a1f1dSLionel Sambuc 	*save = val;
1772*0a6a1f1dSLionel Sambuc     return p;
1773*0a6a1f1dSLionel Sambuc }
1774*0a6a1f1dSLionel Sambuc 
1775*0a6a1f1dSLionel Sambuc static void
parse_arginfo(bucket * a,char * args,int argslen)1776*0a6a1f1dSLionel Sambuc parse_arginfo(bucket *a, char *args, int argslen)
1777*0a6a1f1dSLionel Sambuc {
1778*0a6a1f1dSLionel Sambuc     char *p = args, *tmp;
1779*0a6a1f1dSLionel Sambuc     int i, redec = 0;
1780*0a6a1f1dSLionel Sambuc 
1781*0a6a1f1dSLionel Sambuc     if (a->args > 0)
1782*0a6a1f1dSLionel Sambuc     {
1783*0a6a1f1dSLionel Sambuc 	if (a->args != argslen)
1784*0a6a1f1dSLionel Sambuc 	    arg_number_disagree_warning(rescan_lineno, a->name);
1785*0a6a1f1dSLionel Sambuc 	redec = 1;
1786*0a6a1f1dSLionel Sambuc     }
1787*0a6a1f1dSLionel Sambuc     else
1788*0a6a1f1dSLionel Sambuc     {
1789*0a6a1f1dSLionel Sambuc 	if ((a->args = argslen) == 0)
1790*0a6a1f1dSLionel Sambuc 	    return;
1791*0a6a1f1dSLionel Sambuc 	a->argnames = TMALLOC(char *, argslen);
1792*0a6a1f1dSLionel Sambuc 	NO_SPACE(a->argnames);
1793*0a6a1f1dSLionel Sambuc 	a->argtags = TMALLOC(char *, argslen);
1794*0a6a1f1dSLionel Sambuc 	NO_SPACE(a->argtags);
1795*0a6a1f1dSLionel Sambuc     }
1796*0a6a1f1dSLionel Sambuc     if (!args)
1797*0a6a1f1dSLionel Sambuc 	return;
1798*0a6a1f1dSLionel Sambuc     for (i = 0; i < argslen; i++)
1799*0a6a1f1dSLionel Sambuc     {
1800*0a6a1f1dSLionel Sambuc 	while (isspace((unsigned char)*p))
1801*0a6a1f1dSLionel Sambuc 	    if (*p++ == '\n')
1802*0a6a1f1dSLionel Sambuc 		rescan_lineno++;
1803*0a6a1f1dSLionel Sambuc 	if (*p++ != '$')
1804*0a6a1f1dSLionel Sambuc 	    bad_formals();
1805*0a6a1f1dSLionel Sambuc 	while (isspace((unsigned char)*p))
1806*0a6a1f1dSLionel Sambuc 	    if (*p++ == '\n')
1807*0a6a1f1dSLionel Sambuc 		rescan_lineno++;
1808*0a6a1f1dSLionel Sambuc 	if (*p == '<')
1809*0a6a1f1dSLionel Sambuc 	{
1810*0a6a1f1dSLionel Sambuc 	    havetags = 1;
1811*0a6a1f1dSLionel Sambuc 	    if (!(p = parse_id(p + 1, &tmp)))
1812*0a6a1f1dSLionel Sambuc 		bad_formals();
1813*0a6a1f1dSLionel Sambuc 	    while (isspace((unsigned char)*p))
1814*0a6a1f1dSLionel Sambuc 		if (*p++ == '\n')
1815*0a6a1f1dSLionel Sambuc 		    rescan_lineno++;
1816*0a6a1f1dSLionel Sambuc 	    if (*p++ != '>')
1817*0a6a1f1dSLionel Sambuc 		bad_formals();
1818*0a6a1f1dSLionel Sambuc 	    if (redec)
1819*0a6a1f1dSLionel Sambuc 	    {
1820*0a6a1f1dSLionel Sambuc 		if (a->argtags[i] != tmp)
1821*0a6a1f1dSLionel Sambuc 		    arg_type_disagree_warning(rescan_lineno, i + 1, a->name);
1822*0a6a1f1dSLionel Sambuc 	    }
1823*0a6a1f1dSLionel Sambuc 	    else
1824*0a6a1f1dSLionel Sambuc 		a->argtags[i] = tmp;
1825*0a6a1f1dSLionel Sambuc 	}
1826*0a6a1f1dSLionel Sambuc 	else if (!redec)
1827*0a6a1f1dSLionel Sambuc 	    a->argtags[i] = NULL;
1828*0a6a1f1dSLionel Sambuc 	if (!(p = parse_id(p, &a->argnames[i])))
1829*0a6a1f1dSLionel Sambuc 	    bad_formals();
1830*0a6a1f1dSLionel Sambuc 	while (isspace((unsigned char)*p))
1831*0a6a1f1dSLionel Sambuc 	    if (*p++ == '\n')
1832*0a6a1f1dSLionel Sambuc 		rescan_lineno++;
1833*0a6a1f1dSLionel Sambuc 	if (*p++)
1834*0a6a1f1dSLionel Sambuc 	    bad_formals();
1835*0a6a1f1dSLionel Sambuc     }
1836*0a6a1f1dSLionel Sambuc     free(args);
1837*0a6a1f1dSLionel Sambuc }
1838*0a6a1f1dSLionel Sambuc 
1839*0a6a1f1dSLionel Sambuc static char *
compile_arg(char ** theptr,char * yyvaltag)1840*0a6a1f1dSLionel Sambuc compile_arg(char **theptr, char *yyvaltag)
1841*0a6a1f1dSLionel Sambuc {
1842*0a6a1f1dSLionel Sambuc     char *p = *theptr;
1843*0a6a1f1dSLionel Sambuc     struct mstring *c = msnew();
1844*0a6a1f1dSLionel Sambuc     int i, j, n;
1845*0a6a1f1dSLionel Sambuc     Value_t *offsets = NULL, maxoffset;
1846*0a6a1f1dSLionel Sambuc     bucket **rhs;
1847*0a6a1f1dSLionel Sambuc 
1848*0a6a1f1dSLionel Sambuc     maxoffset = 0;
1849*0a6a1f1dSLionel Sambuc     n = 0;
1850*0a6a1f1dSLionel Sambuc     for (i = nitems - 1; pitem[i]; --i)
1851*0a6a1f1dSLionel Sambuc     {
1852*0a6a1f1dSLionel Sambuc 	n++;
1853*0a6a1f1dSLionel Sambuc 	if (pitem[i]->class != ARGUMENT)
1854*0a6a1f1dSLionel Sambuc 	    maxoffset++;
1855*0a6a1f1dSLionel Sambuc     }
1856*0a6a1f1dSLionel Sambuc     if (maxoffset > 0)
1857*0a6a1f1dSLionel Sambuc     {
1858*0a6a1f1dSLionel Sambuc 	offsets = TMALLOC(Value_t, maxoffset + 1);
1859*0a6a1f1dSLionel Sambuc 	NO_SPACE(offsets);
1860*0a6a1f1dSLionel Sambuc 
1861*0a6a1f1dSLionel Sambuc 	for (j = 0, i++; i < nitems; i++)
1862*0a6a1f1dSLionel Sambuc 	    if (pitem[i]->class != ARGUMENT)
1863*0a6a1f1dSLionel Sambuc 		offsets[++j] = (Value_t) (i - nitems + 1);
1864*0a6a1f1dSLionel Sambuc     }
1865*0a6a1f1dSLionel Sambuc     rhs = pitem + nitems - 1;
1866*0a6a1f1dSLionel Sambuc 
1867*0a6a1f1dSLionel Sambuc     if (yyvaltag)
1868*0a6a1f1dSLionel Sambuc 	msprintf(c, "yyval.%s = ", yyvaltag);
1869*0a6a1f1dSLionel Sambuc     else
1870*0a6a1f1dSLionel Sambuc 	msprintf(c, "yyval = ");
1871*0a6a1f1dSLionel Sambuc     while (*p)
1872*0a6a1f1dSLionel Sambuc     {
1873*0a6a1f1dSLionel Sambuc 	if (*p == '$')
1874*0a6a1f1dSLionel Sambuc 	{
1875*0a6a1f1dSLionel Sambuc 	    char *tag = NULL;
1876*0a6a1f1dSLionel Sambuc 	    if (*++p == '<')
1877*0a6a1f1dSLionel Sambuc 		if (!(p = parse_id(++p, &tag)) || *p++ != '>')
1878*0a6a1f1dSLionel Sambuc 		    illegal_tag(rescan_lineno, NULL, NULL);
1879*0a6a1f1dSLionel Sambuc 	    if (isdigit((unsigned char)*p) || *p == '-')
1880*0a6a1f1dSLionel Sambuc 	    {
1881*0a6a1f1dSLionel Sambuc 		int val;
1882*0a6a1f1dSLionel Sambuc 		if (!(p = parse_int(p, &val)))
1883*0a6a1f1dSLionel Sambuc 		    dollar_error(rescan_lineno, NULL, NULL);
1884*0a6a1f1dSLionel Sambuc 		if (val <= 0)
1885*0a6a1f1dSLionel Sambuc 		    i = val - n;
1886*0a6a1f1dSLionel Sambuc 		else if (val > maxoffset)
1887*0a6a1f1dSLionel Sambuc 		{
1888*0a6a1f1dSLionel Sambuc 		    dollar_warning(rescan_lineno, val);
1889*0a6a1f1dSLionel Sambuc 		    i = val - maxoffset;
1890*0a6a1f1dSLionel Sambuc 		}
1891*0a6a1f1dSLionel Sambuc 		else if (maxoffset > 0)
1892*0a6a1f1dSLionel Sambuc 		{
1893*0a6a1f1dSLionel Sambuc 		    i = offsets[val];
1894*0a6a1f1dSLionel Sambuc 		    if (!tag && !(tag = rhs[i]->tag) && havetags)
1895*0a6a1f1dSLionel Sambuc 			untyped_rhs(val, rhs[i]->name);
1896*0a6a1f1dSLionel Sambuc 		}
1897*0a6a1f1dSLionel Sambuc 		msprintf(c, "yystack.l_mark[%d]", i);
1898*0a6a1f1dSLionel Sambuc 		if (tag)
1899*0a6a1f1dSLionel Sambuc 		    msprintf(c, ".%s", tag);
1900*0a6a1f1dSLionel Sambuc 		else if (havetags)
1901*0a6a1f1dSLionel Sambuc 		    unknown_rhs(val);
1902*0a6a1f1dSLionel Sambuc 	    }
1903*0a6a1f1dSLionel Sambuc 	    else if (isalpha((unsigned char)*p) || *p == '_')
1904*0a6a1f1dSLionel Sambuc 	    {
1905*0a6a1f1dSLionel Sambuc 		char *arg;
1906*0a6a1f1dSLionel Sambuc 		if (!(p = parse_id(p, &arg)))
1907*0a6a1f1dSLionel Sambuc 		    dollar_error(rescan_lineno, NULL, NULL);
1908*0a6a1f1dSLionel Sambuc 		for (i = plhs[nrules]->args - 1; i >= 0; i--)
1909*0a6a1f1dSLionel Sambuc 		    if (arg == plhs[nrules]->argnames[i])
1910*0a6a1f1dSLionel Sambuc 			break;
1911*0a6a1f1dSLionel Sambuc 		if (i < 0)
1912*0a6a1f1dSLionel Sambuc 		    unknown_arg_warning(rescan_lineno, "$", arg, NULL, NULL);
1913*0a6a1f1dSLionel Sambuc 		else if (!tag)
1914*0a6a1f1dSLionel Sambuc 		    tag = plhs[nrules]->argtags[i];
1915*0a6a1f1dSLionel Sambuc 		msprintf(c, "yystack.l_mark[%d]", i - plhs[nrules]->args + 1
1916*0a6a1f1dSLionel Sambuc 			 - n);
1917*0a6a1f1dSLionel Sambuc 		if (tag)
1918*0a6a1f1dSLionel Sambuc 		    msprintf(c, ".%s", tag);
1919*0a6a1f1dSLionel Sambuc 		else if (havetags)
1920*0a6a1f1dSLionel Sambuc 		    untyped_arg_warning(rescan_lineno, "$", arg);
1921*0a6a1f1dSLionel Sambuc 	    }
1922*0a6a1f1dSLionel Sambuc 	    else
1923*0a6a1f1dSLionel Sambuc 		dollar_error(rescan_lineno, NULL, NULL);
1924*0a6a1f1dSLionel Sambuc 	}
1925*0a6a1f1dSLionel Sambuc 	else if (*p == '@')
1926*0a6a1f1dSLionel Sambuc 	{
1927*0a6a1f1dSLionel Sambuc 	    at_error(rescan_lineno, NULL, NULL);
1928*0a6a1f1dSLionel Sambuc 	}
1929*0a6a1f1dSLionel Sambuc 	else
1930*0a6a1f1dSLionel Sambuc 	{
1931*0a6a1f1dSLionel Sambuc 	    if (*p == '\n')
1932*0a6a1f1dSLionel Sambuc 		rescan_lineno++;
1933*0a6a1f1dSLionel Sambuc 	    mputc(c, *p++);
1934*0a6a1f1dSLionel Sambuc 	}
1935*0a6a1f1dSLionel Sambuc     }
1936*0a6a1f1dSLionel Sambuc     *theptr = p;
1937*0a6a1f1dSLionel Sambuc     if (maxoffset > 0)
1938*0a6a1f1dSLionel Sambuc 	FREE(offsets);
1939*0a6a1f1dSLionel Sambuc     return msdone(c);
1940*0a6a1f1dSLionel Sambuc }
1941*0a6a1f1dSLionel Sambuc 
1942*0a6a1f1dSLionel Sambuc #define ARG_CACHE_SIZE	1024
1943*0a6a1f1dSLionel Sambuc static struct arg_cache
1944*0a6a1f1dSLionel Sambuc {
1945*0a6a1f1dSLionel Sambuc     struct arg_cache *next;
1946*0a6a1f1dSLionel Sambuc     char *code;
1947*0a6a1f1dSLionel Sambuc     int rule;
1948*0a6a1f1dSLionel Sambuc }
1949*0a6a1f1dSLionel Sambuc  *arg_cache[ARG_CACHE_SIZE];
1950*0a6a1f1dSLionel Sambuc 
1951*0a6a1f1dSLionel Sambuc static int
lookup_arg_cache(char * code)1952*0a6a1f1dSLionel Sambuc lookup_arg_cache(char *code)
1953*0a6a1f1dSLionel Sambuc {
1954*0a6a1f1dSLionel Sambuc     struct arg_cache *entry;
1955*0a6a1f1dSLionel Sambuc 
1956*0a6a1f1dSLionel Sambuc     entry = arg_cache[strnshash(code) % ARG_CACHE_SIZE];
1957*0a6a1f1dSLionel Sambuc     while (entry)
1958*0a6a1f1dSLionel Sambuc     {
1959*0a6a1f1dSLionel Sambuc 	if (!strnscmp(entry->code, code))
1960*0a6a1f1dSLionel Sambuc 	    return entry->rule;
1961*0a6a1f1dSLionel Sambuc 	entry = entry->next;
1962*0a6a1f1dSLionel Sambuc     }
1963*0a6a1f1dSLionel Sambuc     return -1;
1964*0a6a1f1dSLionel Sambuc }
1965*0a6a1f1dSLionel Sambuc 
1966*0a6a1f1dSLionel Sambuc static void
insert_arg_cache(char * code,int rule)1967*0a6a1f1dSLionel Sambuc insert_arg_cache(char *code, int rule)
1968*0a6a1f1dSLionel Sambuc {
1969*0a6a1f1dSLionel Sambuc     struct arg_cache *entry = NEW(struct arg_cache);
1970*0a6a1f1dSLionel Sambuc     int i;
1971*0a6a1f1dSLionel Sambuc 
1972*0a6a1f1dSLionel Sambuc     NO_SPACE(entry);
1973*0a6a1f1dSLionel Sambuc     i = strnshash(code) % ARG_CACHE_SIZE;
1974*0a6a1f1dSLionel Sambuc     entry->code = code;
1975*0a6a1f1dSLionel Sambuc     entry->rule = rule;
1976*0a6a1f1dSLionel Sambuc     entry->next = arg_cache[i];
1977*0a6a1f1dSLionel Sambuc     arg_cache[i] = entry;
1978*0a6a1f1dSLionel Sambuc }
1979*0a6a1f1dSLionel Sambuc 
1980*0a6a1f1dSLionel Sambuc static void
clean_arg_cache(void)1981*0a6a1f1dSLionel Sambuc clean_arg_cache(void)
1982*0a6a1f1dSLionel Sambuc {
1983*0a6a1f1dSLionel Sambuc     struct arg_cache *e, *t;
1984*0a6a1f1dSLionel Sambuc     int i;
1985*0a6a1f1dSLionel Sambuc 
1986*0a6a1f1dSLionel Sambuc     for (i = 0; i < ARG_CACHE_SIZE; i++)
1987*0a6a1f1dSLionel Sambuc     {
1988*0a6a1f1dSLionel Sambuc 	for (e = arg_cache[i]; (t = e); e = e->next, FREE(t))
1989*0a6a1f1dSLionel Sambuc 	    free(e->code);
1990*0a6a1f1dSLionel Sambuc 	arg_cache[i] = NULL;
1991*0a6a1f1dSLionel Sambuc     }
1992*0a6a1f1dSLionel Sambuc }
1993*0a6a1f1dSLionel Sambuc #endif
1994*0a6a1f1dSLionel Sambuc 
19954a17663cSThomas Veerman static void
advance_to_start(void)19964a17663cSThomas Veerman advance_to_start(void)
19974a17663cSThomas Veerman {
19984a17663cSThomas Veerman     int c;
19994a17663cSThomas Veerman     bucket *bp;
20004a17663cSThomas Veerman     char *s_cptr;
20014a17663cSThomas Veerman     int s_lineno;
2002*0a6a1f1dSLionel Sambuc #if defined(YYBTYACC)
2003*0a6a1f1dSLionel Sambuc     char *args = NULL;
2004*0a6a1f1dSLionel Sambuc     int argslen = 0;
2005*0a6a1f1dSLionel Sambuc #endif
20064a17663cSThomas Veerman 
20074a17663cSThomas Veerman     for (;;)
20084a17663cSThomas Veerman     {
20094a17663cSThomas Veerman 	c = nextc();
20104a17663cSThomas Veerman 	if (c != '%')
20114a17663cSThomas Veerman 	    break;
20124a17663cSThomas Veerman 	s_cptr = cptr;
20134a17663cSThomas Veerman 	switch (keyword())
20144a17663cSThomas Veerman 	{
20154a17663cSThomas Veerman 	case MARK:
20164a17663cSThomas Veerman 	    no_grammar();
20174a17663cSThomas Veerman 
20184a17663cSThomas Veerman 	case TEXT:
20194a17663cSThomas Veerman 	    copy_text();
20204a17663cSThomas Veerman 	    break;
20214a17663cSThomas Veerman 
20224a17663cSThomas Veerman 	case START:
20234a17663cSThomas Veerman 	    declare_start();
20244a17663cSThomas Veerman 	    break;
20254a17663cSThomas Veerman 
20264a17663cSThomas Veerman 	default:
20274a17663cSThomas Veerman 	    syntax_error(lineno, line, s_cptr);
20284a17663cSThomas Veerman 	}
20294a17663cSThomas Veerman     }
20304a17663cSThomas Veerman 
20314a17663cSThomas Veerman     c = nextc();
20324a17663cSThomas Veerman     if (!isalpha(c) && c != '_' && c != '.' && c != '_')
20334a17663cSThomas Veerman 	syntax_error(lineno, line, cptr);
20344a17663cSThomas Veerman     bp = get_name();
20354a17663cSThomas Veerman     if (goal == 0)
20364a17663cSThomas Veerman     {
20374a17663cSThomas Veerman 	if (bp->class == TERM)
20384a17663cSThomas Veerman 	    terminal_start(bp->name);
20394a17663cSThomas Veerman 	goal = bp;
20404a17663cSThomas Veerman     }
20414a17663cSThomas Veerman 
20424a17663cSThomas Veerman     s_lineno = lineno;
20434a17663cSThomas Veerman     c = nextc();
20444a17663cSThomas Veerman     if (c == EOF)
20454a17663cSThomas Veerman 	unexpected_EOF();
2046*0a6a1f1dSLionel Sambuc     rescan_lineno = lineno;	/* line# for possible inherited args rescan */
2047*0a6a1f1dSLionel Sambuc #if defined(YYBTYACC)
2048*0a6a1f1dSLionel Sambuc     if (c == L_PAREN)
2049*0a6a1f1dSLionel Sambuc     {
2050*0a6a1f1dSLionel Sambuc 	++cptr;
2051*0a6a1f1dSLionel Sambuc 	args = copy_args(&argslen);
2052*0a6a1f1dSLionel Sambuc 	NO_SPACE(args);
2053*0a6a1f1dSLionel Sambuc 	c = nextc();
2054*0a6a1f1dSLionel Sambuc     }
2055*0a6a1f1dSLionel Sambuc #endif
20564a17663cSThomas Veerman     if (c != ':')
20574a17663cSThomas Veerman 	syntax_error(lineno, line, cptr);
20584a17663cSThomas Veerman     start_rule(bp, s_lineno);
2059*0a6a1f1dSLionel Sambuc #if defined(YYBTYACC)
2060*0a6a1f1dSLionel Sambuc     parse_arginfo(bp, args, argslen);
2061*0a6a1f1dSLionel Sambuc #endif
20624a17663cSThomas Veerman     ++cptr;
20634a17663cSThomas Veerman }
20644a17663cSThomas Veerman 
20654a17663cSThomas Veerman static void
start_rule(bucket * bp,int s_lineno)20664a17663cSThomas Veerman start_rule(bucket *bp, int s_lineno)
20674a17663cSThomas Veerman {
20684a17663cSThomas Veerman     if (bp->class == TERM)
20694a17663cSThomas Veerman 	terminal_lhs(s_lineno);
20704a17663cSThomas Veerman     bp->class = NONTERM;
2071*0a6a1f1dSLionel Sambuc     if (!bp->index)
2072*0a6a1f1dSLionel Sambuc 	bp->index = nrules;
20734a17663cSThomas Veerman     if (nrules >= maxrules)
20744a17663cSThomas Veerman 	expand_rules();
20754a17663cSThomas Veerman     plhs[nrules] = bp;
20764a17663cSThomas Veerman     rprec[nrules] = UNDEFINED;
20774a17663cSThomas Veerman     rassoc[nrules] = TOKEN;
20784a17663cSThomas Veerman }
20794a17663cSThomas Veerman 
20804a17663cSThomas Veerman static void
end_rule(void)20814a17663cSThomas Veerman end_rule(void)
20824a17663cSThomas Veerman {
20834a17663cSThomas Veerman     int i;
20844a17663cSThomas Veerman 
20854a17663cSThomas Veerman     if (!last_was_action && plhs[nrules]->tag)
20864a17663cSThomas Veerman     {
20874a17663cSThomas Veerman 	if (pitem[nitems - 1])
20884a17663cSThomas Veerman 	{
20894a17663cSThomas Veerman 	    for (i = nitems - 1; (i > 0) && pitem[i]; --i)
20904a17663cSThomas Veerman 		continue;
20914a17663cSThomas Veerman 	    if (pitem[i + 1] == 0 || pitem[i + 1]->tag != plhs[nrules]->tag)
20924a17663cSThomas Veerman 		default_action_warning();
20934a17663cSThomas Veerman 	}
20944a17663cSThomas Veerman 	else
20954a17663cSThomas Veerman 	{
20964a17663cSThomas Veerman 	    default_action_warning();
20974a17663cSThomas Veerman 	}
20984a17663cSThomas Veerman     }
20994a17663cSThomas Veerman 
21004a17663cSThomas Veerman     last_was_action = 0;
21014a17663cSThomas Veerman     if (nitems >= maxitems)
21024a17663cSThomas Veerman 	expand_items();
21034a17663cSThomas Veerman     pitem[nitems] = 0;
21044a17663cSThomas Veerman     ++nitems;
21054a17663cSThomas Veerman     ++nrules;
21064a17663cSThomas Veerman }
21074a17663cSThomas Veerman 
21084a17663cSThomas Veerman static void
insert_empty_rule(void)21094a17663cSThomas Veerman insert_empty_rule(void)
21104a17663cSThomas Veerman {
21114a17663cSThomas Veerman     bucket *bp, **bpp;
21124a17663cSThomas Veerman 
21134a17663cSThomas Veerman     assert(cache);
21144a17663cSThomas Veerman     sprintf(cache, "$$%d", ++gensym);
21154a17663cSThomas Veerman     bp = make_bucket(cache);
21164a17663cSThomas Veerman     last_symbol->next = bp;
21174a17663cSThomas Veerman     last_symbol = bp;
21184a17663cSThomas Veerman     bp->tag = plhs[nrules]->tag;
2119*0a6a1f1dSLionel Sambuc     bp->class = ACTION;
2120*0a6a1f1dSLionel Sambuc #if defined(YYBTYACC)
2121*0a6a1f1dSLionel Sambuc     bp->args = 0;
2122*0a6a1f1dSLionel Sambuc #endif
21234a17663cSThomas Veerman 
2124*0a6a1f1dSLionel Sambuc     nitems = (Value_t) (nitems + 2);
2125*0a6a1f1dSLionel Sambuc     if (nitems > maxitems)
21264a17663cSThomas Veerman 	expand_items();
21274a17663cSThomas Veerman     bpp = pitem + nitems - 1;
21284a17663cSThomas Veerman     *bpp-- = bp;
21294a17663cSThomas Veerman     while ((bpp[0] = bpp[-1]) != 0)
21304a17663cSThomas Veerman 	--bpp;
21314a17663cSThomas Veerman 
21324a17663cSThomas Veerman     if (++nrules >= maxrules)
21334a17663cSThomas Veerman 	expand_rules();
21344a17663cSThomas Veerman     plhs[nrules] = plhs[nrules - 1];
21354a17663cSThomas Veerman     plhs[nrules - 1] = bp;
21364a17663cSThomas Veerman     rprec[nrules] = rprec[nrules - 1];
21374a17663cSThomas Veerman     rprec[nrules - 1] = 0;
21384a17663cSThomas Veerman     rassoc[nrules] = rassoc[nrules - 1];
21394a17663cSThomas Veerman     rassoc[nrules - 1] = TOKEN;
21404a17663cSThomas Veerman }
21414a17663cSThomas Veerman 
2142*0a6a1f1dSLionel Sambuc #if defined(YYBTYACC)
2143*0a6a1f1dSLionel Sambuc static char *
insert_arg_rule(char * arg,char * tag)2144*0a6a1f1dSLionel Sambuc insert_arg_rule(char *arg, char *tag)
2145*0a6a1f1dSLionel Sambuc {
2146*0a6a1f1dSLionel Sambuc     int line_number = rescan_lineno;
2147*0a6a1f1dSLionel Sambuc     char *code = compile_arg(&arg, tag);
2148*0a6a1f1dSLionel Sambuc     int rule = lookup_arg_cache(code);
2149*0a6a1f1dSLionel Sambuc     FILE *f = action_file;
2150*0a6a1f1dSLionel Sambuc 
2151*0a6a1f1dSLionel Sambuc     if (rule < 0)
2152*0a6a1f1dSLionel Sambuc     {
2153*0a6a1f1dSLionel Sambuc 	rule = nrules;
2154*0a6a1f1dSLionel Sambuc 	insert_arg_cache(code, rule);
2155*0a6a1f1dSLionel Sambuc 	fprintf(f, "case %d:\n", rule - 2);
2156*0a6a1f1dSLionel Sambuc 	if (!lflag)
2157*0a6a1f1dSLionel Sambuc 	    fprintf(f, line_format, line_number, input_file_name);
2158*0a6a1f1dSLionel Sambuc 	fprintf(f, "%s;\n", code);
2159*0a6a1f1dSLionel Sambuc 	fprintf(f, "break;\n");
2160*0a6a1f1dSLionel Sambuc 	insert_empty_rule();
2161*0a6a1f1dSLionel Sambuc 	plhs[rule]->tag = tag;
2162*0a6a1f1dSLionel Sambuc 	plhs[rule]->class = ARGUMENT;
2163*0a6a1f1dSLionel Sambuc     }
2164*0a6a1f1dSLionel Sambuc     else
2165*0a6a1f1dSLionel Sambuc     {
2166*0a6a1f1dSLionel Sambuc 	if (++nitems > maxitems)
2167*0a6a1f1dSLionel Sambuc 	    expand_items();
2168*0a6a1f1dSLionel Sambuc 	pitem[nitems - 1] = plhs[rule];
2169*0a6a1f1dSLionel Sambuc 	free(code);
2170*0a6a1f1dSLionel Sambuc     }
2171*0a6a1f1dSLionel Sambuc     return arg + 1;
2172*0a6a1f1dSLionel Sambuc }
2173*0a6a1f1dSLionel Sambuc #endif
2174*0a6a1f1dSLionel Sambuc 
21754a17663cSThomas Veerman static void
add_symbol(void)21764a17663cSThomas Veerman add_symbol(void)
21774a17663cSThomas Veerman {
21784a17663cSThomas Veerman     int c;
21794a17663cSThomas Veerman     bucket *bp;
21804a17663cSThomas Veerman     int s_lineno = lineno;
2181*0a6a1f1dSLionel Sambuc #if defined(YYBTYACC)
2182*0a6a1f1dSLionel Sambuc     char *args = NULL;
2183*0a6a1f1dSLionel Sambuc     int argslen = 0;
2184*0a6a1f1dSLionel Sambuc #endif
21854a17663cSThomas Veerman 
21864a17663cSThomas Veerman     c = *cptr;
21874a17663cSThomas Veerman     if (c == '\'' || c == '"')
21884a17663cSThomas Veerman 	bp = get_literal();
21894a17663cSThomas Veerman     else
21904a17663cSThomas Veerman 	bp = get_name();
21914a17663cSThomas Veerman 
21924a17663cSThomas Veerman     c = nextc();
2193*0a6a1f1dSLionel Sambuc     rescan_lineno = lineno;	/* line# for possible inherited args rescan */
2194*0a6a1f1dSLionel Sambuc #if defined(YYBTYACC)
2195*0a6a1f1dSLionel Sambuc     if (c == L_PAREN)
2196*0a6a1f1dSLionel Sambuc     {
2197*0a6a1f1dSLionel Sambuc 	++cptr;
2198*0a6a1f1dSLionel Sambuc 	args = copy_args(&argslen);
2199*0a6a1f1dSLionel Sambuc 	NO_SPACE(args);
2200*0a6a1f1dSLionel Sambuc 	c = nextc();
2201*0a6a1f1dSLionel Sambuc     }
2202*0a6a1f1dSLionel Sambuc #endif
22034a17663cSThomas Veerman     if (c == ':')
22044a17663cSThomas Veerman     {
22054a17663cSThomas Veerman 	end_rule();
22064a17663cSThomas Veerman 	start_rule(bp, s_lineno);
2207*0a6a1f1dSLionel Sambuc #if defined(YYBTYACC)
2208*0a6a1f1dSLionel Sambuc 	parse_arginfo(bp, args, argslen);
2209*0a6a1f1dSLionel Sambuc #endif
22104a17663cSThomas Veerman 	++cptr;
22114a17663cSThomas Veerman 	return;
22124a17663cSThomas Veerman     }
22134a17663cSThomas Veerman 
22144a17663cSThomas Veerman     if (last_was_action)
22154a17663cSThomas Veerman 	insert_empty_rule();
22164a17663cSThomas Veerman     last_was_action = 0;
22174a17663cSThomas Veerman 
2218*0a6a1f1dSLionel Sambuc #if defined(YYBTYACC)
2219*0a6a1f1dSLionel Sambuc     if (bp->args < 0)
2220*0a6a1f1dSLionel Sambuc 	bp->args = argslen;
2221*0a6a1f1dSLionel Sambuc     if (argslen == 0 && bp->args > 0 && pitem[nitems - 1] == NULL)
2222*0a6a1f1dSLionel Sambuc     {
2223*0a6a1f1dSLionel Sambuc 	int i;
2224*0a6a1f1dSLionel Sambuc 	if (plhs[nrules]->args != bp->args)
2225*0a6a1f1dSLionel Sambuc 	    wrong_number_args_warning("default ", bp->name);
2226*0a6a1f1dSLionel Sambuc 	for (i = bp->args - 1; i >= 0; i--)
2227*0a6a1f1dSLionel Sambuc 	    if (plhs[nrules]->argtags[i] != bp->argtags[i])
2228*0a6a1f1dSLionel Sambuc 		wrong_type_for_arg_warning(i + 1, bp->name);
2229*0a6a1f1dSLionel Sambuc     }
2230*0a6a1f1dSLionel Sambuc     else if (bp->args != argslen)
2231*0a6a1f1dSLionel Sambuc 	wrong_number_args_warning("", bp->name);
2232*0a6a1f1dSLionel Sambuc     if (bp->args > 0 && argslen > 0)
2233*0a6a1f1dSLionel Sambuc     {
2234*0a6a1f1dSLionel Sambuc 	char *ap;
2235*0a6a1f1dSLionel Sambuc 	int i;
2236*0a6a1f1dSLionel Sambuc 	for (ap = args, i = 0; i < argslen; i++)
2237*0a6a1f1dSLionel Sambuc 	    ap = insert_arg_rule(ap, bp->argtags[i]);
2238*0a6a1f1dSLionel Sambuc 	free(args);
2239*0a6a1f1dSLionel Sambuc     }
2240*0a6a1f1dSLionel Sambuc #endif /* defined(YYBTYACC) */
2241*0a6a1f1dSLionel Sambuc 
22424a17663cSThomas Veerman     if (++nitems > maxitems)
22434a17663cSThomas Veerman 	expand_items();
22444a17663cSThomas Veerman     pitem[nitems - 1] = bp;
22454a17663cSThomas Veerman }
22464a17663cSThomas Veerman 
22474a17663cSThomas Veerman static void
copy_action(void)22484a17663cSThomas Veerman copy_action(void)
22494a17663cSThomas Veerman {
22504a17663cSThomas Veerman     int c;
2251*0a6a1f1dSLionel Sambuc     int i, j, n;
22524a17663cSThomas Veerman     int depth;
2253*0a6a1f1dSLionel Sambuc #if defined(YYBTYACC)
2254*0a6a1f1dSLionel Sambuc     int trialaction = 0;
2255*0a6a1f1dSLionel Sambuc     int haveyyval = 0;
2256*0a6a1f1dSLionel Sambuc #endif
22574a17663cSThomas Veerman     char *tag;
22584a17663cSThomas Veerman     FILE *f = action_file;
2259*0a6a1f1dSLionel Sambuc     struct ainfo a;
2260*0a6a1f1dSLionel Sambuc     Value_t *offsets = NULL, maxoffset;
2261*0a6a1f1dSLionel Sambuc     bucket **rhs;
2262*0a6a1f1dSLionel Sambuc 
2263*0a6a1f1dSLionel Sambuc     a.a_lineno = lineno;
2264*0a6a1f1dSLionel Sambuc     a.a_line = dup_line();
2265*0a6a1f1dSLionel Sambuc     a.a_cptr = a.a_line + (cptr - line);
22664a17663cSThomas Veerman 
22674a17663cSThomas Veerman     if (last_was_action)
22684a17663cSThomas Veerman 	insert_empty_rule();
22694a17663cSThomas Veerman     last_was_action = 1;
22704a17663cSThomas Veerman 
22714a17663cSThomas Veerman     fprintf(f, "case %d:\n", nrules - 2);
2272*0a6a1f1dSLionel Sambuc #if defined(YYBTYACC)
2273*0a6a1f1dSLionel Sambuc     if (backtrack)
2274*0a6a1f1dSLionel Sambuc     {
2275*0a6a1f1dSLionel Sambuc 	if (*cptr != L_BRAC)
2276*0a6a1f1dSLionel Sambuc 	    fprintf(f, "  if (!yytrial)\n");
2277*0a6a1f1dSLionel Sambuc 	else
2278*0a6a1f1dSLionel Sambuc 	    trialaction = 1;
2279*0a6a1f1dSLionel Sambuc     }
2280*0a6a1f1dSLionel Sambuc #endif
22814a17663cSThomas Veerman     if (!lflag)
22824a17663cSThomas Veerman 	fprintf(f, line_format, lineno, input_file_name);
22834a17663cSThomas Veerman     if (*cptr == '=')
22844a17663cSThomas Veerman 	++cptr;
22854a17663cSThomas Veerman 
22864a17663cSThomas Veerman     /* avoid putting curly-braces in first column, to ease editing */
22874a17663cSThomas Veerman     if (*after_blanks(cptr) == L_CURL)
22884a17663cSThomas Veerman     {
22894a17663cSThomas Veerman 	putc('\t', f);
22904a17663cSThomas Veerman 	cptr = after_blanks(cptr);
22914a17663cSThomas Veerman     }
22924a17663cSThomas Veerman 
2293*0a6a1f1dSLionel Sambuc     maxoffset = 0;
22944a17663cSThomas Veerman     n = 0;
22954a17663cSThomas Veerman     for (i = nitems - 1; pitem[i]; --i)
2296*0a6a1f1dSLionel Sambuc     {
22974a17663cSThomas Veerman 	++n;
2298*0a6a1f1dSLionel Sambuc 	if (pitem[i]->class != ARGUMENT)
2299*0a6a1f1dSLionel Sambuc 	    maxoffset++;
2300*0a6a1f1dSLionel Sambuc     }
2301*0a6a1f1dSLionel Sambuc     if (maxoffset > 0)
2302*0a6a1f1dSLionel Sambuc     {
2303*0a6a1f1dSLionel Sambuc 	offsets = TMALLOC(Value_t, maxoffset + 1);
2304*0a6a1f1dSLionel Sambuc 	NO_SPACE(offsets);
2305*0a6a1f1dSLionel Sambuc 
2306*0a6a1f1dSLionel Sambuc 	for (j = 0, i++; i < nitems; i++)
2307*0a6a1f1dSLionel Sambuc 	{
2308*0a6a1f1dSLionel Sambuc 	    if (pitem[i]->class != ARGUMENT)
2309*0a6a1f1dSLionel Sambuc 	    {
2310*0a6a1f1dSLionel Sambuc 		offsets[++j] = (Value_t) (i - nitems + 1);
2311*0a6a1f1dSLionel Sambuc 	    }
2312*0a6a1f1dSLionel Sambuc 	}
2313*0a6a1f1dSLionel Sambuc     }
2314*0a6a1f1dSLionel Sambuc     rhs = pitem + nitems - 1;
23154a17663cSThomas Veerman 
23164a17663cSThomas Veerman     depth = 0;
23174a17663cSThomas Veerman   loop:
23184a17663cSThomas Veerman     c = *cptr;
23194a17663cSThomas Veerman     if (c == '$')
23204a17663cSThomas Veerman     {
23214a17663cSThomas Veerman 	if (cptr[1] == '<')
23224a17663cSThomas Veerman 	{
23234a17663cSThomas Veerman 	    int d_lineno = lineno;
23244a17663cSThomas Veerman 	    char *d_line = dup_line();
23254a17663cSThomas Veerman 	    char *d_cptr = d_line + (cptr - line);
23264a17663cSThomas Veerman 
23274a17663cSThomas Veerman 	    ++cptr;
23284a17663cSThomas Veerman 	    tag = get_tag();
23294a17663cSThomas Veerman 	    c = *cptr;
23304a17663cSThomas Veerman 	    if (c == '$')
23314a17663cSThomas Veerman 	    {
23324a17663cSThomas Veerman 		fprintf(f, "yyval.%s", tag);
23334a17663cSThomas Veerman 		++cptr;
23344a17663cSThomas Veerman 		FREE(d_line);
23354a17663cSThomas Veerman 		goto loop;
23364a17663cSThomas Veerman 	    }
23374a17663cSThomas Veerman 	    else if (isdigit(c))
23384a17663cSThomas Veerman 	    {
23394a17663cSThomas Veerman 		i = get_number();
2340*0a6a1f1dSLionel Sambuc 		if (i == 0)
2341*0a6a1f1dSLionel Sambuc 		    fprintf(f, "yystack.l_mark[%d].%s", -n, tag);
2342*0a6a1f1dSLionel Sambuc 		else if (i > maxoffset)
2343*0a6a1f1dSLionel Sambuc 		{
23444a17663cSThomas Veerman 		    dollar_warning(d_lineno, i);
2345*0a6a1f1dSLionel Sambuc 		    fprintf(f, "yystack.l_mark[%d].%s", i - maxoffset, tag);
2346*0a6a1f1dSLionel Sambuc 		}
2347*0a6a1f1dSLionel Sambuc 		else if (offsets)
2348*0a6a1f1dSLionel Sambuc 		    fprintf(f, "yystack.l_mark[%d].%s", offsets[i], tag);
23494a17663cSThomas Veerman 		FREE(d_line);
23504a17663cSThomas Veerman 		goto loop;
23514a17663cSThomas Veerman 	    }
23524a17663cSThomas Veerman 	    else if (c == '-' && isdigit(UCH(cptr[1])))
23534a17663cSThomas Veerman 	    {
23544a17663cSThomas Veerman 		++cptr;
23554a17663cSThomas Veerman 		i = -get_number() - n;
23564a17663cSThomas Veerman 		fprintf(f, "yystack.l_mark[%d].%s", i, tag);
23574a17663cSThomas Veerman 		FREE(d_line);
23584a17663cSThomas Veerman 		goto loop;
23594a17663cSThomas Veerman 	    }
2360*0a6a1f1dSLionel Sambuc #if defined(YYBTYACC)
2361*0a6a1f1dSLionel Sambuc 	    else if (isalpha(c) || c == '_')
2362*0a6a1f1dSLionel Sambuc 	    {
2363*0a6a1f1dSLionel Sambuc 		char *arg = scan_id();
2364*0a6a1f1dSLionel Sambuc 		for (i = plhs[nrules]->args - 1; i >= 0; i--)
2365*0a6a1f1dSLionel Sambuc 		    if (arg == plhs[nrules]->argnames[i])
2366*0a6a1f1dSLionel Sambuc 			break;
2367*0a6a1f1dSLionel Sambuc 		if (i < 0)
2368*0a6a1f1dSLionel Sambuc 		    unknown_arg_warning(d_lineno, "$", arg, d_line, d_cptr);
2369*0a6a1f1dSLionel Sambuc 		fprintf(f, "yystack.l_mark[%d].%s", i - plhs[nrules]->args +
2370*0a6a1f1dSLionel Sambuc 			1 - n, tag);
2371*0a6a1f1dSLionel Sambuc 		FREE(d_line);
2372*0a6a1f1dSLionel Sambuc 		goto loop;
2373*0a6a1f1dSLionel Sambuc 	    }
2374*0a6a1f1dSLionel Sambuc #endif
23754a17663cSThomas Veerman 	    else
23764a17663cSThomas Veerman 		dollar_error(d_lineno, d_line, d_cptr);
23774a17663cSThomas Veerman 	}
23784a17663cSThomas Veerman 	else if (cptr[1] == '$')
23794a17663cSThomas Veerman 	{
2380*0a6a1f1dSLionel Sambuc 	    if (havetags)
23814a17663cSThomas Veerman 	    {
23824a17663cSThomas Veerman 		tag = plhs[nrules]->tag;
23834a17663cSThomas Veerman 		if (tag == 0)
23844a17663cSThomas Veerman 		    untyped_lhs();
23854a17663cSThomas Veerman 		fprintf(f, "yyval.%s", tag);
23864a17663cSThomas Veerman 	    }
23874a17663cSThomas Veerman 	    else
23884a17663cSThomas Veerman 		fprintf(f, "yyval");
23894a17663cSThomas Veerman 	    cptr += 2;
2390*0a6a1f1dSLionel Sambuc #if defined(YYBTYACC)
2391*0a6a1f1dSLionel Sambuc 	    haveyyval = 1;
2392*0a6a1f1dSLionel Sambuc #endif
23934a17663cSThomas Veerman 	    goto loop;
23944a17663cSThomas Veerman 	}
23954a17663cSThomas Veerman 	else if (isdigit(UCH(cptr[1])))
23964a17663cSThomas Veerman 	{
23974a17663cSThomas Veerman 	    ++cptr;
23984a17663cSThomas Veerman 	    i = get_number();
2399*0a6a1f1dSLionel Sambuc 	    if (havetags && offsets)
24004a17663cSThomas Veerman 	    {
2401*0a6a1f1dSLionel Sambuc 		if (i <= 0 || i > maxoffset)
24024a17663cSThomas Veerman 		    unknown_rhs(i);
2403*0a6a1f1dSLionel Sambuc 		tag = rhs[offsets[i]]->tag;
24044a17663cSThomas Veerman 		if (tag == 0)
2405*0a6a1f1dSLionel Sambuc 		    untyped_rhs(i, rhs[offsets[i]]->name);
2406*0a6a1f1dSLionel Sambuc 		fprintf(f, "yystack.l_mark[%d].%s", offsets[i], tag);
24074a17663cSThomas Veerman 	    }
24084a17663cSThomas Veerman 	    else
24094a17663cSThomas Veerman 	    {
2410*0a6a1f1dSLionel Sambuc 		if (i == 0)
2411*0a6a1f1dSLionel Sambuc 		    fprintf(f, "yystack.l_mark[%d]", -n);
2412*0a6a1f1dSLionel Sambuc 		else if (i > maxoffset)
2413*0a6a1f1dSLionel Sambuc 		{
24144a17663cSThomas Veerman 		    dollar_warning(lineno, i);
2415*0a6a1f1dSLionel Sambuc 		    fprintf(f, "yystack.l_mark[%d]", i - maxoffset);
2416*0a6a1f1dSLionel Sambuc 		}
2417*0a6a1f1dSLionel Sambuc 		else if (offsets)
2418*0a6a1f1dSLionel Sambuc 		    fprintf(f, "yystack.l_mark[%d]", offsets[i]);
24194a17663cSThomas Veerman 	    }
24204a17663cSThomas Veerman 	    goto loop;
24214a17663cSThomas Veerman 	}
24224a17663cSThomas Veerman 	else if (cptr[1] == '-')
24234a17663cSThomas Veerman 	{
24244a17663cSThomas Veerman 	    cptr += 2;
24254a17663cSThomas Veerman 	    i = get_number();
2426*0a6a1f1dSLionel Sambuc 	    if (havetags)
24274a17663cSThomas Veerman 		unknown_rhs(-i);
24284a17663cSThomas Veerman 	    fprintf(f, "yystack.l_mark[%d]", -i - n);
24294a17663cSThomas Veerman 	    goto loop;
24304a17663cSThomas Veerman 	}
2431*0a6a1f1dSLionel Sambuc #if defined(YYBTYACC)
2432*0a6a1f1dSLionel Sambuc 	else if (isalpha((unsigned char)cptr[1]) || cptr[1] == '_')
2433*0a6a1f1dSLionel Sambuc 	{
2434*0a6a1f1dSLionel Sambuc 	    char *arg;
2435*0a6a1f1dSLionel Sambuc 	    ++cptr;
2436*0a6a1f1dSLionel Sambuc 	    arg = scan_id();
2437*0a6a1f1dSLionel Sambuc 	    for (i = plhs[nrules]->args - 1; i >= 0; i--)
2438*0a6a1f1dSLionel Sambuc 		if (arg == plhs[nrules]->argnames[i])
2439*0a6a1f1dSLionel Sambuc 		    break;
2440*0a6a1f1dSLionel Sambuc 	    if (i < 0)
2441*0a6a1f1dSLionel Sambuc 		unknown_arg_warning(lineno, "$", arg, line, cptr);
2442*0a6a1f1dSLionel Sambuc 	    tag = (i < 0 ? NULL : plhs[nrules]->argtags[i]);
2443*0a6a1f1dSLionel Sambuc 	    fprintf(f, "yystack.l_mark[%d]", i - plhs[nrules]->args + 1 - n);
2444*0a6a1f1dSLionel Sambuc 	    if (tag)
2445*0a6a1f1dSLionel Sambuc 		fprintf(f, ".%s", tag);
2446*0a6a1f1dSLionel Sambuc 	    else if (havetags)
2447*0a6a1f1dSLionel Sambuc 		untyped_arg_warning(lineno, "$", arg);
2448*0a6a1f1dSLionel Sambuc 	    goto loop;
24494a17663cSThomas Veerman 	}
2450*0a6a1f1dSLionel Sambuc #endif
2451*0a6a1f1dSLionel Sambuc     }
2452*0a6a1f1dSLionel Sambuc #if defined(YYBTYACC)
2453*0a6a1f1dSLionel Sambuc     if (c == '@')
2454*0a6a1f1dSLionel Sambuc     {
2455*0a6a1f1dSLionel Sambuc 	if (!locations)
2456*0a6a1f1dSLionel Sambuc 	{
2457*0a6a1f1dSLionel Sambuc 	    int l_lineno = lineno;
2458*0a6a1f1dSLionel Sambuc 	    char *l_line = dup_line();
2459*0a6a1f1dSLionel Sambuc 	    char *l_cptr = l_line + (cptr - line);
2460*0a6a1f1dSLionel Sambuc 	    syntax_error(l_lineno, l_line, l_cptr);
2461*0a6a1f1dSLionel Sambuc 	}
2462*0a6a1f1dSLionel Sambuc 	if (cptr[1] == '$')
2463*0a6a1f1dSLionel Sambuc 	{
2464*0a6a1f1dSLionel Sambuc 	    fprintf(f, "yyloc");
2465*0a6a1f1dSLionel Sambuc 	    cptr += 2;
2466*0a6a1f1dSLionel Sambuc 	    goto loop;
2467*0a6a1f1dSLionel Sambuc 	}
2468*0a6a1f1dSLionel Sambuc 	else if (isdigit(UCH(cptr[1])))
2469*0a6a1f1dSLionel Sambuc 	{
2470*0a6a1f1dSLionel Sambuc 	    ++cptr;
2471*0a6a1f1dSLionel Sambuc 	    i = get_number();
2472*0a6a1f1dSLionel Sambuc 	    if (i == 0)
2473*0a6a1f1dSLionel Sambuc 		fprintf(f, "yystack.p_mark[%d]", -n);
2474*0a6a1f1dSLionel Sambuc 	    else if (i > maxoffset)
2475*0a6a1f1dSLionel Sambuc 	    {
2476*0a6a1f1dSLionel Sambuc 		at_warning(lineno, i);
2477*0a6a1f1dSLionel Sambuc 		fprintf(f, "yystack.p_mark[%d]", i - maxoffset);
2478*0a6a1f1dSLionel Sambuc 	    }
2479*0a6a1f1dSLionel Sambuc 	    else if (offsets)
2480*0a6a1f1dSLionel Sambuc 		fprintf(f, "yystack.p_mark[%d]", offsets[i]);
2481*0a6a1f1dSLionel Sambuc 	    goto loop;
2482*0a6a1f1dSLionel Sambuc 	}
2483*0a6a1f1dSLionel Sambuc     }
2484*0a6a1f1dSLionel Sambuc #endif
24854a17663cSThomas Veerman     if (isalpha(c) || c == '_' || c == '$')
24864a17663cSThomas Veerman     {
24874a17663cSThomas Veerman 	do
24884a17663cSThomas Veerman 	{
24894a17663cSThomas Veerman 	    putc(c, f);
24904a17663cSThomas Veerman 	    c = *++cptr;
24914a17663cSThomas Veerman 	}
24924a17663cSThomas Veerman 	while (isalnum(c) || c == '_' || c == '$');
24934a17663cSThomas Veerman 	goto loop;
24944a17663cSThomas Veerman     }
24954a17663cSThomas Veerman     ++cptr;
2496*0a6a1f1dSLionel Sambuc #if defined(YYBTYACC)
2497*0a6a1f1dSLionel Sambuc     if (backtrack)
2498*0a6a1f1dSLionel Sambuc     {
2499*0a6a1f1dSLionel Sambuc 	if (trialaction && c == L_BRAC && depth == 0)
2500*0a6a1f1dSLionel Sambuc 	{
2501*0a6a1f1dSLionel Sambuc 	    ++depth;
2502*0a6a1f1dSLionel Sambuc 	    putc(L_CURL, f);
2503*0a6a1f1dSLionel Sambuc 	    goto loop;
2504*0a6a1f1dSLionel Sambuc 	}
2505*0a6a1f1dSLionel Sambuc 	if (trialaction && c == R_BRAC && depth == 1)
2506*0a6a1f1dSLionel Sambuc 	{
2507*0a6a1f1dSLionel Sambuc 	    --depth;
2508*0a6a1f1dSLionel Sambuc 	    putc(R_CURL, f);
2509*0a6a1f1dSLionel Sambuc 	    c = nextc();
2510*0a6a1f1dSLionel Sambuc 	    if (c == L_BRAC && !haveyyval)
2511*0a6a1f1dSLionel Sambuc 	    {
2512*0a6a1f1dSLionel Sambuc 		goto loop;
2513*0a6a1f1dSLionel Sambuc 	    }
2514*0a6a1f1dSLionel Sambuc 	    if (c == L_CURL && !haveyyval)
2515*0a6a1f1dSLionel Sambuc 	    {
2516*0a6a1f1dSLionel Sambuc 		fprintf(f, "  if (!yytrial)\n");
2517*0a6a1f1dSLionel Sambuc 		if (!lflag)
2518*0a6a1f1dSLionel Sambuc 		    fprintf(f, line_format, lineno, input_file_name);
2519*0a6a1f1dSLionel Sambuc 		trialaction = 0;
2520*0a6a1f1dSLionel Sambuc 		goto loop;
2521*0a6a1f1dSLionel Sambuc 	    }
2522*0a6a1f1dSLionel Sambuc 	    fprintf(f, "\nbreak;\n");
2523*0a6a1f1dSLionel Sambuc 	    FREE(a.a_line);
2524*0a6a1f1dSLionel Sambuc 	    if (maxoffset > 0)
2525*0a6a1f1dSLionel Sambuc 		FREE(offsets);
2526*0a6a1f1dSLionel Sambuc 	    return;
2527*0a6a1f1dSLionel Sambuc 	}
2528*0a6a1f1dSLionel Sambuc     }
2529*0a6a1f1dSLionel Sambuc #endif
2530*0a6a1f1dSLionel Sambuc     putc(c, f);
25314a17663cSThomas Veerman     switch (c)
25324a17663cSThomas Veerman     {
25334a17663cSThomas Veerman     case '\n':
25344a17663cSThomas Veerman 	get_line();
25354a17663cSThomas Veerman 	if (line)
25364a17663cSThomas Veerman 	    goto loop;
2537*0a6a1f1dSLionel Sambuc 	unterminated_action(&a);
25384a17663cSThomas Veerman 
25394a17663cSThomas Veerman     case ';':
25404a17663cSThomas Veerman 	if (depth > 0)
25414a17663cSThomas Veerman 	    goto loop;
25424a17663cSThomas Veerman 	fprintf(f, "\nbreak;\n");
2543*0a6a1f1dSLionel Sambuc 	free(a.a_line);
2544*0a6a1f1dSLionel Sambuc 	if (maxoffset > 0)
2545*0a6a1f1dSLionel Sambuc 	    FREE(offsets);
25464a17663cSThomas Veerman 	return;
25474a17663cSThomas Veerman 
2548*0a6a1f1dSLionel Sambuc #if defined(YYBTYACC)
2549*0a6a1f1dSLionel Sambuc     case L_BRAC:
2550*0a6a1f1dSLionel Sambuc 	if (backtrack)
2551*0a6a1f1dSLionel Sambuc 	    ++depth;
2552*0a6a1f1dSLionel Sambuc 	goto loop;
2553*0a6a1f1dSLionel Sambuc 
2554*0a6a1f1dSLionel Sambuc     case R_BRAC:
2555*0a6a1f1dSLionel Sambuc 	if (backtrack)
2556*0a6a1f1dSLionel Sambuc 	    --depth;
2557*0a6a1f1dSLionel Sambuc 	goto loop;
2558*0a6a1f1dSLionel Sambuc #endif
2559*0a6a1f1dSLionel Sambuc 
25604a17663cSThomas Veerman     case L_CURL:
25614a17663cSThomas Veerman 	++depth;
25624a17663cSThomas Veerman 	goto loop;
25634a17663cSThomas Veerman 
25644a17663cSThomas Veerman     case R_CURL:
25654a17663cSThomas Veerman 	if (--depth > 0)
25664a17663cSThomas Veerman 	    goto loop;
2567*0a6a1f1dSLionel Sambuc #if defined(YYBTYACC)
2568*0a6a1f1dSLionel Sambuc 	if (backtrack)
2569*0a6a1f1dSLionel Sambuc 	{
2570*0a6a1f1dSLionel Sambuc 	    c = nextc();
2571*0a6a1f1dSLionel Sambuc 	    if (c == L_BRAC && !haveyyval)
2572*0a6a1f1dSLionel Sambuc 	    {
2573*0a6a1f1dSLionel Sambuc 		trialaction = 1;
2574*0a6a1f1dSLionel Sambuc 		goto loop;
2575*0a6a1f1dSLionel Sambuc 	    }
2576*0a6a1f1dSLionel Sambuc 	    if (c == L_CURL && !haveyyval)
2577*0a6a1f1dSLionel Sambuc 	    {
2578*0a6a1f1dSLionel Sambuc 		fprintf(f, "  if (!yytrial)\n");
2579*0a6a1f1dSLionel Sambuc 		if (!lflag)
2580*0a6a1f1dSLionel Sambuc 		    fprintf(f, line_format, lineno, input_file_name);
2581*0a6a1f1dSLionel Sambuc 		goto loop;
2582*0a6a1f1dSLionel Sambuc 	    }
2583*0a6a1f1dSLionel Sambuc 	}
2584*0a6a1f1dSLionel Sambuc #endif
25854a17663cSThomas Veerman 	fprintf(f, "\nbreak;\n");
2586*0a6a1f1dSLionel Sambuc 	free(a.a_line);
2587*0a6a1f1dSLionel Sambuc 	if (maxoffset > 0)
2588*0a6a1f1dSLionel Sambuc 	    FREE(offsets);
25894a17663cSThomas Veerman 	return;
25904a17663cSThomas Veerman 
25914a17663cSThomas Veerman     case '\'':
25924a17663cSThomas Veerman     case '"':
25934a17663cSThomas Veerman 	{
2594*0a6a1f1dSLionel Sambuc 	    char *s = copy_string(c);
2595*0a6a1f1dSLionel Sambuc 	    fputs(s, f);
2596*0a6a1f1dSLionel Sambuc 	    free(s);
2597*0a6a1f1dSLionel Sambuc 	}
2598*0a6a1f1dSLionel Sambuc 	goto loop;
25994a17663cSThomas Veerman 
2600*0a6a1f1dSLionel Sambuc     case '/':
2601*0a6a1f1dSLionel Sambuc 	{
2602*0a6a1f1dSLionel Sambuc 	    char *s = copy_comment();
2603*0a6a1f1dSLionel Sambuc 	    fputs(s, f);
2604*0a6a1f1dSLionel Sambuc 	    free(s);
2605*0a6a1f1dSLionel Sambuc 	}
2606*0a6a1f1dSLionel Sambuc 	goto loop;
2607*0a6a1f1dSLionel Sambuc 
2608*0a6a1f1dSLionel Sambuc     default:
2609*0a6a1f1dSLionel Sambuc 	goto loop;
2610*0a6a1f1dSLionel Sambuc     }
2611*0a6a1f1dSLionel Sambuc }
2612*0a6a1f1dSLionel Sambuc 
2613*0a6a1f1dSLionel Sambuc #if defined(YYBTYACC)
2614*0a6a1f1dSLionel Sambuc static char *
get_code(struct ainfo * a,const char * loc)2615*0a6a1f1dSLionel Sambuc get_code(struct ainfo *a, const char *loc)
2616*0a6a1f1dSLionel Sambuc {
2617*0a6a1f1dSLionel Sambuc     int c;
2618*0a6a1f1dSLionel Sambuc     int depth;
2619*0a6a1f1dSLionel Sambuc     char *tag;
2620*0a6a1f1dSLionel Sambuc     struct mstring *code_mstr = msnew();
2621*0a6a1f1dSLionel Sambuc 
2622*0a6a1f1dSLionel Sambuc     if (!lflag)
2623*0a6a1f1dSLionel Sambuc 	msprintf(code_mstr, line_format, lineno, input_file_name);
2624*0a6a1f1dSLionel Sambuc 
2625*0a6a1f1dSLionel Sambuc     cptr = after_blanks(cptr);
2626*0a6a1f1dSLionel Sambuc     if (*cptr == L_CURL)
2627*0a6a1f1dSLionel Sambuc 	/* avoid putting curly-braces in first column, to ease editing */
2628*0a6a1f1dSLionel Sambuc 	mputc(code_mstr, '\t');
2629*0a6a1f1dSLionel Sambuc     else
2630*0a6a1f1dSLionel Sambuc 	syntax_error(lineno, line, cptr);
2631*0a6a1f1dSLionel Sambuc 
2632*0a6a1f1dSLionel Sambuc     a->a_lineno = lineno;
2633*0a6a1f1dSLionel Sambuc     a->a_line = dup_line();
2634*0a6a1f1dSLionel Sambuc     a->a_cptr = a->a_line + (cptr - line);
2635*0a6a1f1dSLionel Sambuc 
2636*0a6a1f1dSLionel Sambuc     depth = 0;
2637*0a6a1f1dSLionel Sambuc   loop:
2638*0a6a1f1dSLionel Sambuc     c = *cptr;
2639*0a6a1f1dSLionel Sambuc     if (c == '$')
2640*0a6a1f1dSLionel Sambuc     {
2641*0a6a1f1dSLionel Sambuc 	if (cptr[1] == '<')
2642*0a6a1f1dSLionel Sambuc 	{
2643*0a6a1f1dSLionel Sambuc 	    int d_lineno = lineno;
2644*0a6a1f1dSLionel Sambuc 	    char *d_line = dup_line();
2645*0a6a1f1dSLionel Sambuc 	    char *d_cptr = d_line + (cptr - line);
2646*0a6a1f1dSLionel Sambuc 
2647*0a6a1f1dSLionel Sambuc 	    ++cptr;
2648*0a6a1f1dSLionel Sambuc 	    tag = get_tag();
2649*0a6a1f1dSLionel Sambuc 	    c = *cptr;
2650*0a6a1f1dSLionel Sambuc 	    if (c == '$')
2651*0a6a1f1dSLionel Sambuc 	    {
2652*0a6a1f1dSLionel Sambuc 		msprintf(code_mstr, "(*val).%s", tag);
2653*0a6a1f1dSLionel Sambuc 		++cptr;
2654*0a6a1f1dSLionel Sambuc 		FREE(d_line);
2655*0a6a1f1dSLionel Sambuc 		goto loop;
2656*0a6a1f1dSLionel Sambuc 	    }
2657*0a6a1f1dSLionel Sambuc 	    else
2658*0a6a1f1dSLionel Sambuc 		dollar_error(d_lineno, d_line, d_cptr);
2659*0a6a1f1dSLionel Sambuc 	}
2660*0a6a1f1dSLionel Sambuc 	else if (cptr[1] == '$')
2661*0a6a1f1dSLionel Sambuc 	{
2662*0a6a1f1dSLionel Sambuc 	    /* process '$$' later; replacement is context dependent */
2663*0a6a1f1dSLionel Sambuc 	    msprintf(code_mstr, "$$");
2664*0a6a1f1dSLionel Sambuc 	    cptr += 2;
2665*0a6a1f1dSLionel Sambuc 	    goto loop;
2666*0a6a1f1dSLionel Sambuc 	}
2667*0a6a1f1dSLionel Sambuc     }
2668*0a6a1f1dSLionel Sambuc     if (c == '@' && cptr[1] == '$')
2669*0a6a1f1dSLionel Sambuc     {
2670*0a6a1f1dSLionel Sambuc 	if (!locations)
2671*0a6a1f1dSLionel Sambuc 	{
2672*0a6a1f1dSLionel Sambuc 	    int l_lineno = lineno;
2673*0a6a1f1dSLionel Sambuc 	    char *l_line = dup_line();
2674*0a6a1f1dSLionel Sambuc 	    char *l_cptr = l_line + (cptr - line);
2675*0a6a1f1dSLionel Sambuc 	    syntax_error(l_lineno, l_line, l_cptr);
2676*0a6a1f1dSLionel Sambuc 	}
2677*0a6a1f1dSLionel Sambuc 	msprintf(code_mstr, "%s", loc);
2678*0a6a1f1dSLionel Sambuc 	cptr += 2;
2679*0a6a1f1dSLionel Sambuc 	goto loop;
2680*0a6a1f1dSLionel Sambuc     }
2681*0a6a1f1dSLionel Sambuc     if (isalpha(c) || c == '_' || c == '$')
2682*0a6a1f1dSLionel Sambuc     {
2683*0a6a1f1dSLionel Sambuc 	do
2684*0a6a1f1dSLionel Sambuc 	{
2685*0a6a1f1dSLionel Sambuc 	    mputc(code_mstr, c);
2686*0a6a1f1dSLionel Sambuc 	    c = *++cptr;
2687*0a6a1f1dSLionel Sambuc 	}
2688*0a6a1f1dSLionel Sambuc 	while (isalnum(c) || c == '_' || c == '$');
2689*0a6a1f1dSLionel Sambuc 	goto loop;
2690*0a6a1f1dSLionel Sambuc     }
2691*0a6a1f1dSLionel Sambuc     ++cptr;
2692*0a6a1f1dSLionel Sambuc     mputc(code_mstr, c);
2693*0a6a1f1dSLionel Sambuc     switch (c)
2694*0a6a1f1dSLionel Sambuc     {
2695*0a6a1f1dSLionel Sambuc     case '\n':
2696*0a6a1f1dSLionel Sambuc 	get_line();
2697*0a6a1f1dSLionel Sambuc 	if (line)
2698*0a6a1f1dSLionel Sambuc 	    goto loop;
2699*0a6a1f1dSLionel Sambuc 	unterminated_action(a);
2700*0a6a1f1dSLionel Sambuc 
2701*0a6a1f1dSLionel Sambuc     case L_CURL:
2702*0a6a1f1dSLionel Sambuc 	++depth;
2703*0a6a1f1dSLionel Sambuc 	goto loop;
2704*0a6a1f1dSLionel Sambuc 
2705*0a6a1f1dSLionel Sambuc     case R_CURL:
2706*0a6a1f1dSLionel Sambuc 	if (--depth > 0)
2707*0a6a1f1dSLionel Sambuc 	    goto loop;
2708*0a6a1f1dSLionel Sambuc 	goto out;
2709*0a6a1f1dSLionel Sambuc 
2710*0a6a1f1dSLionel Sambuc     case '\'':
2711*0a6a1f1dSLionel Sambuc     case '"':
2712*0a6a1f1dSLionel Sambuc 	{
2713*0a6a1f1dSLionel Sambuc 	    char *s = copy_string(c);
2714*0a6a1f1dSLionel Sambuc 	    msprintf(code_mstr, "%s", s);
2715*0a6a1f1dSLionel Sambuc 	    free(s);
2716*0a6a1f1dSLionel Sambuc 	}
2717*0a6a1f1dSLionel Sambuc 	goto loop;
2718*0a6a1f1dSLionel Sambuc 
2719*0a6a1f1dSLionel Sambuc     case '/':
2720*0a6a1f1dSLionel Sambuc 	{
2721*0a6a1f1dSLionel Sambuc 	    char *s = copy_comment();
2722*0a6a1f1dSLionel Sambuc 	    msprintf(code_mstr, "%s", s);
2723*0a6a1f1dSLionel Sambuc 	    free(s);
2724*0a6a1f1dSLionel Sambuc 	}
2725*0a6a1f1dSLionel Sambuc 	goto loop;
2726*0a6a1f1dSLionel Sambuc 
2727*0a6a1f1dSLionel Sambuc     default:
2728*0a6a1f1dSLionel Sambuc 	goto loop;
2729*0a6a1f1dSLionel Sambuc     }
2730*0a6a1f1dSLionel Sambuc   out:
2731*0a6a1f1dSLionel Sambuc     return msdone(code_mstr);
2732*0a6a1f1dSLionel Sambuc }
2733*0a6a1f1dSLionel Sambuc 
2734*0a6a1f1dSLionel Sambuc static void
copy_initial_action(void)2735*0a6a1f1dSLionel Sambuc copy_initial_action(void)
2736*0a6a1f1dSLionel Sambuc {
2737*0a6a1f1dSLionel Sambuc     struct ainfo a;
2738*0a6a1f1dSLionel Sambuc 
2739*0a6a1f1dSLionel Sambuc     initial_action = get_code(&a, "yyloc");
2740*0a6a1f1dSLionel Sambuc     free(a.a_line);
2741*0a6a1f1dSLionel Sambuc }
2742*0a6a1f1dSLionel Sambuc 
2743*0a6a1f1dSLionel Sambuc static void
copy_destructor(void)2744*0a6a1f1dSLionel Sambuc copy_destructor(void)
2745*0a6a1f1dSLionel Sambuc {
2746*0a6a1f1dSLionel Sambuc     char *code_text;
2747*0a6a1f1dSLionel Sambuc     int c;
2748*0a6a1f1dSLionel Sambuc     struct ainfo a;
2749*0a6a1f1dSLionel Sambuc     bucket *bp;
2750*0a6a1f1dSLionel Sambuc 
2751*0a6a1f1dSLionel Sambuc     code_text = get_code(&a, "(*loc)");
2752*0a6a1f1dSLionel Sambuc 
2753*0a6a1f1dSLionel Sambuc     for (;;)
2754*0a6a1f1dSLionel Sambuc     {
2755*0a6a1f1dSLionel Sambuc 	c = nextc();
2756*0a6a1f1dSLionel Sambuc 	if (c == EOF)
2757*0a6a1f1dSLionel Sambuc 	    unexpected_EOF();
2758*0a6a1f1dSLionel Sambuc 	if (c == '<')
2759*0a6a1f1dSLionel Sambuc 	{
2760*0a6a1f1dSLionel Sambuc 	    if (cptr[1] == '>')
2761*0a6a1f1dSLionel Sambuc 	    {			/* "no semantic type" default destructor */
2762*0a6a1f1dSLionel Sambuc 		cptr += 2;
2763*0a6a1f1dSLionel Sambuc 		if ((bp = default_destructor[UNTYPED_DEFAULT]) == NULL)
2764*0a6a1f1dSLionel Sambuc 		{
2765*0a6a1f1dSLionel Sambuc 		    static char untyped_default[] = "<>";
2766*0a6a1f1dSLionel Sambuc 		    bp = make_bucket("untyped default");
2767*0a6a1f1dSLionel Sambuc 		    bp->tag = untyped_default;
2768*0a6a1f1dSLionel Sambuc 		    default_destructor[UNTYPED_DEFAULT] = bp;
2769*0a6a1f1dSLionel Sambuc 		}
2770*0a6a1f1dSLionel Sambuc 		if (bp->destructor != NULL)
2771*0a6a1f1dSLionel Sambuc 		    destructor_redeclared_warning(&a);
2772*0a6a1f1dSLionel Sambuc 		else
2773*0a6a1f1dSLionel Sambuc 		    /* replace "$$" with "(*val)" in destructor code */
2774*0a6a1f1dSLionel Sambuc 		    bp->destructor = process_destructor_XX(code_text, NULL);
2775*0a6a1f1dSLionel Sambuc 	    }
2776*0a6a1f1dSLionel Sambuc 	    else if (cptr[1] == '*' && cptr[2] == '>')
2777*0a6a1f1dSLionel Sambuc 	    {			/* "no per-symbol or per-type" default destructor */
2778*0a6a1f1dSLionel Sambuc 		cptr += 3;
2779*0a6a1f1dSLionel Sambuc 		if ((bp = default_destructor[TYPED_DEFAULT]) == NULL)
2780*0a6a1f1dSLionel Sambuc 		{
2781*0a6a1f1dSLionel Sambuc 		    static char typed_default[] = "<*>";
2782*0a6a1f1dSLionel Sambuc 		    bp = make_bucket("typed default");
2783*0a6a1f1dSLionel Sambuc 		    bp->tag = typed_default;
2784*0a6a1f1dSLionel Sambuc 		    default_destructor[TYPED_DEFAULT] = bp;
2785*0a6a1f1dSLionel Sambuc 		}
2786*0a6a1f1dSLionel Sambuc 		if (bp->destructor != NULL)
2787*0a6a1f1dSLionel Sambuc 		    destructor_redeclared_warning(&a);
2788*0a6a1f1dSLionel Sambuc 		else
2789*0a6a1f1dSLionel Sambuc 		{
2790*0a6a1f1dSLionel Sambuc 		    /* postpone re-processing destructor $$s until end of grammar spec */
2791*0a6a1f1dSLionel Sambuc 		    bp->destructor = TMALLOC(char, strlen(code_text) + 1);
2792*0a6a1f1dSLionel Sambuc 		    NO_SPACE(bp->destructor);
2793*0a6a1f1dSLionel Sambuc 		    strcpy(bp->destructor, code_text);
2794*0a6a1f1dSLionel Sambuc 		}
2795*0a6a1f1dSLionel Sambuc 	    }
2796*0a6a1f1dSLionel Sambuc 	    else
2797*0a6a1f1dSLionel Sambuc 	    {			/* "semantic type" default destructor */
2798*0a6a1f1dSLionel Sambuc 		char *tag = get_tag();
2799*0a6a1f1dSLionel Sambuc 		bp = lookup_type_destructor(tag);
2800*0a6a1f1dSLionel Sambuc 		if (bp->destructor != NULL)
2801*0a6a1f1dSLionel Sambuc 		    destructor_redeclared_warning(&a);
2802*0a6a1f1dSLionel Sambuc 		else
2803*0a6a1f1dSLionel Sambuc 		    /* replace "$$" with "(*val).tag" in destructor code */
2804*0a6a1f1dSLionel Sambuc 		    bp->destructor = process_destructor_XX(code_text, tag);
2805*0a6a1f1dSLionel Sambuc 	    }
2806*0a6a1f1dSLionel Sambuc 	}
2807*0a6a1f1dSLionel Sambuc 	else if (isalpha(c) || c == '_' || c == '.' || c == '$')
2808*0a6a1f1dSLionel Sambuc 	{			/* "symbol" destructor */
2809*0a6a1f1dSLionel Sambuc 	    bp = get_name();
2810*0a6a1f1dSLionel Sambuc 	    if (bp->destructor != NULL)
2811*0a6a1f1dSLionel Sambuc 		destructor_redeclared_warning(&a);
2812*0a6a1f1dSLionel Sambuc 	    else
2813*0a6a1f1dSLionel Sambuc 	    {
2814*0a6a1f1dSLionel Sambuc 		/* postpone re-processing destructor $$s until end of grammar spec */
2815*0a6a1f1dSLionel Sambuc 		bp->destructor = TMALLOC(char, strlen(code_text) + 1);
2816*0a6a1f1dSLionel Sambuc 		NO_SPACE(bp->destructor);
2817*0a6a1f1dSLionel Sambuc 		strcpy(bp->destructor, code_text);
2818*0a6a1f1dSLionel Sambuc 	    }
2819*0a6a1f1dSLionel Sambuc 	}
2820*0a6a1f1dSLionel Sambuc 	else
2821*0a6a1f1dSLionel Sambuc 	    break;
2822*0a6a1f1dSLionel Sambuc     }
2823*0a6a1f1dSLionel Sambuc     free(a.a_line);
2824*0a6a1f1dSLionel Sambuc     free(code_text);
2825*0a6a1f1dSLionel Sambuc }
2826*0a6a1f1dSLionel Sambuc 
2827*0a6a1f1dSLionel Sambuc static char *
process_destructor_XX(char * code,char * tag)2828*0a6a1f1dSLionel Sambuc process_destructor_XX(char *code, char *tag)
2829*0a6a1f1dSLionel Sambuc {
2830*0a6a1f1dSLionel Sambuc     int c;
2831*0a6a1f1dSLionel Sambuc     int quote;
2832*0a6a1f1dSLionel Sambuc     int depth;
2833*0a6a1f1dSLionel Sambuc     struct mstring *new_code = msnew();
2834*0a6a1f1dSLionel Sambuc     char *codeptr = code;
2835*0a6a1f1dSLionel Sambuc 
2836*0a6a1f1dSLionel Sambuc     depth = 0;
2837*0a6a1f1dSLionel Sambuc   loop:			/* step thru code */
2838*0a6a1f1dSLionel Sambuc     c = *codeptr;
2839*0a6a1f1dSLionel Sambuc     if (c == '$' && codeptr[1] == '$')
2840*0a6a1f1dSLionel Sambuc     {
2841*0a6a1f1dSLionel Sambuc 	codeptr += 2;
2842*0a6a1f1dSLionel Sambuc 	if (tag == NULL)
2843*0a6a1f1dSLionel Sambuc 	    msprintf(new_code, "(*val)");
2844*0a6a1f1dSLionel Sambuc 	else
2845*0a6a1f1dSLionel Sambuc 	    msprintf(new_code, "(*val).%s", tag);
2846*0a6a1f1dSLionel Sambuc 	goto loop;
2847*0a6a1f1dSLionel Sambuc     }
2848*0a6a1f1dSLionel Sambuc     if (isalpha(c) || c == '_' || c == '$')
2849*0a6a1f1dSLionel Sambuc     {
2850*0a6a1f1dSLionel Sambuc 	do
2851*0a6a1f1dSLionel Sambuc 	{
2852*0a6a1f1dSLionel Sambuc 	    mputc(new_code, c);
2853*0a6a1f1dSLionel Sambuc 	    c = *++codeptr;
2854*0a6a1f1dSLionel Sambuc 	}
2855*0a6a1f1dSLionel Sambuc 	while (isalnum(c) || c == '_' || c == '$');
2856*0a6a1f1dSLionel Sambuc 	goto loop;
2857*0a6a1f1dSLionel Sambuc     }
2858*0a6a1f1dSLionel Sambuc     ++codeptr;
2859*0a6a1f1dSLionel Sambuc     mputc(new_code, c);
2860*0a6a1f1dSLionel Sambuc     switch (c)
2861*0a6a1f1dSLionel Sambuc     {
2862*0a6a1f1dSLionel Sambuc     case L_CURL:
2863*0a6a1f1dSLionel Sambuc 	++depth;
2864*0a6a1f1dSLionel Sambuc 	goto loop;
2865*0a6a1f1dSLionel Sambuc 
2866*0a6a1f1dSLionel Sambuc     case R_CURL:
2867*0a6a1f1dSLionel Sambuc 	if (--depth > 0)
2868*0a6a1f1dSLionel Sambuc 	    goto loop;
2869*0a6a1f1dSLionel Sambuc 	return msdone(new_code);
2870*0a6a1f1dSLionel Sambuc 
2871*0a6a1f1dSLionel Sambuc     case '\'':
2872*0a6a1f1dSLionel Sambuc     case '"':
28734a17663cSThomas Veerman 	quote = c;
28744a17663cSThomas Veerman 	for (;;)
28754a17663cSThomas Veerman 	{
2876*0a6a1f1dSLionel Sambuc 	    c = *codeptr++;
2877*0a6a1f1dSLionel Sambuc 	    mputc(new_code, c);
28784a17663cSThomas Veerman 	    if (c == quote)
28794a17663cSThomas Veerman 		goto loop;
28804a17663cSThomas Veerman 	    if (c == '\\')
28814a17663cSThomas Veerman 	    {
2882*0a6a1f1dSLionel Sambuc 		c = *codeptr++;
2883*0a6a1f1dSLionel Sambuc 		mputc(new_code, c);
28844a17663cSThomas Veerman 	    }
28854a17663cSThomas Veerman 	}
28864a17663cSThomas Veerman 
28874a17663cSThomas Veerman     case '/':
2888*0a6a1f1dSLionel Sambuc 	c = *codeptr;
28894a17663cSThomas Veerman 	if (c == '*')
28904a17663cSThomas Veerman 	{
2891*0a6a1f1dSLionel Sambuc 	    mputc(new_code, c);
2892*0a6a1f1dSLionel Sambuc 	    ++codeptr;
28934a17663cSThomas Veerman 	    for (;;)
28944a17663cSThomas Veerman 	    {
2895*0a6a1f1dSLionel Sambuc 		c = *codeptr++;
2896*0a6a1f1dSLionel Sambuc 		mputc(new_code, c);
2897*0a6a1f1dSLionel Sambuc 		if (c == '*' && *codeptr == '/')
28984a17663cSThomas Veerman 		{
2899*0a6a1f1dSLionel Sambuc 		    mputc(new_code, '/');
2900*0a6a1f1dSLionel Sambuc 		    ++codeptr;
29014a17663cSThomas Veerman 		    goto loop;
29024a17663cSThomas Veerman 		}
29034a17663cSThomas Veerman 	    }
29044a17663cSThomas Veerman 	}
29054a17663cSThomas Veerman 	goto loop;
29064a17663cSThomas Veerman 
29074a17663cSThomas Veerman     default:
29084a17663cSThomas Veerman 	goto loop;
29094a17663cSThomas Veerman     }
29104a17663cSThomas Veerman }
2911*0a6a1f1dSLionel Sambuc #endif /* defined(YYBTYACC) */
29124a17663cSThomas Veerman 
29134a17663cSThomas Veerman static int
mark_symbol(void)29144a17663cSThomas Veerman mark_symbol(void)
29154a17663cSThomas Veerman {
29164a17663cSThomas Veerman     int c;
291784d9c625SLionel Sambuc     bucket *bp = NULL;
29184a17663cSThomas Veerman 
29194a17663cSThomas Veerman     c = cptr[1];
29204a17663cSThomas Veerman     if (c == '%' || c == '\\')
29214a17663cSThomas Veerman     {
29224a17663cSThomas Veerman 	cptr += 2;
29234a17663cSThomas Veerman 	return (1);
29244a17663cSThomas Veerman     }
29254a17663cSThomas Veerman 
29264a17663cSThomas Veerman     if (c == '=')
29274a17663cSThomas Veerman 	cptr += 2;
29284a17663cSThomas Veerman     else if ((c == 'p' || c == 'P') &&
29294a17663cSThomas Veerman 	     ((c = cptr[2]) == 'r' || c == 'R') &&
29304a17663cSThomas Veerman 	     ((c = cptr[3]) == 'e' || c == 'E') &&
29314a17663cSThomas Veerman 	     ((c = cptr[4]) == 'c' || c == 'C') &&
29324a17663cSThomas Veerman 	     ((c = cptr[5], !IS_IDENT(c))))
29334a17663cSThomas Veerman 	cptr += 5;
29344a17663cSThomas Veerman     else
29354a17663cSThomas Veerman 	syntax_error(lineno, line, cptr);
29364a17663cSThomas Veerman 
29374a17663cSThomas Veerman     c = nextc();
29384a17663cSThomas Veerman     if (isalpha(c) || c == '_' || c == '.' || c == '$')
29394a17663cSThomas Veerman 	bp = get_name();
29404a17663cSThomas Veerman     else if (c == '\'' || c == '"')
29414a17663cSThomas Veerman 	bp = get_literal();
29424a17663cSThomas Veerman     else
29434a17663cSThomas Veerman     {
29444a17663cSThomas Veerman 	syntax_error(lineno, line, cptr);
29454a17663cSThomas Veerman     }
29464a17663cSThomas Veerman 
29474a17663cSThomas Veerman     if (rprec[nrules] != UNDEFINED && bp->prec != rprec[nrules])
29484a17663cSThomas Veerman 	prec_redeclared();
29494a17663cSThomas Veerman 
29504a17663cSThomas Veerman     rprec[nrules] = bp->prec;
29514a17663cSThomas Veerman     rassoc[nrules] = bp->assoc;
29524a17663cSThomas Veerman     return (0);
29534a17663cSThomas Veerman }
29544a17663cSThomas Veerman 
29554a17663cSThomas Veerman static void
read_grammar(void)29564a17663cSThomas Veerman read_grammar(void)
29574a17663cSThomas Veerman {
29584a17663cSThomas Veerman     int c;
29594a17663cSThomas Veerman 
29604a17663cSThomas Veerman     initialize_grammar();
29614a17663cSThomas Veerman     advance_to_start();
29624a17663cSThomas Veerman 
29634a17663cSThomas Veerman     for (;;)
29644a17663cSThomas Veerman     {
29654a17663cSThomas Veerman 	c = nextc();
29664a17663cSThomas Veerman 	if (c == EOF)
29674a17663cSThomas Veerman 	    break;
29684a17663cSThomas Veerman 	if (isalpha(c)
29694a17663cSThomas Veerman 	    || c == '_'
29704a17663cSThomas Veerman 	    || c == '.'
29714a17663cSThomas Veerman 	    || c == '$'
29724a17663cSThomas Veerman 	    || c == '\''
29734a17663cSThomas Veerman 	    || c == '"')
29744a17663cSThomas Veerman 	    add_symbol();
2975*0a6a1f1dSLionel Sambuc #if defined(YYBTYACC)
2976*0a6a1f1dSLionel Sambuc 	else if (c == L_CURL || c == '=' || (backtrack && c == L_BRAC))
2977*0a6a1f1dSLionel Sambuc #else
29784a17663cSThomas Veerman 	else if (c == L_CURL || c == '=')
2979*0a6a1f1dSLionel Sambuc #endif
29804a17663cSThomas Veerman 	    copy_action();
29814a17663cSThomas Veerman 	else if (c == '|')
29824a17663cSThomas Veerman 	{
29834a17663cSThomas Veerman 	    end_rule();
29844a17663cSThomas Veerman 	    start_rule(plhs[nrules - 1], 0);
29854a17663cSThomas Veerman 	    ++cptr;
29864a17663cSThomas Veerman 	}
29874a17663cSThomas Veerman 	else if (c == '%')
29884a17663cSThomas Veerman 	{
29894a17663cSThomas Veerman 	    if (mark_symbol())
29904a17663cSThomas Veerman 		break;
29914a17663cSThomas Veerman 	}
29924a17663cSThomas Veerman 	else
29934a17663cSThomas Veerman 	    syntax_error(lineno, line, cptr);
29944a17663cSThomas Veerman     }
29954a17663cSThomas Veerman     end_rule();
2996*0a6a1f1dSLionel Sambuc #if defined(YYBTYACC)
2997*0a6a1f1dSLionel Sambuc     if (goal->args > 0)
2998*0a6a1f1dSLionel Sambuc 	start_requires_args(goal->name);
2999*0a6a1f1dSLionel Sambuc #endif
30004a17663cSThomas Veerman }
30014a17663cSThomas Veerman 
30024a17663cSThomas Veerman static void
free_tags(void)30034a17663cSThomas Veerman free_tags(void)
30044a17663cSThomas Veerman {
30054a17663cSThomas Veerman     int i;
30064a17663cSThomas Veerman 
30074a17663cSThomas Veerman     if (tag_table == 0)
30084a17663cSThomas Veerman 	return;
30094a17663cSThomas Veerman 
30104a17663cSThomas Veerman     for (i = 0; i < ntags; ++i)
30114a17663cSThomas Veerman     {
30124a17663cSThomas Veerman 	assert(tag_table[i]);
30134a17663cSThomas Veerman 	FREE(tag_table[i]);
30144a17663cSThomas Veerman     }
30154a17663cSThomas Veerman     FREE(tag_table);
30164a17663cSThomas Veerman }
30174a17663cSThomas Veerman 
30184a17663cSThomas Veerman static void
pack_names(void)30194a17663cSThomas Veerman pack_names(void)
30204a17663cSThomas Veerman {
30214a17663cSThomas Veerman     bucket *bp;
30224a17663cSThomas Veerman     char *p, *s, *t;
30234a17663cSThomas Veerman 
30244a17663cSThomas Veerman     name_pool_size = 13;	/* 13 == sizeof("$end") + sizeof("$accept") */
30254a17663cSThomas Veerman     for (bp = first_symbol; bp; bp = bp->next)
30264a17663cSThomas Veerman 	name_pool_size += strlen(bp->name) + 1;
30274a17663cSThomas Veerman 
302884d9c625SLionel Sambuc     name_pool = TMALLOC(char, name_pool_size);
30294a17663cSThomas Veerman     NO_SPACE(name_pool);
30304a17663cSThomas Veerman 
30314a17663cSThomas Veerman     strlcpy(name_pool, "$accept", name_pool_size);
30324a17663cSThomas Veerman     strlcpy(name_pool + 8, "$end", name_pool_size - 8);
30334a17663cSThomas Veerman     t = name_pool + 13;
30344a17663cSThomas Veerman     for (bp = first_symbol; bp; bp = bp->next)
30354a17663cSThomas Veerman     {
30364a17663cSThomas Veerman 	p = t;
30374a17663cSThomas Veerman 	s = bp->name;
30384a17663cSThomas Veerman 	while ((*t++ = *s++) != 0)
30394a17663cSThomas Veerman 	    continue;
30404a17663cSThomas Veerman 	FREE(bp->name);
30414a17663cSThomas Veerman 	bp->name = p;
30424a17663cSThomas Veerman     }
30434a17663cSThomas Veerman }
30444a17663cSThomas Veerman 
30454a17663cSThomas Veerman static void
check_symbols(void)30464a17663cSThomas Veerman check_symbols(void)
30474a17663cSThomas Veerman {
30484a17663cSThomas Veerman     bucket *bp;
30494a17663cSThomas Veerman 
30504a17663cSThomas Veerman     if (goal->class == UNKNOWN)
30514a17663cSThomas Veerman 	undefined_goal(goal->name);
30524a17663cSThomas Veerman 
30534a17663cSThomas Veerman     for (bp = first_symbol; bp; bp = bp->next)
30544a17663cSThomas Veerman     {
30554a17663cSThomas Veerman 	if (bp->class == UNKNOWN)
30564a17663cSThomas Veerman 	{
30574a17663cSThomas Veerman 	    undefined_symbol_warning(bp->name);
30584a17663cSThomas Veerman 	    bp->class = TERM;
30594a17663cSThomas Veerman 	}
30604a17663cSThomas Veerman     }
30614a17663cSThomas Veerman }
30624a17663cSThomas Veerman 
30634a17663cSThomas Veerman static void
protect_string(char * src,char ** des)30644a17663cSThomas Veerman protect_string(char *src, char **des)
30654a17663cSThomas Veerman {
30664a17663cSThomas Veerman     unsigned len;
30674a17663cSThomas Veerman     char *s;
30684a17663cSThomas Veerman     char *d;
30694a17663cSThomas Veerman 
30704a17663cSThomas Veerman     *des = src;
30714a17663cSThomas Veerman     if (src)
30724a17663cSThomas Veerman     {
30734a17663cSThomas Veerman 	len = 1;
30744a17663cSThomas Veerman 	s = src;
30754a17663cSThomas Veerman 	while (*s)
30764a17663cSThomas Veerman 	{
30774a17663cSThomas Veerman 	    if ('\\' == *s || '"' == *s)
30784a17663cSThomas Veerman 		len++;
30794a17663cSThomas Veerman 	    s++;
30804a17663cSThomas Veerman 	    len++;
30814a17663cSThomas Veerman 	}
30824a17663cSThomas Veerman 
308384d9c625SLionel Sambuc 	*des = d = TMALLOC(char, len);
30844a17663cSThomas Veerman 	NO_SPACE(d);
30854a17663cSThomas Veerman 
30864a17663cSThomas Veerman 	s = src;
30874a17663cSThomas Veerman 	while (*s)
30884a17663cSThomas Veerman 	{
30894a17663cSThomas Veerman 	    if ('\\' == *s || '"' == *s)
30904a17663cSThomas Veerman 		*d++ = '\\';
30914a17663cSThomas Veerman 	    *d++ = *s++;
30924a17663cSThomas Veerman 	}
30934a17663cSThomas Veerman 	*d = '\0';
30944a17663cSThomas Veerman     }
30954a17663cSThomas Veerman }
30964a17663cSThomas Veerman 
30974a17663cSThomas Veerman static void
pack_symbols(void)30984a17663cSThomas Veerman pack_symbols(void)
30994a17663cSThomas Veerman {
31004a17663cSThomas Veerman     bucket *bp;
31014a17663cSThomas Veerman     bucket **v;
31024a17663cSThomas Veerman     Value_t i, j, k, n;
3103*0a6a1f1dSLionel Sambuc #if defined(YYBTYACC)
3104*0a6a1f1dSLionel Sambuc     Value_t max_tok_pval;
3105*0a6a1f1dSLionel Sambuc #endif
31064a17663cSThomas Veerman 
31074a17663cSThomas Veerman     nsyms = 2;
31084a17663cSThomas Veerman     ntokens = 1;
31094a17663cSThomas Veerman     for (bp = first_symbol; bp; bp = bp->next)
31104a17663cSThomas Veerman     {
31114a17663cSThomas Veerman 	++nsyms;
31124a17663cSThomas Veerman 	if (bp->class == TERM)
31134a17663cSThomas Veerman 	    ++ntokens;
31144a17663cSThomas Veerman     }
31154a17663cSThomas Veerman     start_symbol = (Value_t) ntokens;
3116*0a6a1f1dSLionel Sambuc     nvars = (Value_t) (nsyms - ntokens);
31174a17663cSThomas Veerman 
311884d9c625SLionel Sambuc     symbol_name = TMALLOC(char *, nsyms);
31194a17663cSThomas Veerman     NO_SPACE(symbol_name);
31204a17663cSThomas Veerman 
312184d9c625SLionel Sambuc     symbol_value = TMALLOC(Value_t, nsyms);
31224a17663cSThomas Veerman     NO_SPACE(symbol_value);
31234a17663cSThomas Veerman 
3124*0a6a1f1dSLionel Sambuc     symbol_prec = TMALLOC(Value_t, nsyms);
31254a17663cSThomas Veerman     NO_SPACE(symbol_prec);
31264a17663cSThomas Veerman 
312784d9c625SLionel Sambuc     symbol_assoc = TMALLOC(char, nsyms);
31284a17663cSThomas Veerman     NO_SPACE(symbol_assoc);
31294a17663cSThomas Veerman 
3130*0a6a1f1dSLionel Sambuc #if defined(YYBTYACC)
3131*0a6a1f1dSLionel Sambuc     symbol_pval = TMALLOC(Value_t, nsyms);
3132*0a6a1f1dSLionel Sambuc     NO_SPACE(symbol_pval);
3133*0a6a1f1dSLionel Sambuc 
3134*0a6a1f1dSLionel Sambuc     if (destructor)
3135*0a6a1f1dSLionel Sambuc     {
3136*0a6a1f1dSLionel Sambuc 	symbol_destructor = CALLOC(sizeof(char *), nsyms);
3137*0a6a1f1dSLionel Sambuc 	NO_SPACE(symbol_destructor);
3138*0a6a1f1dSLionel Sambuc 
3139*0a6a1f1dSLionel Sambuc 	symbol_type_tag = CALLOC(sizeof(char *), nsyms);
3140*0a6a1f1dSLionel Sambuc 	NO_SPACE(symbol_type_tag);
3141*0a6a1f1dSLionel Sambuc     }
3142*0a6a1f1dSLionel Sambuc #endif
3143*0a6a1f1dSLionel Sambuc 
314484d9c625SLionel Sambuc     v = TMALLOC(bucket *, nsyms);
31454a17663cSThomas Veerman     NO_SPACE(v);
31464a17663cSThomas Veerman 
31474a17663cSThomas Veerman     v[0] = 0;
31484a17663cSThomas Veerman     v[start_symbol] = 0;
31494a17663cSThomas Veerman 
31504a17663cSThomas Veerman     i = 1;
31514a17663cSThomas Veerman     j = (Value_t) (start_symbol + 1);
31524a17663cSThomas Veerman     for (bp = first_symbol; bp; bp = bp->next)
31534a17663cSThomas Veerman     {
31544a17663cSThomas Veerman 	if (bp->class == TERM)
31554a17663cSThomas Veerman 	    v[i++] = bp;
31564a17663cSThomas Veerman 	else
31574a17663cSThomas Veerman 	    v[j++] = bp;
31584a17663cSThomas Veerman     }
31594a17663cSThomas Veerman     assert(i == ntokens && j == nsyms);
31604a17663cSThomas Veerman 
31614a17663cSThomas Veerman     for (i = 1; i < ntokens; ++i)
31624a17663cSThomas Veerman 	v[i]->index = i;
31634a17663cSThomas Veerman 
31644a17663cSThomas Veerman     goal->index = (Index_t) (start_symbol + 1);
31654a17663cSThomas Veerman     k = (Value_t) (start_symbol + 2);
31664a17663cSThomas Veerman     while (++i < nsyms)
31674a17663cSThomas Veerman 	if (v[i] != goal)
31684a17663cSThomas Veerman 	{
31694a17663cSThomas Veerman 	    v[i]->index = k;
31704a17663cSThomas Veerman 	    ++k;
31714a17663cSThomas Veerman 	}
31724a17663cSThomas Veerman 
31734a17663cSThomas Veerman     goal->value = 0;
31744a17663cSThomas Veerman     k = 1;
31754a17663cSThomas Veerman     for (i = (Value_t) (start_symbol + 1); i < nsyms; ++i)
31764a17663cSThomas Veerman     {
31774a17663cSThomas Veerman 	if (v[i] != goal)
31784a17663cSThomas Veerman 	{
31794a17663cSThomas Veerman 	    v[i]->value = k;
31804a17663cSThomas Veerman 	    ++k;
31814a17663cSThomas Veerman 	}
31824a17663cSThomas Veerman     }
31834a17663cSThomas Veerman 
31844a17663cSThomas Veerman     k = 0;
31854a17663cSThomas Veerman     for (i = 1; i < ntokens; ++i)
31864a17663cSThomas Veerman     {
31874a17663cSThomas Veerman 	n = v[i]->value;
31884a17663cSThomas Veerman 	if (n > 256)
31894a17663cSThomas Veerman 	{
31904a17663cSThomas Veerman 	    for (j = k++; j > 0 && symbol_value[j - 1] > n; --j)
31914a17663cSThomas Veerman 		symbol_value[j] = symbol_value[j - 1];
31924a17663cSThomas Veerman 	    symbol_value[j] = n;
31934a17663cSThomas Veerman 	}
31944a17663cSThomas Veerman     }
31954a17663cSThomas Veerman 
31964a17663cSThomas Veerman     assert(v[1] != 0);
31974a17663cSThomas Veerman 
31984a17663cSThomas Veerman     if (v[1]->value == UNDEFINED)
31994a17663cSThomas Veerman 	v[1]->value = 256;
32004a17663cSThomas Veerman 
32014a17663cSThomas Veerman     j = 0;
32024a17663cSThomas Veerman     n = 257;
32034a17663cSThomas Veerman     for (i = 2; i < ntokens; ++i)
32044a17663cSThomas Veerman     {
32054a17663cSThomas Veerman 	if (v[i]->value == UNDEFINED)
32064a17663cSThomas Veerman 	{
32074a17663cSThomas Veerman 	    while (j < k && n == symbol_value[j])
32084a17663cSThomas Veerman 	    {
32094a17663cSThomas Veerman 		while (++j < k && n == symbol_value[j])
32104a17663cSThomas Veerman 		    continue;
32114a17663cSThomas Veerman 		++n;
32124a17663cSThomas Veerman 	    }
32134a17663cSThomas Veerman 	    v[i]->value = n;
32144a17663cSThomas Veerman 	    ++n;
32154a17663cSThomas Veerman 	}
32164a17663cSThomas Veerman     }
32174a17663cSThomas Veerman 
32184a17663cSThomas Veerman     symbol_name[0] = name_pool + 8;
32194a17663cSThomas Veerman     symbol_value[0] = 0;
32204a17663cSThomas Veerman     symbol_prec[0] = 0;
32214a17663cSThomas Veerman     symbol_assoc[0] = TOKEN;
3222*0a6a1f1dSLionel Sambuc #if defined(YYBTYACC)
3223*0a6a1f1dSLionel Sambuc     symbol_pval[0] = 0;
3224*0a6a1f1dSLionel Sambuc     max_tok_pval = 0;
3225*0a6a1f1dSLionel Sambuc #endif
32264a17663cSThomas Veerman     for (i = 1; i < ntokens; ++i)
32274a17663cSThomas Veerman     {
32284a17663cSThomas Veerman 	symbol_name[i] = v[i]->name;
32294a17663cSThomas Veerman 	symbol_value[i] = v[i]->value;
32304a17663cSThomas Veerman 	symbol_prec[i] = v[i]->prec;
32314a17663cSThomas Veerman 	symbol_assoc[i] = v[i]->assoc;
3232*0a6a1f1dSLionel Sambuc #if defined(YYBTYACC)
3233*0a6a1f1dSLionel Sambuc 	symbol_pval[i] = v[i]->value;
3234*0a6a1f1dSLionel Sambuc 	if (symbol_pval[i] > max_tok_pval)
3235*0a6a1f1dSLionel Sambuc 	    max_tok_pval = symbol_pval[i];
3236*0a6a1f1dSLionel Sambuc 	if (destructor)
3237*0a6a1f1dSLionel Sambuc 	{
3238*0a6a1f1dSLionel Sambuc 	    symbol_destructor[i] = v[i]->destructor;
3239*0a6a1f1dSLionel Sambuc 	    symbol_type_tag[i] = v[i]->tag;
3240*0a6a1f1dSLionel Sambuc 	}
3241*0a6a1f1dSLionel Sambuc #endif
32424a17663cSThomas Veerman     }
32434a17663cSThomas Veerman     symbol_name[start_symbol] = name_pool;
32444a17663cSThomas Veerman     symbol_value[start_symbol] = -1;
32454a17663cSThomas Veerman     symbol_prec[start_symbol] = 0;
32464a17663cSThomas Veerman     symbol_assoc[start_symbol] = TOKEN;
3247*0a6a1f1dSLionel Sambuc #if defined(YYBTYACC)
3248*0a6a1f1dSLionel Sambuc     symbol_pval[start_symbol] = (Value_t) (max_tok_pval + 1);
3249*0a6a1f1dSLionel Sambuc #endif
32504a17663cSThomas Veerman     for (++i; i < nsyms; ++i)
32514a17663cSThomas Veerman     {
32524a17663cSThomas Veerman 	k = v[i]->index;
32534a17663cSThomas Veerman 	symbol_name[k] = v[i]->name;
32544a17663cSThomas Veerman 	symbol_value[k] = v[i]->value;
32554a17663cSThomas Veerman 	symbol_prec[k] = v[i]->prec;
32564a17663cSThomas Veerman 	symbol_assoc[k] = v[i]->assoc;
3257*0a6a1f1dSLionel Sambuc #if defined(YYBTYACC)
3258*0a6a1f1dSLionel Sambuc 	symbol_pval[k] = (Value_t) ((max_tok_pval + 1) + v[i]->value + 1);
3259*0a6a1f1dSLionel Sambuc 	if (destructor)
3260*0a6a1f1dSLionel Sambuc 	{
3261*0a6a1f1dSLionel Sambuc 	    symbol_destructor[k] = v[i]->destructor;
3262*0a6a1f1dSLionel Sambuc 	    symbol_type_tag[k] = v[i]->tag;
3263*0a6a1f1dSLionel Sambuc 	}
3264*0a6a1f1dSLionel Sambuc #endif
32654a17663cSThomas Veerman     }
32664a17663cSThomas Veerman 
32674a17663cSThomas Veerman     if (gflag)
32684a17663cSThomas Veerman     {
326984d9c625SLionel Sambuc 	symbol_pname = TMALLOC(char *, nsyms);
32704a17663cSThomas Veerman 	NO_SPACE(symbol_pname);
32714a17663cSThomas Veerman 
32724a17663cSThomas Veerman 	for (i = 0; i < nsyms; ++i)
32734a17663cSThomas Veerman 	    protect_string(symbol_name[i], &(symbol_pname[i]));
32744a17663cSThomas Veerman     }
32754a17663cSThomas Veerman 
32764a17663cSThomas Veerman     FREE(v);
32774a17663cSThomas Veerman }
32784a17663cSThomas Veerman 
32794a17663cSThomas Veerman static void
pack_grammar(void)32804a17663cSThomas Veerman pack_grammar(void)
32814a17663cSThomas Veerman {
32824a17663cSThomas Veerman     int i;
32834a17663cSThomas Veerman     Value_t j;
32844a17663cSThomas Veerman     Assoc_t assoc;
32854a17663cSThomas Veerman     Value_t prec2;
32864a17663cSThomas Veerman 
328784d9c625SLionel Sambuc     ritem = TMALLOC(Value_t, nitems);
32884a17663cSThomas Veerman     NO_SPACE(ritem);
32894a17663cSThomas Veerman 
329084d9c625SLionel Sambuc     rlhs = TMALLOC(Value_t, nrules);
32914a17663cSThomas Veerman     NO_SPACE(rlhs);
32924a17663cSThomas Veerman 
329384d9c625SLionel Sambuc     rrhs = TMALLOC(Value_t, nrules + 1);
32944a17663cSThomas Veerman     NO_SPACE(rrhs);
32954a17663cSThomas Veerman 
329684d9c625SLionel Sambuc     rprec = TREALLOC(Value_t, rprec, nrules);
32974a17663cSThomas Veerman     NO_SPACE(rprec);
32984a17663cSThomas Veerman 
329984d9c625SLionel Sambuc     rassoc = TREALLOC(Assoc_t, rassoc, nrules);
33004a17663cSThomas Veerman     NO_SPACE(rassoc);
33014a17663cSThomas Veerman 
33024a17663cSThomas Veerman     ritem[0] = -1;
33034a17663cSThomas Veerman     ritem[1] = goal->index;
33044a17663cSThomas Veerman     ritem[2] = 0;
33054a17663cSThomas Veerman     ritem[3] = -2;
33064a17663cSThomas Veerman     rlhs[0] = 0;
33074a17663cSThomas Veerman     rlhs[1] = 0;
33084a17663cSThomas Veerman     rlhs[2] = start_symbol;
33094a17663cSThomas Veerman     rrhs[0] = 0;
33104a17663cSThomas Veerman     rrhs[1] = 0;
33114a17663cSThomas Veerman     rrhs[2] = 1;
33124a17663cSThomas Veerman 
33134a17663cSThomas Veerman     j = 4;
33144a17663cSThomas Veerman     for (i = 3; i < nrules; ++i)
33154a17663cSThomas Veerman     {
3316*0a6a1f1dSLionel Sambuc #if defined(YYBTYACC)
3317*0a6a1f1dSLionel Sambuc 	if (plhs[i]->args > 0)
3318*0a6a1f1dSLionel Sambuc 	{
3319*0a6a1f1dSLionel Sambuc 	    if (plhs[i]->argnames)
3320*0a6a1f1dSLionel Sambuc 	    {
3321*0a6a1f1dSLionel Sambuc 		FREE(plhs[i]->argnames);
3322*0a6a1f1dSLionel Sambuc 		plhs[i]->argnames = NULL;
3323*0a6a1f1dSLionel Sambuc 	    }
3324*0a6a1f1dSLionel Sambuc 	    if (plhs[i]->argtags)
3325*0a6a1f1dSLionel Sambuc 	    {
3326*0a6a1f1dSLionel Sambuc 		FREE(plhs[i]->argtags);
3327*0a6a1f1dSLionel Sambuc 		plhs[i]->argtags = NULL;
3328*0a6a1f1dSLionel Sambuc 	    }
3329*0a6a1f1dSLionel Sambuc 	}
3330*0a6a1f1dSLionel Sambuc #endif /* defined(YYBTYACC) */
33314a17663cSThomas Veerman 	rlhs[i] = plhs[i]->index;
33324a17663cSThomas Veerman 	rrhs[i] = j;
33334a17663cSThomas Veerman 	assoc = TOKEN;
33344a17663cSThomas Veerman 	prec2 = 0;
33354a17663cSThomas Veerman 	while (pitem[j])
33364a17663cSThomas Veerman 	{
33374a17663cSThomas Veerman 	    ritem[j] = pitem[j]->index;
33384a17663cSThomas Veerman 	    if (pitem[j]->class == TERM)
33394a17663cSThomas Veerman 	    {
33404a17663cSThomas Veerman 		prec2 = pitem[j]->prec;
33414a17663cSThomas Veerman 		assoc = pitem[j]->assoc;
33424a17663cSThomas Veerman 	    }
33434a17663cSThomas Veerman 	    ++j;
33444a17663cSThomas Veerman 	}
33454a17663cSThomas Veerman 	ritem[j] = (Value_t) - i;
33464a17663cSThomas Veerman 	++j;
33474a17663cSThomas Veerman 	if (rprec[i] == UNDEFINED)
33484a17663cSThomas Veerman 	{
33494a17663cSThomas Veerman 	    rprec[i] = prec2;
33504a17663cSThomas Veerman 	    rassoc[i] = assoc;
33514a17663cSThomas Veerman 	}
33524a17663cSThomas Veerman     }
33534a17663cSThomas Veerman     rrhs[i] = j;
33544a17663cSThomas Veerman 
33554a17663cSThomas Veerman     FREE(plhs);
33564a17663cSThomas Veerman     FREE(pitem);
3357*0a6a1f1dSLionel Sambuc #if defined(YYBTYACC)
3358*0a6a1f1dSLionel Sambuc     clean_arg_cache();
3359*0a6a1f1dSLionel Sambuc #endif
33604a17663cSThomas Veerman }
33614a17663cSThomas Veerman 
33624a17663cSThomas Veerman static void
print_grammar(void)33634a17663cSThomas Veerman print_grammar(void)
33644a17663cSThomas Veerman {
33654a17663cSThomas Veerman     int i, k;
33664a17663cSThomas Veerman     size_t j, spacing = 0;
33674a17663cSThomas Veerman     FILE *f = verbose_file;
33684a17663cSThomas Veerman 
33694a17663cSThomas Veerman     if (!vflag)
33704a17663cSThomas Veerman 	return;
33714a17663cSThomas Veerman 
33724a17663cSThomas Veerman     k = 1;
33734a17663cSThomas Veerman     for (i = 2; i < nrules; ++i)
33744a17663cSThomas Veerman     {
33754a17663cSThomas Veerman 	if (rlhs[i] != rlhs[i - 1])
33764a17663cSThomas Veerman 	{
33774a17663cSThomas Veerman 	    if (i != 2)
33784a17663cSThomas Veerman 		fprintf(f, "\n");
33794a17663cSThomas Veerman 	    fprintf(f, "%4d  %s :", i - 2, symbol_name[rlhs[i]]);
33804a17663cSThomas Veerman 	    spacing = strlen(symbol_name[rlhs[i]]) + 1;
33814a17663cSThomas Veerman 	}
33824a17663cSThomas Veerman 	else
33834a17663cSThomas Veerman 	{
33844a17663cSThomas Veerman 	    fprintf(f, "%4d  ", i - 2);
33854a17663cSThomas Veerman 	    j = spacing;
33864a17663cSThomas Veerman 	    while (j-- != 0)
33874a17663cSThomas Veerman 		putc(' ', f);
33884a17663cSThomas Veerman 	    putc('|', f);
33894a17663cSThomas Veerman 	}
33904a17663cSThomas Veerman 
33914a17663cSThomas Veerman 	while (ritem[k] >= 0)
33924a17663cSThomas Veerman 	{
33934a17663cSThomas Veerman 	    fprintf(f, " %s", symbol_name[ritem[k]]);
33944a17663cSThomas Veerman 	    ++k;
33954a17663cSThomas Veerman 	}
33964a17663cSThomas Veerman 	++k;
33974a17663cSThomas Veerman 	putc('\n', f);
33984a17663cSThomas Veerman     }
33994a17663cSThomas Veerman }
34004a17663cSThomas Veerman 
3401*0a6a1f1dSLionel Sambuc #if defined(YYBTYACC)
3402*0a6a1f1dSLionel Sambuc static void
finalize_destructors(void)3403*0a6a1f1dSLionel Sambuc finalize_destructors(void)
3404*0a6a1f1dSLionel Sambuc {
3405*0a6a1f1dSLionel Sambuc     int i;
3406*0a6a1f1dSLionel Sambuc     bucket *bp;
3407*0a6a1f1dSLionel Sambuc     char *tag;
3408*0a6a1f1dSLionel Sambuc 
3409*0a6a1f1dSLionel Sambuc     for (i = 2; i < nsyms; ++i)
3410*0a6a1f1dSLionel Sambuc     {
3411*0a6a1f1dSLionel Sambuc 	tag = symbol_type_tag[i];
3412*0a6a1f1dSLionel Sambuc 	if (symbol_destructor[i] == NULL)
3413*0a6a1f1dSLionel Sambuc 	{
3414*0a6a1f1dSLionel Sambuc 	    if (tag == NULL)
3415*0a6a1f1dSLionel Sambuc 	    {			/* use <> destructor, if there is one */
3416*0a6a1f1dSLionel Sambuc 		if ((bp = default_destructor[UNTYPED_DEFAULT]) != NULL)
3417*0a6a1f1dSLionel Sambuc 		{
3418*0a6a1f1dSLionel Sambuc 		    symbol_destructor[i] = TMALLOC(char,
3419*0a6a1f1dSLionel Sambuc 						   strlen(bp->destructor) + 1);
3420*0a6a1f1dSLionel Sambuc 		    NO_SPACE(symbol_destructor[i]);
3421*0a6a1f1dSLionel Sambuc 		    strcpy(symbol_destructor[i], bp->destructor);
3422*0a6a1f1dSLionel Sambuc 		}
3423*0a6a1f1dSLionel Sambuc 	    }
3424*0a6a1f1dSLionel Sambuc 	    else
3425*0a6a1f1dSLionel Sambuc 	    {			/* use type destructor for this tag, if there is one */
3426*0a6a1f1dSLionel Sambuc 		bp = lookup_type_destructor(tag);
3427*0a6a1f1dSLionel Sambuc 		if (bp->destructor != NULL)
3428*0a6a1f1dSLionel Sambuc 		{
3429*0a6a1f1dSLionel Sambuc 		    symbol_destructor[i] = TMALLOC(char,
3430*0a6a1f1dSLionel Sambuc 						   strlen(bp->destructor) + 1);
3431*0a6a1f1dSLionel Sambuc 		    NO_SPACE(symbol_destructor[i]);
3432*0a6a1f1dSLionel Sambuc 		    strcpy(symbol_destructor[i], bp->destructor);
3433*0a6a1f1dSLionel Sambuc 		}
3434*0a6a1f1dSLionel Sambuc 		else
3435*0a6a1f1dSLionel Sambuc 		{		/* use <*> destructor, if there is one */
3436*0a6a1f1dSLionel Sambuc 		    if ((bp = default_destructor[TYPED_DEFAULT]) != NULL)
3437*0a6a1f1dSLionel Sambuc 			/* replace "$$" with "(*val).tag" in destructor code */
3438*0a6a1f1dSLionel Sambuc 			symbol_destructor[i]
3439*0a6a1f1dSLionel Sambuc 			    = process_destructor_XX(bp->destructor, tag);
3440*0a6a1f1dSLionel Sambuc 		}
3441*0a6a1f1dSLionel Sambuc 	    }
3442*0a6a1f1dSLionel Sambuc 	}
3443*0a6a1f1dSLionel Sambuc 	else
3444*0a6a1f1dSLionel Sambuc 	{			/* replace "$$" with "(*val)[.tag]" in destructor code */
3445*0a6a1f1dSLionel Sambuc 	    symbol_destructor[i]
3446*0a6a1f1dSLionel Sambuc 		= process_destructor_XX(symbol_destructor[i], tag);
3447*0a6a1f1dSLionel Sambuc 	}
3448*0a6a1f1dSLionel Sambuc     }
3449*0a6a1f1dSLionel Sambuc     /* 'symbol_type_tag[]' elements are freed by 'free_tags()' */
3450*0a6a1f1dSLionel Sambuc     DO_FREE(symbol_type_tag);	/* no longer needed */
3451*0a6a1f1dSLionel Sambuc     if ((bp = default_destructor[UNTYPED_DEFAULT]) != NULL)
3452*0a6a1f1dSLionel Sambuc     {
3453*0a6a1f1dSLionel Sambuc 	FREE(bp->name);
3454*0a6a1f1dSLionel Sambuc 	/* 'bp->tag' is a static value, don't free */
3455*0a6a1f1dSLionel Sambuc 	FREE(bp->destructor);
3456*0a6a1f1dSLionel Sambuc 	FREE(bp);
3457*0a6a1f1dSLionel Sambuc     }
3458*0a6a1f1dSLionel Sambuc     if ((bp = default_destructor[TYPED_DEFAULT]) != NULL)
3459*0a6a1f1dSLionel Sambuc     {
3460*0a6a1f1dSLionel Sambuc 	FREE(bp->name);
3461*0a6a1f1dSLionel Sambuc 	/* 'bp->tag' is a static value, don't free */
3462*0a6a1f1dSLionel Sambuc 	FREE(bp->destructor);
3463*0a6a1f1dSLionel Sambuc 	FREE(bp);
3464*0a6a1f1dSLionel Sambuc     }
3465*0a6a1f1dSLionel Sambuc     if ((bp = default_destructor[TYPE_SPECIFIED]) != NULL)
3466*0a6a1f1dSLionel Sambuc     {
3467*0a6a1f1dSLionel Sambuc 	bucket *p;
3468*0a6a1f1dSLionel Sambuc 	for (; bp; bp = p)
3469*0a6a1f1dSLionel Sambuc 	{
3470*0a6a1f1dSLionel Sambuc 	    p = bp->link;
3471*0a6a1f1dSLionel Sambuc 	    FREE(bp->name);
3472*0a6a1f1dSLionel Sambuc 	    /* 'bp->tag' freed by 'free_tags()' */
3473*0a6a1f1dSLionel Sambuc 	    FREE(bp->destructor);
3474*0a6a1f1dSLionel Sambuc 	    FREE(bp);
3475*0a6a1f1dSLionel Sambuc 	}
3476*0a6a1f1dSLionel Sambuc     }
3477*0a6a1f1dSLionel Sambuc }
3478*0a6a1f1dSLionel Sambuc #endif /* defined(YYBTYACC) */
3479*0a6a1f1dSLionel Sambuc 
34804a17663cSThomas Veerman void
reader(void)34814a17663cSThomas Veerman reader(void)
34824a17663cSThomas Veerman {
34834a17663cSThomas Veerman     write_section(code_file, banner);
34844a17663cSThomas Veerman     create_symbol_table();
34854a17663cSThomas Veerman     read_declarations();
34864a17663cSThomas Veerman     read_grammar();
34874a17663cSThomas Veerman     free_symbol_table();
34884a17663cSThomas Veerman     pack_names();
34894a17663cSThomas Veerman     check_symbols();
34904a17663cSThomas Veerman     pack_symbols();
34914a17663cSThomas Veerman     pack_grammar();
34924a17663cSThomas Veerman     free_symbols();
34934a17663cSThomas Veerman     print_grammar();
3494*0a6a1f1dSLionel Sambuc #if defined(YYBTYACC)
3495*0a6a1f1dSLionel Sambuc     if (destructor)
3496*0a6a1f1dSLionel Sambuc 	finalize_destructors();
3497*0a6a1f1dSLionel Sambuc #endif
3498*0a6a1f1dSLionel Sambuc     free_tags();
34994a17663cSThomas Veerman }
35004a17663cSThomas Veerman 
35014a17663cSThomas Veerman #ifdef NO_LEAKS
35024a17663cSThomas Veerman static param *
free_declarations(param * list)35034a17663cSThomas Veerman free_declarations(param * list)
35044a17663cSThomas Veerman {
35054a17663cSThomas Veerman     while (list != 0)
35064a17663cSThomas Veerman     {
35074a17663cSThomas Veerman 	param *next = list->next;
35084a17663cSThomas Veerman 	free(list->type);
35094a17663cSThomas Veerman 	free(list->name);
35104a17663cSThomas Veerman 	free(list->type2);
35114a17663cSThomas Veerman 	free(list);
35124a17663cSThomas Veerman 	list = next;
35134a17663cSThomas Veerman     }
35144a17663cSThomas Veerman     return list;
35154a17663cSThomas Veerman }
35164a17663cSThomas Veerman 
35174a17663cSThomas Veerman void
reader_leaks(void)35184a17663cSThomas Veerman reader_leaks(void)
35194a17663cSThomas Veerman {
35204a17663cSThomas Veerman     lex_param = free_declarations(lex_param);
35214a17663cSThomas Veerman     parse_param = free_declarations(parse_param);
35224a17663cSThomas Veerman 
35234a17663cSThomas Veerman     DO_FREE(line);
35244a17663cSThomas Veerman     DO_FREE(rrhs);
35254a17663cSThomas Veerman     DO_FREE(rlhs);
35264a17663cSThomas Veerman     DO_FREE(rprec);
35274a17663cSThomas Veerman     DO_FREE(ritem);
35284a17663cSThomas Veerman     DO_FREE(rassoc);
35294a17663cSThomas Veerman     DO_FREE(cache);
35304a17663cSThomas Veerman     DO_FREE(name_pool);
35314a17663cSThomas Veerman     DO_FREE(symbol_name);
35324a17663cSThomas Veerman     DO_FREE(symbol_prec);
35334a17663cSThomas Veerman     DO_FREE(symbol_assoc);
35344a17663cSThomas Veerman     DO_FREE(symbol_value);
3535*0a6a1f1dSLionel Sambuc #if defined(YYBTYACC)
3536*0a6a1f1dSLionel Sambuc     DO_FREE(symbol_pval);
3537*0a6a1f1dSLionel Sambuc     DO_FREE(symbol_destructor);
3538*0a6a1f1dSLionel Sambuc     DO_FREE(symbol_type_tag);
3539*0a6a1f1dSLionel Sambuc #endif
35404a17663cSThomas Veerman }
35414a17663cSThomas Veerman #endif
3542