xref: /freebsd/contrib/byacc/reader.c (revision 822ca3276345b4a67ccbc9b54616d8b205fd37f2)
1*822ca327SBaptiste Daroussin /* $Id: reader.c,v 1.104 2023/05/18 21:18:17 tom Exp $ */
298e903e7SBaptiste Daroussin 
398e903e7SBaptiste Daroussin #include "defs.h"
498e903e7SBaptiste Daroussin 
598e903e7SBaptiste Daroussin /*  The line size must be a positive integer.  One hundred was chosen	*/
698e903e7SBaptiste Daroussin /*  because few lines in Yacc input grammars exceed 100 characters.	*/
798e903e7SBaptiste Daroussin /*  Note that if a line exceeds LINESIZE characters, the line buffer	*/
8b53bb29fSJung-uk Kim /*  will be expanded to accommodate it.					*/
998e903e7SBaptiste Daroussin 
1098e903e7SBaptiste Daroussin #define LINESIZE 100
1198e903e7SBaptiste Daroussin 
1298e903e7SBaptiste Daroussin #define L_CURL  '{'
1398e903e7SBaptiste Daroussin #define R_CURL  '}'
140c8de5b0SBaptiste Daroussin #define L_PAREN '('
150c8de5b0SBaptiste Daroussin #define R_PAREN ')'
160c8de5b0SBaptiste Daroussin #define L_BRAC  '['
170c8de5b0SBaptiste Daroussin #define R_BRAC  ']'
180c8de5b0SBaptiste Daroussin 
190c8de5b0SBaptiste Daroussin /* the maximum number of arguments (inherited attributes) to a non-terminal */
200c8de5b0SBaptiste Daroussin /* this is a hard limit, but seems more than adequate */
210c8de5b0SBaptiste Daroussin #define MAXARGS	20
2298e903e7SBaptiste Daroussin 
23*822ca327SBaptiste Daroussin /* limit the size of optional names for %union */
24*822ca327SBaptiste Daroussin #define NAME_LEN 32
25*822ca327SBaptiste Daroussin 
26*822ca327SBaptiste Daroussin #define IS_ALNUM(c) (isalnum(c) || (c) == '_')
27*822ca327SBaptiste Daroussin 
288e022d3cSDag-Erling Smørgrav #define begin_case(f,n) fprintf(f, "case %d:\n", (int)(n))
298e022d3cSDag-Erling Smørgrav 
308e022d3cSDag-Erling Smørgrav #define end_case(f) \
318e022d3cSDag-Erling Smørgrav 	    fprintf(f, "\n"); \
328e022d3cSDag-Erling Smørgrav 	    fprintf_lineno(f, 1, ""); \
338e022d3cSDag-Erling Smørgrav 	    fprintf(f, "break;\n")
348e022d3cSDag-Erling Smørgrav 
35*822ca327SBaptiste Daroussin #define begin_ainfo(data, offset) do { \
36*822ca327SBaptiste Daroussin 	    data.a_lineno = lineno; \
37*822ca327SBaptiste Daroussin 	    data.a_line = dup_line(); \
38*822ca327SBaptiste Daroussin 	    data.a_cptr = data.a_line + (cptr - line - offset); \
39*822ca327SBaptiste Daroussin 	} while (0)
40*822ca327SBaptiste Daroussin 
41*822ca327SBaptiste Daroussin #define end_ainfo(data) do { \
42*822ca327SBaptiste Daroussin 	    FREE(data.a_line); \
43*822ca327SBaptiste Daroussin 	    memset(&data, 0, sizeof(data)); \
44*822ca327SBaptiste Daroussin 	} while (0)
45*822ca327SBaptiste Daroussin 
4698e903e7SBaptiste Daroussin static void start_rule(bucket *bp, int s_lineno);
470c8de5b0SBaptiste Daroussin #if defined(YYBTYACC)
482aca18c7SJung-uk Kim static void copy_initial_action(void);
490c8de5b0SBaptiste Daroussin static void copy_destructor(void);
500c8de5b0SBaptiste Daroussin static char *process_destructor_XX(char *code, char *tag);
510c8de5b0SBaptiste Daroussin #endif
5298e903e7SBaptiste Daroussin 
530f86d14eSJung-uk Kim #define CACHE_SIZE 256
5498e903e7SBaptiste Daroussin static char *cache;
5598e903e7SBaptiste Daroussin static int cinc, cache_size;
5698e903e7SBaptiste Daroussin 
5798e903e7SBaptiste Daroussin int ntags;
580c8de5b0SBaptiste Daroussin static int tagmax, havetags;
5998e903e7SBaptiste Daroussin static char **tag_table;
6098e903e7SBaptiste Daroussin 
6198e903e7SBaptiste Daroussin static char saw_eof;
6298e903e7SBaptiste Daroussin char unionized;
63*822ca327SBaptiste Daroussin 
64*822ca327SBaptiste Daroussin char *line;		/* current input-line */
65*822ca327SBaptiste Daroussin char *cptr;		/* position within current input-line */
66*822ca327SBaptiste Daroussin static size_t linesize;	/* length of current input-line */
67*822ca327SBaptiste Daroussin 
68*822ca327SBaptiste Daroussin typedef struct
69*822ca327SBaptiste Daroussin {
70*822ca327SBaptiste Daroussin     char *line_data;	/* saved input-line */
71*822ca327SBaptiste Daroussin     size_t line_used;	/* position within saved input-line */
72*822ca327SBaptiste Daroussin     size_t line_size;	/* length of saved input-line */
73*822ca327SBaptiste Daroussin     fpos_t line_fpos;	/* pointer before reading past saved input-line */
74*822ca327SBaptiste Daroussin }
75*822ca327SBaptiste Daroussin SAVE_LINE;
76*822ca327SBaptiste Daroussin 
77*822ca327SBaptiste Daroussin static SAVE_LINE save_area;
78*822ca327SBaptiste Daroussin static int must_save;	/* request > 0, triggered < 0, inactive 0 */
7998e903e7SBaptiste Daroussin 
8098e903e7SBaptiste Daroussin static bucket *goal;
8198e903e7SBaptiste Daroussin static Value_t prec;
8298e903e7SBaptiste Daroussin static int gensym;
8398e903e7SBaptiste Daroussin static char last_was_action;
84c5b5d71aSJung-uk Kim #if defined(YYBTYACC)
85c5b5d71aSJung-uk Kim static int trialaction;
86c5b5d71aSJung-uk Kim #endif
8798e903e7SBaptiste Daroussin 
8898e903e7SBaptiste Daroussin static int maxitems;
8998e903e7SBaptiste Daroussin static bucket **pitem;
9098e903e7SBaptiste Daroussin 
9198e903e7SBaptiste Daroussin static int maxrules;
9298e903e7SBaptiste Daroussin static bucket **plhs;
9398e903e7SBaptiste Daroussin 
9498e903e7SBaptiste Daroussin static size_t name_pool_size;
9598e903e7SBaptiste Daroussin static char *name_pool;
9698e903e7SBaptiste Daroussin 
9798e903e7SBaptiste Daroussin char line_format[] = "#line %d \"%s\"\n";
9898e903e7SBaptiste Daroussin 
9998e903e7SBaptiste Daroussin param *lex_param;
10098e903e7SBaptiste Daroussin param *parse_param;
10198e903e7SBaptiste Daroussin 
102b53bb29fSJung-uk Kim static const char *code_keys[] =
103b53bb29fSJung-uk Kim {
104b53bb29fSJung-uk Kim     "", "requires", "provides", "top", "imports",
105b53bb29fSJung-uk Kim };
106b53bb29fSJung-uk Kim 
107b53bb29fSJung-uk Kim struct code_lines code_lines[CODE_MAX];
108b53bb29fSJung-uk Kim 
1090c8de5b0SBaptiste Daroussin #if defined(YYBTYACC)
1100c8de5b0SBaptiste Daroussin int destructor = 0;	/* =1 if at least one %destructor */
1110c8de5b0SBaptiste Daroussin 
1120c8de5b0SBaptiste Daroussin static bucket *default_destructor[3] =
1130c8de5b0SBaptiste Daroussin {0, 0, 0};
1140c8de5b0SBaptiste Daroussin 
1150c8de5b0SBaptiste Daroussin #define UNTYPED_DEFAULT 0
1160c8de5b0SBaptiste Daroussin #define TYPED_DEFAULT   1
1170c8de5b0SBaptiste Daroussin #define TYPE_SPECIFIED  2
1180c8de5b0SBaptiste Daroussin 
1190c8de5b0SBaptiste Daroussin static bucket *
lookup_type_destructor(char * tag)1200c8de5b0SBaptiste Daroussin lookup_type_destructor(char *tag)
1210c8de5b0SBaptiste Daroussin {
12211fce282SBaptiste Daroussin     const char fmt[] = "%.*s destructor";
1230c8de5b0SBaptiste Daroussin     char name[1024] = "\0";
1240c8de5b0SBaptiste Daroussin     bucket *bp, **bpp = &default_destructor[TYPE_SPECIFIED];
1250c8de5b0SBaptiste Daroussin 
1260c8de5b0SBaptiste Daroussin     while ((bp = *bpp) != NULL)
1270c8de5b0SBaptiste Daroussin     {
1280c8de5b0SBaptiste Daroussin 	if (bp->tag == tag)
1290c8de5b0SBaptiste Daroussin 	    return (bp);
1300c8de5b0SBaptiste Daroussin 	bpp = &bp->link;
1310c8de5b0SBaptiste Daroussin     }
1320c8de5b0SBaptiste Daroussin 
13311fce282SBaptiste Daroussin     sprintf(name, fmt, (int)(sizeof(name) - sizeof(fmt)), tag);
13411fce282SBaptiste Daroussin     *bpp = bp = make_bucket(name);
1350c8de5b0SBaptiste Daroussin     bp->tag = tag;
1360c8de5b0SBaptiste Daroussin 
1370c8de5b0SBaptiste Daroussin     return (bp);
1380c8de5b0SBaptiste Daroussin }
1390c8de5b0SBaptiste Daroussin #endif /* defined(YYBTYACC) */
1400c8de5b0SBaptiste Daroussin 
14198e903e7SBaptiste Daroussin static void
cachec(int c)14298e903e7SBaptiste Daroussin cachec(int c)
14398e903e7SBaptiste Daroussin {
14498e903e7SBaptiste Daroussin     assert(cinc >= 0);
14598e903e7SBaptiste Daroussin     if (cinc >= cache_size)
14698e903e7SBaptiste Daroussin     {
1470f86d14eSJung-uk Kim 	cache_size += CACHE_SIZE;
1483e066022SBaptiste Daroussin 	cache = TREALLOC(char, cache, cache_size);
14998e903e7SBaptiste Daroussin 	NO_SPACE(cache);
15098e903e7SBaptiste Daroussin     }
15198e903e7SBaptiste Daroussin     cache[cinc] = (char)c;
15298e903e7SBaptiste Daroussin     ++cinc;
15398e903e7SBaptiste Daroussin }
15498e903e7SBaptiste Daroussin 
1553e794565SJung-uk Kim typedef enum
1563e794565SJung-uk Kim {
1573e794565SJung-uk Kim     ldSPC1,
1583e794565SJung-uk Kim     ldSPC2,
1593e794565SJung-uk Kim     ldNAME,
1603e794565SJung-uk Kim     ldSPC3,
1613e794565SJung-uk Kim     ldNUM,
1623e794565SJung-uk Kim     ldSPC4,
1633e794565SJung-uk Kim     ldFILE,
1643e794565SJung-uk Kim     ldOK,
1653e794565SJung-uk Kim     ldERR
1663e794565SJung-uk Kim }
1673e794565SJung-uk Kim LINE_DIR;
1683e794565SJung-uk Kim 
1693e794565SJung-uk Kim /*
1703e794565SJung-uk Kim  * Expect this pattern:
1713e794565SJung-uk Kim  *	/^[[:space:]]*#[[:space:]]*
1723e794565SJung-uk Kim  *	  line[[:space:]]+
1733e794565SJung-uk Kim  *	  [[:digit:]]+
1743e794565SJung-uk Kim  *	  ([[:space:]]*|[[:space:]]+"[^"]+")/
1753e794565SJung-uk Kim  */
1763e794565SJung-uk Kim static int
line_directive(void)1773e794565SJung-uk Kim line_directive(void)
1783e794565SJung-uk Kim {
1793e794565SJung-uk Kim #define UNLESS(what) if (what) { ld = ldERR; break; }
1803e794565SJung-uk Kim     int n;
1813e794565SJung-uk Kim     int line_1st = -1;
1823e794565SJung-uk Kim     int name_1st = -1;
1833e794565SJung-uk Kim     int name_end = -1;
1843e794565SJung-uk Kim     LINE_DIR ld = ldSPC1;
1853e794565SJung-uk Kim     for (n = 0; (ld <= ldOK) && (line[n] != '\0'); ++n)
1863e794565SJung-uk Kim     {
1873e794565SJung-uk Kim 	int ch = UCH(line[n]);
1883e794565SJung-uk Kim 	switch (ld)
1893e794565SJung-uk Kim 	{
1903e794565SJung-uk Kim 	case ldSPC1:
191b53bb29fSJung-uk Kim 	    if (isspace(UCH(ch)))
1923e794565SJung-uk Kim 	    {
1933e794565SJung-uk Kim 		break;
1943e794565SJung-uk Kim 	    }
1953e794565SJung-uk Kim 	    else
1963e794565SJung-uk Kim 		UNLESS(ch != '#');
1973e794565SJung-uk Kim 	    ld = ldSPC2;
1983e794565SJung-uk Kim 	    break;
1993e794565SJung-uk Kim 	case ldSPC2:
200b53bb29fSJung-uk Kim 	    if (isspace(UCH(ch)))
2013e794565SJung-uk Kim 	    {
2023e794565SJung-uk Kim 		break;
2033e794565SJung-uk Kim 	    }
2043e794565SJung-uk Kim 	    /* FALLTHRU */
2053e794565SJung-uk Kim 	case ldNAME:
2063e794565SJung-uk Kim 	    UNLESS(strncmp(line + n, "line", 4));
2073e794565SJung-uk Kim 	    n += 4;
2083e794565SJung-uk Kim 	    if (line[n] == '\0')
2093e794565SJung-uk Kim 	    {
2103e794565SJung-uk Kim 		ld = ldOK;
2113e794565SJung-uk Kim 		break;
2123e794565SJung-uk Kim 	    }
2133e794565SJung-uk Kim 	    else
2143e794565SJung-uk Kim 		UNLESS(!isspace(UCH(line[n])));
2153e794565SJung-uk Kim 	    ld = ldSPC3;
2163e794565SJung-uk Kim 	    break;
2173e794565SJung-uk Kim 	case ldSPC3:
218b53bb29fSJung-uk Kim 	    if (isspace(UCH(ch)))
2193e794565SJung-uk Kim 	    {
2203e794565SJung-uk Kim 		break;
2213e794565SJung-uk Kim 	    }
2223e794565SJung-uk Kim 	    else
223b53bb29fSJung-uk Kim 		UNLESS(!isdigit(UCH(ch)));
2243e794565SJung-uk Kim 	    line_1st = n;
2258e022d3cSDag-Erling Smørgrav 	    ld = ldNUM;		/* this is needed, but cppcheck says no... */
2263e794565SJung-uk Kim 	    /* FALLTHRU */
2273e794565SJung-uk Kim 	case ldNUM:
228b53bb29fSJung-uk Kim 	    if (isdigit(UCH(ch)))
2293e794565SJung-uk Kim 	    {
2303e794565SJung-uk Kim 		break;
2313e794565SJung-uk Kim 	    }
2323e794565SJung-uk Kim 	    else
233b53bb29fSJung-uk Kim 		UNLESS(!isspace(UCH(ch)));
2343e794565SJung-uk Kim 	    ld = ldSPC4;
2353e794565SJung-uk Kim 	    break;
2363e794565SJung-uk Kim 	case ldSPC4:
237b53bb29fSJung-uk Kim 	    if (isspace(UCH(ch)))
2383e794565SJung-uk Kim 	    {
2393e794565SJung-uk Kim 		break;
2403e794565SJung-uk Kim 	    }
2413e794565SJung-uk Kim 	    else
2423e794565SJung-uk Kim 		UNLESS(ch != '"');
2433e794565SJung-uk Kim 	    UNLESS(line[n + 1] == '"');
2443e794565SJung-uk Kim 	    ld = ldFILE;
2453e794565SJung-uk Kim 	    name_1st = n;
2463e794565SJung-uk Kim 	    break;
2473e794565SJung-uk Kim 	case ldFILE:
2483e794565SJung-uk Kim 	    if (ch != '"')
2493e794565SJung-uk Kim 	    {
2503e794565SJung-uk Kim 		break;
2513e794565SJung-uk Kim 	    }
2523e794565SJung-uk Kim 	    ld = ldOK;
2533e794565SJung-uk Kim 	    name_end = n;
2543e794565SJung-uk Kim 	    /* FALLTHRU */
2553e794565SJung-uk Kim 	case ldERR:
2563e794565SJung-uk Kim 	case ldOK:
2573e794565SJung-uk Kim 	    break;
2583e794565SJung-uk Kim 	}
2593e794565SJung-uk Kim     }
2603e794565SJung-uk Kim 
2613e794565SJung-uk Kim     if (ld == ldOK)
2623e794565SJung-uk Kim     {
2633e794565SJung-uk Kim 	size_t need = (size_t)(name_end - name_1st);
264b53bb29fSJung-uk Kim 	if ((long)need > (long)input_file_name_len)
2653e794565SJung-uk Kim 	{
266b53bb29fSJung-uk Kim 	    input_file_name_len = ((need + 1) * 3) / 2;
267b53bb29fSJung-uk Kim 	    input_file_name = TREALLOC(char, input_file_name, input_file_name_len);
2683e794565SJung-uk Kim 	    NO_SPACE(input_file_name);
2693e794565SJung-uk Kim 	}
270b53bb29fSJung-uk Kim 	if ((long)need > 0)
271b53bb29fSJung-uk Kim 	{
2723e794565SJung-uk Kim 	    memcpy(input_file_name, line + name_1st + 1, need - 1);
2733e794565SJung-uk Kim 	    input_file_name[need - 1] = '\0';
2743e794565SJung-uk Kim 	}
275b53bb29fSJung-uk Kim 	else
276b53bb29fSJung-uk Kim 	{
277b53bb29fSJung-uk Kim 	    input_file_name[0] = '\0';
278b53bb29fSJung-uk Kim 	}
279b53bb29fSJung-uk Kim     }
2803e794565SJung-uk Kim 
2813e794565SJung-uk Kim     if (ld >= ldNUM && ld < ldERR)
2823e794565SJung-uk Kim     {
283b53bb29fSJung-uk Kim 	if (line_1st >= 0)
284b53bb29fSJung-uk Kim 	{
2853e794565SJung-uk Kim 	    lineno = (int)strtol(line + line_1st, NULL, 10) - 1;
2863e794565SJung-uk Kim 	}
287b53bb29fSJung-uk Kim 	else
288b53bb29fSJung-uk Kim 	{
289b53bb29fSJung-uk Kim 	    lineno = 0;
290b53bb29fSJung-uk Kim 	}
291b53bb29fSJung-uk Kim     }
2923e794565SJung-uk Kim 
2933e794565SJung-uk Kim     return (ld == ldOK);
2943e794565SJung-uk Kim #undef UNLESS
2953e794565SJung-uk Kim }
2963e794565SJung-uk Kim 
29798e903e7SBaptiste Daroussin static void
save_line(void)298*822ca327SBaptiste Daroussin save_line(void)
299*822ca327SBaptiste Daroussin {
300*822ca327SBaptiste Daroussin     /* remember to save the input-line if we call get_line() */
301*822ca327SBaptiste Daroussin     if (!must_save)
302*822ca327SBaptiste Daroussin     {
303*822ca327SBaptiste Daroussin 	must_save = 1;
304*822ca327SBaptiste Daroussin 	save_area.line_used = (size_t)(cptr - line);
305*822ca327SBaptiste Daroussin     }
306*822ca327SBaptiste Daroussin }
307*822ca327SBaptiste Daroussin 
308*822ca327SBaptiste Daroussin static void
restore_line(void)309*822ca327SBaptiste Daroussin restore_line(void)
310*822ca327SBaptiste Daroussin {
311*822ca327SBaptiste Daroussin     /* if we saved the line, restore it */
312*822ca327SBaptiste Daroussin     if (must_save < 0)
313*822ca327SBaptiste Daroussin     {
314*822ca327SBaptiste Daroussin 	free(line);
315*822ca327SBaptiste Daroussin 	line = save_area.line_data;
316*822ca327SBaptiste Daroussin 	cptr = save_area.line_used + line;
317*822ca327SBaptiste Daroussin 	linesize = save_area.line_size;
318*822ca327SBaptiste Daroussin 	if (fsetpos(input_file, &save_area.line_fpos) != 0)
319*822ca327SBaptiste Daroussin 	    on_error();
320*822ca327SBaptiste Daroussin 	memset(&save_area, 0, sizeof(save_area));
321*822ca327SBaptiste Daroussin     }
322*822ca327SBaptiste Daroussin     else if (must_save > 0)
323*822ca327SBaptiste Daroussin     {
324*822ca327SBaptiste Daroussin 	cptr = line + save_area.line_used;
325*822ca327SBaptiste Daroussin     }
326*822ca327SBaptiste Daroussin     must_save = 0;
327*822ca327SBaptiste Daroussin }
328*822ca327SBaptiste Daroussin 
329*822ca327SBaptiste Daroussin static void
get_line(void)33098e903e7SBaptiste Daroussin get_line(void)
33198e903e7SBaptiste Daroussin {
33298e903e7SBaptiste Daroussin     FILE *f = input_file;
33398e903e7SBaptiste Daroussin 
334*822ca327SBaptiste Daroussin     if (must_save > 0)
335*822ca327SBaptiste Daroussin     {
336*822ca327SBaptiste Daroussin 	save_area.line_data = TMALLOC(char, linesize);
337*822ca327SBaptiste Daroussin 	save_area.line_used = (size_t)(cptr - line);
338*822ca327SBaptiste Daroussin 	save_area.line_size = linesize;
339*822ca327SBaptiste Daroussin 	NO_SPACE(save_area.line_data);
340*822ca327SBaptiste Daroussin 	memcpy(save_area.line_data, line, linesize);
341*822ca327SBaptiste Daroussin 	if (fgetpos(f, &save_area.line_fpos) != 0)
342*822ca327SBaptiste Daroussin 	    on_error();
343*822ca327SBaptiste Daroussin 	must_save = -must_save;
344*822ca327SBaptiste Daroussin     }
345*822ca327SBaptiste Daroussin 
3463e794565SJung-uk Kim     do
3473e794565SJung-uk Kim     {
3488e022d3cSDag-Erling Smørgrav 	int c;
349*822ca327SBaptiste Daroussin 	size_t i;
3508e022d3cSDag-Erling Smørgrav 
35198e903e7SBaptiste Daroussin 	if (saw_eof || (c = getc(f)) == EOF)
35298e903e7SBaptiste Daroussin 	{
35398e903e7SBaptiste Daroussin 	    if (line)
35498e903e7SBaptiste Daroussin 	    {
35598e903e7SBaptiste Daroussin 		FREE(line);
35698e903e7SBaptiste Daroussin 		line = 0;
35798e903e7SBaptiste Daroussin 	    }
35898e903e7SBaptiste Daroussin 	    cptr = 0;
35998e903e7SBaptiste Daroussin 	    saw_eof = 1;
36098e903e7SBaptiste Daroussin 	    return;
36198e903e7SBaptiste Daroussin 	}
36298e903e7SBaptiste Daroussin 
363c5b5d71aSJung-uk Kim 	if (line == NULL || linesize != (LINESIZE + 1))
36498e903e7SBaptiste Daroussin 	{
36598e903e7SBaptiste Daroussin 	    if (line)
36698e903e7SBaptiste Daroussin 		FREE(line);
36798e903e7SBaptiste Daroussin 	    linesize = LINESIZE + 1;
368315e69cbSBaptiste Daroussin 	    line = TMALLOC(char, linesize);
36998e903e7SBaptiste Daroussin 	    NO_SPACE(line);
37098e903e7SBaptiste Daroussin 	}
37198e903e7SBaptiste Daroussin 
37298e903e7SBaptiste Daroussin 	i = 0;
37398e903e7SBaptiste Daroussin 	++lineno;
37498e903e7SBaptiste Daroussin 	for (;;)
37598e903e7SBaptiste Daroussin 	{
376315e69cbSBaptiste Daroussin 	    line[i++] = (char)c;
37798e903e7SBaptiste Daroussin 	    if (c == '\n')
3780c8de5b0SBaptiste Daroussin 		break;
379315e69cbSBaptiste Daroussin 	    if ((i + 3) >= linesize)
38098e903e7SBaptiste Daroussin 	    {
38198e903e7SBaptiste Daroussin 		linesize += LINESIZE;
3823e066022SBaptiste Daroussin 		line = TREALLOC(char, line, linesize);
38398e903e7SBaptiste Daroussin 		NO_SPACE(line);
38498e903e7SBaptiste Daroussin 	    }
38598e903e7SBaptiste Daroussin 	    c = getc(f);
38698e903e7SBaptiste Daroussin 	    if (c == EOF)
38798e903e7SBaptiste Daroussin 	    {
388315e69cbSBaptiste Daroussin 		line[i++] = '\n';
38998e903e7SBaptiste Daroussin 		saw_eof = 1;
3900c8de5b0SBaptiste Daroussin 		break;
3910c8de5b0SBaptiste Daroussin 	    }
3920c8de5b0SBaptiste Daroussin 	}
393315e69cbSBaptiste Daroussin 	line[i] = '\0';
3943e794565SJung-uk Kim     }
3953e794565SJung-uk Kim     while (line_directive());
39698e903e7SBaptiste Daroussin     cptr = line;
39798e903e7SBaptiste Daroussin     return;
39898e903e7SBaptiste Daroussin }
39998e903e7SBaptiste Daroussin 
40098e903e7SBaptiste Daroussin static char *
dup_line(void)40198e903e7SBaptiste Daroussin dup_line(void)
40298e903e7SBaptiste Daroussin {
40398e903e7SBaptiste Daroussin     char *p, *s, *t;
40498e903e7SBaptiste Daroussin 
405c5b5d71aSJung-uk Kim     if (line == NULL)
406c5b5d71aSJung-uk Kim 	return (NULL);
40798e903e7SBaptiste Daroussin     s = line;
40898e903e7SBaptiste Daroussin     while (*s != '\n')
40998e903e7SBaptiste Daroussin 	++s;
4103e066022SBaptiste Daroussin     p = TMALLOC(char, s - line + 1);
41198e903e7SBaptiste Daroussin     NO_SPACE(p);
41298e903e7SBaptiste Daroussin 
41398e903e7SBaptiste Daroussin     s = line;
41498e903e7SBaptiste Daroussin     t = p;
41598e903e7SBaptiste Daroussin     while ((*t++ = *s++) != '\n')
41698e903e7SBaptiste Daroussin 	continue;
41798e903e7SBaptiste Daroussin     return (p);
41898e903e7SBaptiste Daroussin }
41998e903e7SBaptiste Daroussin 
42098e903e7SBaptiste Daroussin static void
skip_comment(void)42198e903e7SBaptiste Daroussin skip_comment(void)
42298e903e7SBaptiste Daroussin {
42398e903e7SBaptiste Daroussin     char *s;
4242aca18c7SJung-uk Kim     struct ainfo a;
425*822ca327SBaptiste Daroussin 
426*822ca327SBaptiste Daroussin     begin_ainfo(a, 0);
42798e903e7SBaptiste Daroussin 
42898e903e7SBaptiste Daroussin     s = cptr + 2;
42998e903e7SBaptiste Daroussin     for (;;)
43098e903e7SBaptiste Daroussin     {
43198e903e7SBaptiste Daroussin 	if (*s == '*' && s[1] == '/')
43298e903e7SBaptiste Daroussin 	{
43398e903e7SBaptiste Daroussin 	    cptr = s + 2;
434*822ca327SBaptiste Daroussin 	    end_ainfo(a);
43598e903e7SBaptiste Daroussin 	    return;
43698e903e7SBaptiste Daroussin 	}
43798e903e7SBaptiste Daroussin 	if (*s == '\n')
43898e903e7SBaptiste Daroussin 	{
43998e903e7SBaptiste Daroussin 	    get_line();
440c5b5d71aSJung-uk Kim 	    if (line == NULL)
4412aca18c7SJung-uk Kim 		unterminated_comment(&a);
44298e903e7SBaptiste Daroussin 	    s = cptr;
44398e903e7SBaptiste Daroussin 	}
44498e903e7SBaptiste Daroussin 	else
44598e903e7SBaptiste Daroussin 	    ++s;
44698e903e7SBaptiste Daroussin     }
44798e903e7SBaptiste Daroussin }
44898e903e7SBaptiste Daroussin 
44998e903e7SBaptiste Daroussin static int
next_inline(void)45011fce282SBaptiste Daroussin next_inline(void)
45198e903e7SBaptiste Daroussin {
45298e903e7SBaptiste Daroussin     char *s;
45398e903e7SBaptiste Daroussin 
454c5b5d71aSJung-uk Kim     if (line == NULL)
45598e903e7SBaptiste Daroussin     {
45698e903e7SBaptiste Daroussin 	get_line();
457c5b5d71aSJung-uk Kim 	if (line == NULL)
45898e903e7SBaptiste Daroussin 	    return (EOF);
45998e903e7SBaptiste Daroussin     }
46098e903e7SBaptiste Daroussin 
46198e903e7SBaptiste Daroussin     s = cptr;
46298e903e7SBaptiste Daroussin     for (;;)
46398e903e7SBaptiste Daroussin     {
46498e903e7SBaptiste Daroussin 	switch (*s)
46598e903e7SBaptiste Daroussin 	{
46698e903e7SBaptiste Daroussin 	case '/':
46798e903e7SBaptiste Daroussin 	    if (s[1] == '*')
46898e903e7SBaptiste Daroussin 	    {
46998e903e7SBaptiste Daroussin 		cptr = s;
47098e903e7SBaptiste Daroussin 		skip_comment();
47198e903e7SBaptiste Daroussin 		s = cptr;
47298e903e7SBaptiste Daroussin 		break;
47398e903e7SBaptiste Daroussin 	    }
47498e903e7SBaptiste Daroussin 	    else if (s[1] == '/')
47598e903e7SBaptiste Daroussin 	    {
47698e903e7SBaptiste Daroussin 		get_line();
477c5b5d71aSJung-uk Kim 		if (line == NULL)
47898e903e7SBaptiste Daroussin 		    return (EOF);
47998e903e7SBaptiste Daroussin 		s = cptr;
48098e903e7SBaptiste Daroussin 		break;
48198e903e7SBaptiste Daroussin 	    }
48298e903e7SBaptiste Daroussin 	    /* FALLTHRU */
48398e903e7SBaptiste Daroussin 
48498e903e7SBaptiste Daroussin 	default:
48598e903e7SBaptiste Daroussin 	    cptr = s;
48698e903e7SBaptiste Daroussin 	    return (*s);
48798e903e7SBaptiste Daroussin 	}
48898e903e7SBaptiste Daroussin     }
48998e903e7SBaptiste Daroussin }
49011fce282SBaptiste Daroussin 
49111fce282SBaptiste Daroussin static int
nextc(void)49211fce282SBaptiste Daroussin nextc(void)
49311fce282SBaptiste Daroussin {
49411fce282SBaptiste Daroussin     int ch;
49511fce282SBaptiste Daroussin     int finish = 0;
49611fce282SBaptiste Daroussin 
49711fce282SBaptiste Daroussin     do
49811fce282SBaptiste Daroussin     {
49911fce282SBaptiste Daroussin 	switch (ch = next_inline())
50011fce282SBaptiste Daroussin 	{
501*822ca327SBaptiste Daroussin 	case '\0':
50211fce282SBaptiste Daroussin 	case '\n':
50311fce282SBaptiste Daroussin 	    get_line();
50411fce282SBaptiste Daroussin 	    break;
50511fce282SBaptiste Daroussin 	case ' ':
50611fce282SBaptiste Daroussin 	case '\t':
50711fce282SBaptiste Daroussin 	case '\f':
50811fce282SBaptiste Daroussin 	case '\r':
50911fce282SBaptiste Daroussin 	case '\v':
51011fce282SBaptiste Daroussin 	case ',':
51111fce282SBaptiste Daroussin 	case ';':
51211fce282SBaptiste Daroussin 	    ++cptr;
51311fce282SBaptiste Daroussin 	    break;
51411fce282SBaptiste Daroussin 	case '\\':
51511fce282SBaptiste Daroussin 	    ch = '%';
51611fce282SBaptiste Daroussin 	    /* FALLTHRU */
51711fce282SBaptiste Daroussin 	default:
51811fce282SBaptiste Daroussin 	    finish = 1;
51911fce282SBaptiste Daroussin 	    break;
52011fce282SBaptiste Daroussin 	}
52111fce282SBaptiste Daroussin     }
52211fce282SBaptiste Daroussin     while (!finish);
52311fce282SBaptiste Daroussin 
52411fce282SBaptiste Daroussin     return ch;
52511fce282SBaptiste Daroussin }
5260c8de5b0SBaptiste Daroussin /* *INDENT-OFF* */
5270c8de5b0SBaptiste Daroussin static struct keyword
5280c8de5b0SBaptiste Daroussin {
529b53bb29fSJung-uk Kim     char name[16];
5300c8de5b0SBaptiste Daroussin     int token;
5310c8de5b0SBaptiste Daroussin }
5320c8de5b0SBaptiste Daroussin keywords[] = {
5330c8de5b0SBaptiste Daroussin     { "binary",      NONASSOC },
534b53bb29fSJung-uk Kim     { "code",        XCODE },
5358e022d3cSDag-Erling Smørgrav     { "debug",       NONPOSIX_DEBUG },
536*822ca327SBaptiste Daroussin     { "define",      HACK_DEFINE },
5370c8de5b0SBaptiste Daroussin #if defined(YYBTYACC)
5380c8de5b0SBaptiste Daroussin     { "destructor",  DESTRUCTOR },
5390c8de5b0SBaptiste Daroussin #endif
5402aca18c7SJung-uk Kim     { "error-verbose",ERROR_VERBOSE },
5410c8de5b0SBaptiste Daroussin     { "expect",      EXPECT },
5420c8de5b0SBaptiste Daroussin     { "expect-rr",   EXPECT_RR },
5430c8de5b0SBaptiste Daroussin     { "ident",       IDENT },
5442aca18c7SJung-uk Kim #if defined(YYBTYACC)
5452aca18c7SJung-uk Kim     { "initial-action", INITIAL_ACTION },
5462aca18c7SJung-uk Kim #endif
5470c8de5b0SBaptiste Daroussin     { "left",        LEFT },
5480c8de5b0SBaptiste Daroussin     { "lex-param",   LEX_PARAM },
5490c8de5b0SBaptiste Daroussin #if defined(YYBTYACC)
5500c8de5b0SBaptiste Daroussin     { "locations",   LOCATIONS },
5510c8de5b0SBaptiste Daroussin #endif
5520c8de5b0SBaptiste Daroussin     { "nonassoc",    NONASSOC },
553*822ca327SBaptiste Daroussin     { "nterm",       TYPE },
5540c8de5b0SBaptiste Daroussin     { "parse-param", PARSE_PARAM },
5550c8de5b0SBaptiste Daroussin     { "pure-parser", PURE_PARSER },
5560c8de5b0SBaptiste Daroussin     { "right",       RIGHT },
5570c8de5b0SBaptiste Daroussin     { "start",       START },
5580c8de5b0SBaptiste Daroussin     { "term",        TOKEN },
5590c8de5b0SBaptiste Daroussin     { "token",       TOKEN },
5600c8de5b0SBaptiste Daroussin     { "token-table", TOKEN_TABLE },
5610c8de5b0SBaptiste Daroussin     { "type",        TYPE },
5620c8de5b0SBaptiste Daroussin     { "union",       UNION },
5630c8de5b0SBaptiste Daroussin     { "yacc",        POSIX_YACC },
5640c8de5b0SBaptiste Daroussin };
5650c8de5b0SBaptiste Daroussin /* *INDENT-ON* */
56698e903e7SBaptiste Daroussin 
56798e903e7SBaptiste Daroussin static int
compare_keys(const void * a,const void * b)5680c8de5b0SBaptiste Daroussin compare_keys(const void *a, const void *b)
56998e903e7SBaptiste Daroussin {
5700c8de5b0SBaptiste Daroussin     const struct keyword *p = (const struct keyword *)a;
5710c8de5b0SBaptiste Daroussin     const struct keyword *q = (const struct keyword *)b;
5720c8de5b0SBaptiste Daroussin     return strcmp(p->name, q->name);
57398e903e7SBaptiste Daroussin }
57498e903e7SBaptiste Daroussin 
57598e903e7SBaptiste Daroussin static int
keyword(void)57698e903e7SBaptiste Daroussin keyword(void)
57798e903e7SBaptiste Daroussin {
57898e903e7SBaptiste Daroussin     int c;
57998e903e7SBaptiste Daroussin     char *t_cptr = cptr;
58098e903e7SBaptiste Daroussin 
58198e903e7SBaptiste Daroussin     c = *++cptr;
582b53bb29fSJung-uk Kim     if (isalpha(UCH(c)))
58398e903e7SBaptiste Daroussin     {
5848e022d3cSDag-Erling Smørgrav 	struct keyword *key;
5858e022d3cSDag-Erling Smørgrav 
58698e903e7SBaptiste Daroussin 	cinc = 0;
58798e903e7SBaptiste Daroussin 	for (;;)
58898e903e7SBaptiste Daroussin 	{
589b53bb29fSJung-uk Kim 	    if (isalpha(UCH(c)))
59098e903e7SBaptiste Daroussin 	    {
591b53bb29fSJung-uk Kim 		if (isupper(UCH(c)))
59298e903e7SBaptiste Daroussin 		    c = tolower(c);
59398e903e7SBaptiste Daroussin 		cachec(c);
59498e903e7SBaptiste Daroussin 	    }
595b53bb29fSJung-uk Kim 	    else if (isdigit(UCH(c))
59698e903e7SBaptiste Daroussin 		     || c == '-'
59798e903e7SBaptiste Daroussin 		     || c == '.'
59898e903e7SBaptiste Daroussin 		     || c == '$')
59998e903e7SBaptiste Daroussin 	    {
60098e903e7SBaptiste Daroussin 		cachec(c);
60198e903e7SBaptiste Daroussin 	    }
6020c8de5b0SBaptiste Daroussin 	    else if (c == '_')
6030c8de5b0SBaptiste Daroussin 	    {
6040c8de5b0SBaptiste Daroussin 		/* treat keywords spelled with '_' as if it were '-' */
6050c8de5b0SBaptiste Daroussin 		cachec('-');
6060c8de5b0SBaptiste Daroussin 	    }
60798e903e7SBaptiste Daroussin 	    else
60898e903e7SBaptiste Daroussin 	    {
60998e903e7SBaptiste Daroussin 		break;
61098e903e7SBaptiste Daroussin 	    }
61198e903e7SBaptiste Daroussin 	    c = *++cptr;
61298e903e7SBaptiste Daroussin 	}
61398e903e7SBaptiste Daroussin 	cachec(NUL);
61498e903e7SBaptiste Daroussin 
6150c8de5b0SBaptiste Daroussin 	if ((key = bsearch(cache, keywords,
6160c8de5b0SBaptiste Daroussin 			   sizeof(keywords) / sizeof(*key),
6170c8de5b0SBaptiste Daroussin 			   sizeof(*key), compare_keys)))
6180c8de5b0SBaptiste Daroussin 	    return key->token;
61998e903e7SBaptiste Daroussin     }
62098e903e7SBaptiste Daroussin     else
62198e903e7SBaptiste Daroussin     {
62298e903e7SBaptiste Daroussin 	++cptr;
62398e903e7SBaptiste Daroussin 	if (c == L_CURL)
62498e903e7SBaptiste Daroussin 	    return (TEXT);
62598e903e7SBaptiste Daroussin 	if (c == '%' || c == '\\')
62698e903e7SBaptiste Daroussin 	    return (MARK);
62798e903e7SBaptiste Daroussin 	if (c == '<')
62898e903e7SBaptiste Daroussin 	    return (LEFT);
62998e903e7SBaptiste Daroussin 	if (c == '>')
63098e903e7SBaptiste Daroussin 	    return (RIGHT);
63198e903e7SBaptiste Daroussin 	if (c == '0')
63298e903e7SBaptiste Daroussin 	    return (TOKEN);
63398e903e7SBaptiste Daroussin 	if (c == '2')
63498e903e7SBaptiste Daroussin 	    return (NONASSOC);
63598e903e7SBaptiste Daroussin     }
63698e903e7SBaptiste Daroussin     syntax_error(lineno, line, t_cptr);
637c5b5d71aSJung-uk Kim     /*NOTREACHED */
63898e903e7SBaptiste Daroussin }
63998e903e7SBaptiste Daroussin 
64098e903e7SBaptiste Daroussin static void
copy_ident(void)64198e903e7SBaptiste Daroussin copy_ident(void)
64298e903e7SBaptiste Daroussin {
64398e903e7SBaptiste Daroussin     int c;
64498e903e7SBaptiste Daroussin     FILE *f = output_file;
64598e903e7SBaptiste Daroussin 
64698e903e7SBaptiste Daroussin     c = nextc();
64798e903e7SBaptiste Daroussin     if (c == EOF)
64898e903e7SBaptiste Daroussin 	unexpected_EOF();
64998e903e7SBaptiste Daroussin     if (c != '"')
65098e903e7SBaptiste Daroussin 	syntax_error(lineno, line, cptr);
65198e903e7SBaptiste Daroussin     ++outline;
65298e903e7SBaptiste Daroussin     fprintf(f, "#ident \"");
65398e903e7SBaptiste Daroussin     for (;;)
65498e903e7SBaptiste Daroussin     {
65598e903e7SBaptiste Daroussin 	c = *++cptr;
65698e903e7SBaptiste Daroussin 	if (c == '\n')
65798e903e7SBaptiste Daroussin 	{
65898e903e7SBaptiste Daroussin 	    fprintf(f, "\"\n");
65998e903e7SBaptiste Daroussin 	    return;
66098e903e7SBaptiste Daroussin 	}
66198e903e7SBaptiste Daroussin 	putc(c, f);
66298e903e7SBaptiste Daroussin 	if (c == '"')
66398e903e7SBaptiste Daroussin 	{
66498e903e7SBaptiste Daroussin 	    putc('\n', f);
66598e903e7SBaptiste Daroussin 	    ++cptr;
66698e903e7SBaptiste Daroussin 	    return;
66798e903e7SBaptiste Daroussin 	}
66898e903e7SBaptiste Daroussin     }
66998e903e7SBaptiste Daroussin }
67098e903e7SBaptiste Daroussin 
6710c8de5b0SBaptiste Daroussin static char *
copy_string(int quote)6720c8de5b0SBaptiste Daroussin copy_string(int quote)
6730c8de5b0SBaptiste Daroussin {
6740c8de5b0SBaptiste Daroussin     struct mstring *temp = msnew();
6752aca18c7SJung-uk Kim     struct ainfo a;
676*822ca327SBaptiste Daroussin 
677*822ca327SBaptiste Daroussin     begin_ainfo(a, 1);
6780c8de5b0SBaptiste Daroussin 
6790c8de5b0SBaptiste Daroussin     for (;;)
6800c8de5b0SBaptiste Daroussin     {
6818e022d3cSDag-Erling Smørgrav 	int c = *cptr++;
6828e022d3cSDag-Erling Smørgrav 
6830c8de5b0SBaptiste Daroussin 	mputc(temp, c);
6840c8de5b0SBaptiste Daroussin 	if (c == quote)
6850c8de5b0SBaptiste Daroussin 	{
686*822ca327SBaptiste Daroussin 	    end_ainfo(a);
6870c8de5b0SBaptiste Daroussin 	    return msdone(temp);
6880c8de5b0SBaptiste Daroussin 	}
6890c8de5b0SBaptiste Daroussin 	if (c == '\n')
6902aca18c7SJung-uk Kim 	    unterminated_string(&a);
6910c8de5b0SBaptiste Daroussin 	if (c == '\\')
6920c8de5b0SBaptiste Daroussin 	{
6930c8de5b0SBaptiste Daroussin 	    c = *cptr++;
6940c8de5b0SBaptiste Daroussin 	    mputc(temp, c);
6950c8de5b0SBaptiste Daroussin 	    if (c == '\n')
6960c8de5b0SBaptiste Daroussin 	    {
6970c8de5b0SBaptiste Daroussin 		get_line();
698c5b5d71aSJung-uk Kim 		if (line == NULL)
6992aca18c7SJung-uk Kim 		    unterminated_string(&a);
7000c8de5b0SBaptiste Daroussin 	    }
7010c8de5b0SBaptiste Daroussin 	}
7020c8de5b0SBaptiste Daroussin     }
7030c8de5b0SBaptiste Daroussin }
7040c8de5b0SBaptiste Daroussin 
7050c8de5b0SBaptiste Daroussin static char *
copy_comment(void)7060c8de5b0SBaptiste Daroussin copy_comment(void)
7070c8de5b0SBaptiste Daroussin {
7080c8de5b0SBaptiste Daroussin     struct mstring *temp = msnew();
7090c8de5b0SBaptiste Daroussin     int c;
7100c8de5b0SBaptiste Daroussin 
7110c8de5b0SBaptiste Daroussin     c = *cptr;
7120c8de5b0SBaptiste Daroussin     if (c == '/')
7130c8de5b0SBaptiste Daroussin     {
7140c8de5b0SBaptiste Daroussin 	mputc(temp, '*');
7150c8de5b0SBaptiste Daroussin 	while ((c = *++cptr) != '\n')
7160c8de5b0SBaptiste Daroussin 	{
7170c8de5b0SBaptiste Daroussin 	    mputc(temp, c);
7180c8de5b0SBaptiste Daroussin 	    if (c == '*' && cptr[1] == '/')
7190c8de5b0SBaptiste Daroussin 		mputc(temp, ' ');
7200c8de5b0SBaptiste Daroussin 	}
7210c8de5b0SBaptiste Daroussin 	mputc(temp, '*');
7220c8de5b0SBaptiste Daroussin 	mputc(temp, '/');
7230c8de5b0SBaptiste Daroussin     }
7240c8de5b0SBaptiste Daroussin     else if (c == '*')
7250c8de5b0SBaptiste Daroussin     {
7262aca18c7SJung-uk Kim 	struct ainfo a;
727*822ca327SBaptiste Daroussin 
728*822ca327SBaptiste Daroussin 	begin_ainfo(a, 1);
7290c8de5b0SBaptiste Daroussin 
7300c8de5b0SBaptiste Daroussin 	mputc(temp, c);
7310c8de5b0SBaptiste Daroussin 	++cptr;
7320c8de5b0SBaptiste Daroussin 	for (;;)
7330c8de5b0SBaptiste Daroussin 	{
7340c8de5b0SBaptiste Daroussin 	    c = *cptr++;
7350c8de5b0SBaptiste Daroussin 	    mputc(temp, c);
7360c8de5b0SBaptiste Daroussin 	    if (c == '*' && *cptr == '/')
7370c8de5b0SBaptiste Daroussin 	    {
7380c8de5b0SBaptiste Daroussin 		mputc(temp, '/');
7390c8de5b0SBaptiste Daroussin 		++cptr;
740*822ca327SBaptiste Daroussin 		end_ainfo(a);
7410c8de5b0SBaptiste Daroussin 		return msdone(temp);
7420c8de5b0SBaptiste Daroussin 	    }
7430c8de5b0SBaptiste Daroussin 	    if (c == '\n')
7440c8de5b0SBaptiste Daroussin 	    {
7450c8de5b0SBaptiste Daroussin 		get_line();
746c5b5d71aSJung-uk Kim 		if (line == NULL)
7472aca18c7SJung-uk Kim 		    unterminated_comment(&a);
7480c8de5b0SBaptiste Daroussin 	    }
7490c8de5b0SBaptiste Daroussin 	}
7500c8de5b0SBaptiste Daroussin     }
7510c8de5b0SBaptiste Daroussin     return msdone(temp);
7520c8de5b0SBaptiste Daroussin }
7530c8de5b0SBaptiste Daroussin 
754b53bb29fSJung-uk Kim static int
check_key(int pos)755b53bb29fSJung-uk Kim check_key(int pos)
756b53bb29fSJung-uk Kim {
757b53bb29fSJung-uk Kim     const char *key = code_keys[pos];
758b53bb29fSJung-uk Kim     while (*cptr && *key)
759b53bb29fSJung-uk Kim 	if (*key++ != *cptr++)
760b53bb29fSJung-uk Kim 	    return 0;
761b53bb29fSJung-uk Kim     if (*key || (!isspace(UCH(*cptr)) && *cptr != L_CURL))
762b53bb29fSJung-uk Kim 	return 0;
763b53bb29fSJung-uk Kim     cptr--;
764b53bb29fSJung-uk Kim     return 1;
765b53bb29fSJung-uk Kim }
766b53bb29fSJung-uk Kim 
767b53bb29fSJung-uk Kim static void
copy_code(void)768b53bb29fSJung-uk Kim copy_code(void)
769b53bb29fSJung-uk Kim {
770b53bb29fSJung-uk Kim     int c;
771b53bb29fSJung-uk Kim     int curl;
772b53bb29fSJung-uk Kim     int cline;
773b53bb29fSJung-uk Kim     int on_line = 0;
774b53bb29fSJung-uk Kim     int pos = CODE_HEADER;
775b53bb29fSJung-uk Kim     struct mstring *code_mstr;
776b53bb29fSJung-uk Kim 
777b53bb29fSJung-uk Kim     /* read %code <keyword> { */
778b53bb29fSJung-uk Kim     for (;;)
779b53bb29fSJung-uk Kim     {
780b53bb29fSJung-uk Kim 	c = *++cptr;
781b53bb29fSJung-uk Kim 	if (c == EOF)
782b53bb29fSJung-uk Kim 	    unexpected_EOF();
783*822ca327SBaptiste Daroussin 	if (c == '\0')
784*822ca327SBaptiste Daroussin 	{
785*822ca327SBaptiste Daroussin 	    get_line();
786*822ca327SBaptiste Daroussin 	    if (line == NULL)
787*822ca327SBaptiste Daroussin 	    {
788*822ca327SBaptiste Daroussin 		unexpected_EOF();
789*822ca327SBaptiste Daroussin 		/*NOTREACHED */
790*822ca327SBaptiste Daroussin 	    }
791*822ca327SBaptiste Daroussin 	    c = *cptr;
792*822ca327SBaptiste Daroussin 	}
793b53bb29fSJung-uk Kim 	if (isspace(UCH(c)))
794b53bb29fSJung-uk Kim 	    continue;
795b53bb29fSJung-uk Kim 
796b53bb29fSJung-uk Kim 	if (c == L_CURL)
797b53bb29fSJung-uk Kim 	    break;
798b53bb29fSJung-uk Kim 
799b53bb29fSJung-uk Kim 	if (pos == CODE_HEADER)
800b53bb29fSJung-uk Kim 	{
801b53bb29fSJung-uk Kim 	    switch (UCH(c))
802b53bb29fSJung-uk Kim 	    {
803b53bb29fSJung-uk Kim 	    case 'r':
804b53bb29fSJung-uk Kim 		pos = CODE_REQUIRES;
805b53bb29fSJung-uk Kim 		break;
806b53bb29fSJung-uk Kim 	    case 'p':
807b53bb29fSJung-uk Kim 		pos = CODE_PROVIDES;
808b53bb29fSJung-uk Kim 		break;
809b53bb29fSJung-uk Kim 	    case 't':
810b53bb29fSJung-uk Kim 		pos = CODE_TOP;
811b53bb29fSJung-uk Kim 		break;
812b53bb29fSJung-uk Kim 	    case 'i':
813b53bb29fSJung-uk Kim 		pos = CODE_IMPORTS;
814b53bb29fSJung-uk Kim 		break;
815b53bb29fSJung-uk Kim 	    default:
816b53bb29fSJung-uk Kim 		break;
817b53bb29fSJung-uk Kim 	    }
818b53bb29fSJung-uk Kim 
819b53bb29fSJung-uk Kim 	    if (pos == -1 || !check_key(pos))
820b53bb29fSJung-uk Kim 	    {
821b53bb29fSJung-uk Kim 		syntax_error(lineno, line, cptr);
8228e022d3cSDag-Erling Smørgrav 		/*NOTREACHED */
823b53bb29fSJung-uk Kim 	    }
824b53bb29fSJung-uk Kim 	}
825b53bb29fSJung-uk Kim     }
826b53bb29fSJung-uk Kim 
827b53bb29fSJung-uk Kim     cptr++;			/* skip initial curl */
828b53bb29fSJung-uk Kim     while (*cptr && isspace(UCH(*cptr)))	/* skip space */
829b53bb29fSJung-uk Kim 	cptr++;
830b53bb29fSJung-uk Kim     curl = 1;			/* nesting count */
831b53bb29fSJung-uk Kim 
832b53bb29fSJung-uk Kim     /* gather text */
833b53bb29fSJung-uk Kim     code_lines[pos].name = code_keys[pos];
834b53bb29fSJung-uk Kim     if ((cline = (int)code_lines[pos].num) != 0)
835b53bb29fSJung-uk Kim     {
836b53bb29fSJung-uk Kim 	code_mstr = msrenew(code_lines[pos].lines);
837b53bb29fSJung-uk Kim     }
838b53bb29fSJung-uk Kim     else
839b53bb29fSJung-uk Kim     {
840b53bb29fSJung-uk Kim 	code_mstr = msnew();
841b53bb29fSJung-uk Kim     }
842b53bb29fSJung-uk Kim     cline++;
8438e022d3cSDag-Erling Smørgrav     if (!lflag)
844b53bb29fSJung-uk Kim 	msprintf(code_mstr, line_format, lineno, input_file_name);
845b53bb29fSJung-uk Kim     for (;;)
846b53bb29fSJung-uk Kim     {
847b53bb29fSJung-uk Kim 	c = *cptr++;
848b53bb29fSJung-uk Kim 	switch (c)
849b53bb29fSJung-uk Kim 	{
850b53bb29fSJung-uk Kim 	case '\0':
851b53bb29fSJung-uk Kim 	    get_line();
852b53bb29fSJung-uk Kim 	    if (line == NULL)
853b53bb29fSJung-uk Kim 	    {
854b53bb29fSJung-uk Kim 		unexpected_EOF();
8558e022d3cSDag-Erling Smørgrav 		/*NOTREACHED */
856b53bb29fSJung-uk Kim 	    }
857b53bb29fSJung-uk Kim 	    continue;
858b53bb29fSJung-uk Kim 	case '\n':
859b53bb29fSJung-uk Kim 	    cline++;
860b53bb29fSJung-uk Kim 	    on_line = 0;
861b53bb29fSJung-uk Kim 	    break;
862b53bb29fSJung-uk Kim 	case L_CURL:
863b53bb29fSJung-uk Kim 	    curl++;
864b53bb29fSJung-uk Kim 	    break;
865b53bb29fSJung-uk Kim 	case R_CURL:
866b53bb29fSJung-uk Kim 	    if (--curl == 0)
867b53bb29fSJung-uk Kim 	    {
868b53bb29fSJung-uk Kim 		if (on_line > 1)
869b53bb29fSJung-uk Kim 		{
870b53bb29fSJung-uk Kim 		    mputc(code_mstr, '\n');
871b53bb29fSJung-uk Kim 		    cline++;
872b53bb29fSJung-uk Kim 		}
873b53bb29fSJung-uk Kim 		code_lines[pos].lines = msdone(code_mstr);
874b53bb29fSJung-uk Kim 		code_lines[pos].num = (size_t)cline;
875b53bb29fSJung-uk Kim 		return;
876b53bb29fSJung-uk Kim 	    }
877b53bb29fSJung-uk Kim 	    break;
878b53bb29fSJung-uk Kim 	default:
879b53bb29fSJung-uk Kim 	    break;
880b53bb29fSJung-uk Kim 	}
881b53bb29fSJung-uk Kim 	mputc(code_mstr, c);
882b53bb29fSJung-uk Kim 	on_line++;
883b53bb29fSJung-uk Kim     }
884b53bb29fSJung-uk Kim }
885b53bb29fSJung-uk Kim 
88698e903e7SBaptiste Daroussin static void
copy_text(void)88798e903e7SBaptiste Daroussin copy_text(void)
88898e903e7SBaptiste Daroussin {
88998e903e7SBaptiste Daroussin     int c;
89098e903e7SBaptiste Daroussin     FILE *f = text_file;
89198e903e7SBaptiste Daroussin     int need_newline = 0;
8922aca18c7SJung-uk Kim     struct ainfo a;
893*822ca327SBaptiste Daroussin 
894*822ca327SBaptiste Daroussin     begin_ainfo(a, 2);
89598e903e7SBaptiste Daroussin 
89698e903e7SBaptiste Daroussin     if (*cptr == '\n')
89798e903e7SBaptiste Daroussin     {
89898e903e7SBaptiste Daroussin 	get_line();
899c5b5d71aSJung-uk Kim 	if (line == NULL)
9002aca18c7SJung-uk Kim 	    unterminated_text(&a);
90198e903e7SBaptiste Daroussin     }
9028e022d3cSDag-Erling Smørgrav     fprintf_lineno(f, lineno, input_file_name);
90398e903e7SBaptiste Daroussin 
90498e903e7SBaptiste Daroussin   loop:
90598e903e7SBaptiste Daroussin     c = *cptr++;
90698e903e7SBaptiste Daroussin     switch (c)
90798e903e7SBaptiste Daroussin     {
90898e903e7SBaptiste Daroussin     case '\n':
90998e903e7SBaptiste Daroussin 	putc('\n', f);
91098e903e7SBaptiste Daroussin 	need_newline = 0;
91198e903e7SBaptiste Daroussin 	get_line();
91298e903e7SBaptiste Daroussin 	if (line)
91398e903e7SBaptiste Daroussin 	    goto loop;
9142aca18c7SJung-uk Kim 	unterminated_text(&a);
91598e903e7SBaptiste Daroussin 
91698e903e7SBaptiste Daroussin     case '\'':
91798e903e7SBaptiste Daroussin     case '"':
91898e903e7SBaptiste Daroussin 	putc(c, f);
91998e903e7SBaptiste Daroussin 	{
9200c8de5b0SBaptiste Daroussin 	    char *s = copy_string(c);
9210c8de5b0SBaptiste Daroussin 	    fputs(s, f);
9220c8de5b0SBaptiste Daroussin 	    free(s);
9230c8de5b0SBaptiste Daroussin 	}
92498e903e7SBaptiste Daroussin 	need_newline = 1;
92598e903e7SBaptiste Daroussin 	goto loop;
92698e903e7SBaptiste Daroussin 
92798e903e7SBaptiste Daroussin     case '/':
92898e903e7SBaptiste Daroussin 	putc(c, f);
92998e903e7SBaptiste Daroussin 	{
9300c8de5b0SBaptiste Daroussin 	    char *s = copy_comment();
9310c8de5b0SBaptiste Daroussin 	    fputs(s, f);
9320c8de5b0SBaptiste Daroussin 	    free(s);
93398e903e7SBaptiste Daroussin 	}
93498e903e7SBaptiste Daroussin 	need_newline = 1;
93598e903e7SBaptiste Daroussin 	goto loop;
93698e903e7SBaptiste Daroussin 
93798e903e7SBaptiste Daroussin     case '%':
93898e903e7SBaptiste Daroussin     case '\\':
93998e903e7SBaptiste Daroussin 	if (*cptr == R_CURL)
94098e903e7SBaptiste Daroussin 	{
94198e903e7SBaptiste Daroussin 	    if (need_newline)
94298e903e7SBaptiste Daroussin 		putc('\n', f);
94398e903e7SBaptiste Daroussin 	    ++cptr;
944*822ca327SBaptiste Daroussin 	    end_ainfo(a);
94598e903e7SBaptiste Daroussin 	    return;
94698e903e7SBaptiste Daroussin 	}
94798e903e7SBaptiste Daroussin 	/* FALLTHRU */
94898e903e7SBaptiste Daroussin 
94998e903e7SBaptiste Daroussin     default:
95098e903e7SBaptiste Daroussin 	putc(c, f);
95198e903e7SBaptiste Daroussin 	need_newline = 1;
95298e903e7SBaptiste Daroussin 	goto loop;
95398e903e7SBaptiste Daroussin     }
95498e903e7SBaptiste Daroussin }
95598e903e7SBaptiste Daroussin 
95698e903e7SBaptiste Daroussin static void
puts_both(const char * s)95798e903e7SBaptiste Daroussin puts_both(const char *s)
95898e903e7SBaptiste Daroussin {
959*822ca327SBaptiste Daroussin     if (s && *s)
960*822ca327SBaptiste Daroussin     {
96198e903e7SBaptiste Daroussin 	fputs(s, text_file);
96298e903e7SBaptiste Daroussin 	if (dflag)
96398e903e7SBaptiste Daroussin 	    fputs(s, union_file);
96498e903e7SBaptiste Daroussin     }
965*822ca327SBaptiste Daroussin }
96698e903e7SBaptiste Daroussin 
96798e903e7SBaptiste Daroussin static void
putc_both(int c)96898e903e7SBaptiste Daroussin putc_both(int c)
96998e903e7SBaptiste Daroussin {
97098e903e7SBaptiste Daroussin     putc(c, text_file);
97198e903e7SBaptiste Daroussin     if (dflag)
97298e903e7SBaptiste Daroussin 	putc(c, union_file);
97398e903e7SBaptiste Daroussin }
97498e903e7SBaptiste Daroussin 
97598e903e7SBaptiste Daroussin static void
copy_union(void)97698e903e7SBaptiste Daroussin copy_union(void)
97798e903e7SBaptiste Daroussin {
97898e903e7SBaptiste Daroussin     int c;
97998e903e7SBaptiste Daroussin     int depth;
9802aca18c7SJung-uk Kim     struct ainfo a;
981*822ca327SBaptiste Daroussin     char prefix_buf[NAME_LEN + 1];
982*822ca327SBaptiste Daroussin     size_t prefix_len = 0;
983*822ca327SBaptiste Daroussin     char filler_buf[NAME_LEN + 1];
984*822ca327SBaptiste Daroussin     size_t filler_len = 0;
985*822ca327SBaptiste Daroussin     int in_prefix = 1;
986*822ca327SBaptiste Daroussin 
987*822ca327SBaptiste Daroussin     prefix_buf[0] = '\0';
988*822ca327SBaptiste Daroussin     filler_buf[0] = '\0';
989*822ca327SBaptiste Daroussin 
990*822ca327SBaptiste Daroussin     begin_ainfo(a, 6);
99198e903e7SBaptiste Daroussin 
99298e903e7SBaptiste Daroussin     if (unionized)
99398e903e7SBaptiste Daroussin 	over_unionized(cptr - 6);
99498e903e7SBaptiste Daroussin     unionized = 1;
99598e903e7SBaptiste Daroussin 
99698e903e7SBaptiste Daroussin     puts_both("#ifdef YYSTYPE\n");
99798e903e7SBaptiste Daroussin     puts_both("#undef  YYSTYPE_IS_DECLARED\n");
99898e903e7SBaptiste Daroussin     puts_both("#define YYSTYPE_IS_DECLARED 1\n");
99998e903e7SBaptiste Daroussin     puts_both("#endif\n");
100098e903e7SBaptiste Daroussin     puts_both("#ifndef YYSTYPE_IS_DECLARED\n");
100198e903e7SBaptiste Daroussin     puts_both("#define YYSTYPE_IS_DECLARED 1\n");
1002c5b5d71aSJung-uk Kim 
10038e022d3cSDag-Erling Smørgrav     fprintf_lineno(text_file, lineno, input_file_name);
100498e903e7SBaptiste Daroussin 
100598e903e7SBaptiste Daroussin     depth = 0;
100698e903e7SBaptiste Daroussin   loop:
100798e903e7SBaptiste Daroussin     c = *cptr++;
1008*822ca327SBaptiste Daroussin     if (in_prefix)
1009*822ca327SBaptiste Daroussin     {
1010*822ca327SBaptiste Daroussin 	if (c == L_CURL)
1011*822ca327SBaptiste Daroussin 	{
1012*822ca327SBaptiste Daroussin 	    in_prefix = 0;
1013*822ca327SBaptiste Daroussin 	    if (prefix_len)
1014*822ca327SBaptiste Daroussin 	    {
1015*822ca327SBaptiste Daroussin 		puts_both("union ");
1016*822ca327SBaptiste Daroussin 		puts_both(prefix_buf);
1017*822ca327SBaptiste Daroussin 		puts_both(filler_buf);
1018*822ca327SBaptiste Daroussin 	    }
1019*822ca327SBaptiste Daroussin 	    else
1020*822ca327SBaptiste Daroussin 	    {
1021*822ca327SBaptiste Daroussin 		puts_both("typedef union YYSTYPE");
1022*822ca327SBaptiste Daroussin 		puts_both(filler_buf);
1023*822ca327SBaptiste Daroussin 	    }
1024*822ca327SBaptiste Daroussin 	}
1025*822ca327SBaptiste Daroussin 	else if (isspace(c))
1026*822ca327SBaptiste Daroussin 	{
1027*822ca327SBaptiste Daroussin 	    if (filler_len >= sizeof(filler_buf) - 1)
1028*822ca327SBaptiste Daroussin 	    {
1029*822ca327SBaptiste Daroussin 		puts_both(filler_buf);
1030*822ca327SBaptiste Daroussin 		filler_len = 0;
1031*822ca327SBaptiste Daroussin 	    }
1032*822ca327SBaptiste Daroussin 	    filler_buf[filler_len++] = (char)c;
1033*822ca327SBaptiste Daroussin 	    filler_buf[filler_len] = 0;
1034*822ca327SBaptiste Daroussin 	    if (c != '\n')
1035*822ca327SBaptiste Daroussin 		goto loop;
1036*822ca327SBaptiste Daroussin 	}
1037*822ca327SBaptiste Daroussin 	else if (IS_IDENT(c))
1038*822ca327SBaptiste Daroussin 	{
1039*822ca327SBaptiste Daroussin 	    if (prefix_len < NAME_LEN)
1040*822ca327SBaptiste Daroussin 	    {
1041*822ca327SBaptiste Daroussin 		prefix_buf[prefix_len++] = (char)c;
1042*822ca327SBaptiste Daroussin 		prefix_buf[prefix_len] = 0;
1043*822ca327SBaptiste Daroussin 	    }
1044*822ca327SBaptiste Daroussin 	    goto loop;
1045*822ca327SBaptiste Daroussin 	}
1046*822ca327SBaptiste Daroussin     }
1047*822ca327SBaptiste Daroussin     if (c != '\n' || !in_prefix)
104898e903e7SBaptiste Daroussin 	putc_both(c);
104998e903e7SBaptiste Daroussin     switch (c)
105098e903e7SBaptiste Daroussin     {
105198e903e7SBaptiste Daroussin     case '\n':
105298e903e7SBaptiste Daroussin 	get_line();
1053c5b5d71aSJung-uk Kim 	if (line == NULL)
10542aca18c7SJung-uk Kim 	    unterminated_union(&a);
105598e903e7SBaptiste Daroussin 	goto loop;
105698e903e7SBaptiste Daroussin 
105798e903e7SBaptiste Daroussin     case L_CURL:
105898e903e7SBaptiste Daroussin 	++depth;
105998e903e7SBaptiste Daroussin 	goto loop;
106098e903e7SBaptiste Daroussin 
106198e903e7SBaptiste Daroussin     case R_CURL:
106298e903e7SBaptiste Daroussin 	if (--depth == 0)
106398e903e7SBaptiste Daroussin 	{
1064*822ca327SBaptiste Daroussin 	    puts_both(prefix_len ? "; " : " YYSTYPE;\n");
1065*822ca327SBaptiste Daroussin 	    if (prefix_len)
1066*822ca327SBaptiste Daroussin 	    {
1067*822ca327SBaptiste Daroussin 		puts_both("typedef union ");
1068*822ca327SBaptiste Daroussin 		puts_both(prefix_buf);
106998e903e7SBaptiste Daroussin 		puts_both(" YYSTYPE;\n");
1070*822ca327SBaptiste Daroussin 	    }
107198e903e7SBaptiste Daroussin 	    puts_both("#endif /* !YYSTYPE_IS_DECLARED */\n");
1072*822ca327SBaptiste Daroussin 	    end_ainfo(a);
107398e903e7SBaptiste Daroussin 	    return;
107498e903e7SBaptiste Daroussin 	}
107598e903e7SBaptiste Daroussin 	goto loop;
107698e903e7SBaptiste Daroussin 
107798e903e7SBaptiste Daroussin     case '\'':
107898e903e7SBaptiste Daroussin     case '"':
107998e903e7SBaptiste Daroussin 	{
10800c8de5b0SBaptiste Daroussin 	    char *s = copy_string(c);
10810c8de5b0SBaptiste Daroussin 	    puts_both(s);
10820c8de5b0SBaptiste Daroussin 	    free(s);
10830c8de5b0SBaptiste Daroussin 	}
108498e903e7SBaptiste Daroussin 	goto loop;
108598e903e7SBaptiste Daroussin 
108698e903e7SBaptiste Daroussin     case '/':
108798e903e7SBaptiste Daroussin 	{
10880c8de5b0SBaptiste Daroussin 	    char *s = copy_comment();
10890c8de5b0SBaptiste Daroussin 	    puts_both(s);
10900c8de5b0SBaptiste Daroussin 	    free(s);
109198e903e7SBaptiste Daroussin 	}
109298e903e7SBaptiste Daroussin 	goto loop;
109398e903e7SBaptiste Daroussin 
109498e903e7SBaptiste Daroussin     default:
109598e903e7SBaptiste Daroussin 	goto loop;
109698e903e7SBaptiste Daroussin     }
109798e903e7SBaptiste Daroussin }
109898e903e7SBaptiste Daroussin 
109911fce282SBaptiste Daroussin static char *
after_blanks(char * s)110011fce282SBaptiste Daroussin after_blanks(char *s)
110111fce282SBaptiste Daroussin {
110211fce282SBaptiste Daroussin     while (*s != '\0' && isspace(UCH(*s)))
110311fce282SBaptiste Daroussin 	++s;
110411fce282SBaptiste Daroussin     return s;
110511fce282SBaptiste Daroussin }
110611fce282SBaptiste Daroussin 
110798e903e7SBaptiste Daroussin /*
110811fce282SBaptiste Daroussin  * Trim leading/trailing blanks, and collapse multiple embedded blanks to a
110911fce282SBaptiste Daroussin  * single space.  Return index to last character in the buffer.
111098e903e7SBaptiste Daroussin  */
111111fce282SBaptiste Daroussin static int
trim_blanks(char * buffer)111211fce282SBaptiste Daroussin trim_blanks(char *buffer)
111311fce282SBaptiste Daroussin {
111411fce282SBaptiste Daroussin     if (*buffer != '\0')
111511fce282SBaptiste Daroussin     {
111611fce282SBaptiste Daroussin 	char *d = buffer;
111711fce282SBaptiste Daroussin 	char *s = after_blanks(d);
111811fce282SBaptiste Daroussin 
111911fce282SBaptiste Daroussin 	while ((*d++ = *s++) != '\0')
112011fce282SBaptiste Daroussin 	{
112111fce282SBaptiste Daroussin 	    ;
112211fce282SBaptiste Daroussin 	}
112311fce282SBaptiste Daroussin 
112411fce282SBaptiste Daroussin 	--d;
112511fce282SBaptiste Daroussin 	while ((--d != buffer) && isspace(UCH(*d)))
112611fce282SBaptiste Daroussin 	    *d = '\0';
112711fce282SBaptiste Daroussin 
112811fce282SBaptiste Daroussin 	for (s = d = buffer; (*d++ = *s++) != '\0';)
112911fce282SBaptiste Daroussin 	{
113011fce282SBaptiste Daroussin 	    if (isspace(UCH(*s)))
113111fce282SBaptiste Daroussin 	    {
113211fce282SBaptiste Daroussin 		*s = ' ';
113311fce282SBaptiste Daroussin 		while (isspace(UCH(*s)))
113411fce282SBaptiste Daroussin 		{
113511fce282SBaptiste Daroussin 		    *s++ = ' ';
113611fce282SBaptiste Daroussin 		}
113711fce282SBaptiste Daroussin 		--s;
113811fce282SBaptiste Daroussin 	    }
113911fce282SBaptiste Daroussin 	}
114011fce282SBaptiste Daroussin     }
114111fce282SBaptiste Daroussin 
114211fce282SBaptiste Daroussin     return (int)strlen(buffer) - 1;
114311fce282SBaptiste Daroussin }
114411fce282SBaptiste Daroussin 
114511fce282SBaptiste Daroussin /*
114611fce282SBaptiste Daroussin  * Scan forward in the current line-buffer looking for a right-curly bracket.
114711fce282SBaptiste Daroussin  *
114811fce282SBaptiste Daroussin  * Parameters begin with a left-curly bracket, and continue until there are no
114911fce282SBaptiste Daroussin  * more interesting characters after the last right-curly bracket on the
115011fce282SBaptiste Daroussin  * current line.  Bison documents parameters as separated like this:
115111fce282SBaptiste Daroussin  *	{type param1} {type2 param2}
115211fce282SBaptiste Daroussin  * but also accepts commas (although some versions of bison mishandle this)
115311fce282SBaptiste Daroussin  *	{type param1,  type2 param2}
115411fce282SBaptiste Daroussin  */
115511fce282SBaptiste Daroussin static int
more_curly(void)115611fce282SBaptiste Daroussin more_curly(void)
115711fce282SBaptiste Daroussin {
115811fce282SBaptiste Daroussin     int result = 0;
115911fce282SBaptiste Daroussin     int finish = 0;
1160*822ca327SBaptiste Daroussin     save_line();
116111fce282SBaptiste Daroussin     do
116211fce282SBaptiste Daroussin     {
116311fce282SBaptiste Daroussin 	switch (next_inline())
116411fce282SBaptiste Daroussin 	{
116511fce282SBaptiste Daroussin 	case 0:
116611fce282SBaptiste Daroussin 	case '\n':
116711fce282SBaptiste Daroussin 	    finish = 1;
116811fce282SBaptiste Daroussin 	    break;
116911fce282SBaptiste Daroussin 	case R_CURL:
117011fce282SBaptiste Daroussin 	    finish = 1;
117111fce282SBaptiste Daroussin 	    result = 1;
117211fce282SBaptiste Daroussin 	    break;
117311fce282SBaptiste Daroussin 	}
117411fce282SBaptiste Daroussin 	++cptr;
117511fce282SBaptiste Daroussin     }
117611fce282SBaptiste Daroussin     while (!finish);
1177*822ca327SBaptiste Daroussin     restore_line();
117811fce282SBaptiste Daroussin     return result;
117911fce282SBaptiste Daroussin }
118011fce282SBaptiste Daroussin 
118198e903e7SBaptiste Daroussin static void
save_param(int k,char * buffer,int name,int type2)118211fce282SBaptiste Daroussin save_param(int k, char *buffer, int name, int type2)
118398e903e7SBaptiste Daroussin {
118498e903e7SBaptiste Daroussin     param *head, *p;
118598e903e7SBaptiste Daroussin 
11863e066022SBaptiste Daroussin     p = TMALLOC(param, 1);
118798e903e7SBaptiste Daroussin     NO_SPACE(p);
118898e903e7SBaptiste Daroussin 
118911fce282SBaptiste Daroussin     p->type2 = strdup(buffer + type2);
119098e903e7SBaptiste Daroussin     NO_SPACE(p->type2);
119111fce282SBaptiste Daroussin     buffer[type2] = '\0';
119211fce282SBaptiste Daroussin     (void)trim_blanks(p->type2);
119398e903e7SBaptiste Daroussin 
1194*822ca327SBaptiste Daroussin     if (!IS_ALNUM(buffer[name]))
1195*822ca327SBaptiste Daroussin     {
1196*822ca327SBaptiste Daroussin 	int n;
1197*822ca327SBaptiste Daroussin 	for (n = name - 1; n >= 0; --n)
1198*822ca327SBaptiste Daroussin 	{
1199*822ca327SBaptiste Daroussin 	    if (!isspace(UCH(buffer[n])))
1200*822ca327SBaptiste Daroussin 	    {
1201*822ca327SBaptiste Daroussin 		break;
1202*822ca327SBaptiste Daroussin 	    }
1203*822ca327SBaptiste Daroussin 	}
1204*822ca327SBaptiste Daroussin 	while (n > 0)
1205*822ca327SBaptiste Daroussin 	{
1206*822ca327SBaptiste Daroussin 	    if (!IS_ALNUM(UCH(buffer[n - 1])))
1207*822ca327SBaptiste Daroussin 		break;
1208*822ca327SBaptiste Daroussin 	    --n;
1209*822ca327SBaptiste Daroussin 	}
1210*822ca327SBaptiste Daroussin 	name = n;
1211*822ca327SBaptiste Daroussin     }
121211fce282SBaptiste Daroussin     p->name = strdup(buffer + name);
121398e903e7SBaptiste Daroussin     NO_SPACE(p->name);
121411fce282SBaptiste Daroussin     buffer[name] = '\0';
121511fce282SBaptiste Daroussin     (void)trim_blanks(p->name);
121698e903e7SBaptiste Daroussin 
121711fce282SBaptiste Daroussin     p->type = strdup(buffer);
121811fce282SBaptiste Daroussin     NO_SPACE(p->type);
121911fce282SBaptiste Daroussin     (void)trim_blanks(p->type);
122098e903e7SBaptiste Daroussin 
122198e903e7SBaptiste Daroussin     if (k == LEX_PARAM)
122298e903e7SBaptiste Daroussin 	head = lex_param;
122398e903e7SBaptiste Daroussin     else
122498e903e7SBaptiste Daroussin 	head = parse_param;
122598e903e7SBaptiste Daroussin 
122698e903e7SBaptiste Daroussin     if (head != NULL)
122798e903e7SBaptiste Daroussin     {
122898e903e7SBaptiste Daroussin 	while (head->next)
122998e903e7SBaptiste Daroussin 	    head = head->next;
123098e903e7SBaptiste Daroussin 	head->next = p;
123198e903e7SBaptiste Daroussin     }
123298e903e7SBaptiste Daroussin     else
123398e903e7SBaptiste Daroussin     {
123498e903e7SBaptiste Daroussin 	if (k == LEX_PARAM)
123598e903e7SBaptiste Daroussin 	    lex_param = p;
123698e903e7SBaptiste Daroussin 	else
123798e903e7SBaptiste Daroussin 	    parse_param = p;
123898e903e7SBaptiste Daroussin     }
123998e903e7SBaptiste Daroussin     p->next = NULL;
124011fce282SBaptiste Daroussin }
124111fce282SBaptiste Daroussin 
124211fce282SBaptiste Daroussin /*
124311fce282SBaptiste Daroussin  * Keep a linked list of parameters.  This may be multi-line, if the trailing
124411fce282SBaptiste Daroussin  * right-curly bracket is absent.
124511fce282SBaptiste Daroussin  */
124611fce282SBaptiste Daroussin static void
copy_param(int k)124711fce282SBaptiste Daroussin copy_param(int k)
124811fce282SBaptiste Daroussin {
124911fce282SBaptiste Daroussin     int c;
125011fce282SBaptiste Daroussin     int name, type2;
125111fce282SBaptiste Daroussin     int curly = 0;
125211fce282SBaptiste Daroussin     char *buf = 0;
125311fce282SBaptiste Daroussin     int i = -1;
125411fce282SBaptiste Daroussin     size_t buf_size = 0;
125511fce282SBaptiste Daroussin     int st_lineno = lineno;
125611fce282SBaptiste Daroussin     char *comma;
125711fce282SBaptiste Daroussin 
125811fce282SBaptiste Daroussin     do
125911fce282SBaptiste Daroussin     {
126011fce282SBaptiste Daroussin 	int state = curly;
126111fce282SBaptiste Daroussin 	c = next_inline();
126211fce282SBaptiste Daroussin 	switch (c)
126311fce282SBaptiste Daroussin 	{
126411fce282SBaptiste Daroussin 	case EOF:
126511fce282SBaptiste Daroussin 	    unexpected_EOF();
126611fce282SBaptiste Daroussin 	    break;
126711fce282SBaptiste Daroussin 	case L_CURL:
126811fce282SBaptiste Daroussin 	    if (curly == 1)
126911fce282SBaptiste Daroussin 	    {
127011fce282SBaptiste Daroussin 		goto oops;
127111fce282SBaptiste Daroussin 	    }
127211fce282SBaptiste Daroussin 	    curly = 1;
127311fce282SBaptiste Daroussin 	    st_lineno = lineno;
127411fce282SBaptiste Daroussin 	    break;
127511fce282SBaptiste Daroussin 	case R_CURL:
127611fce282SBaptiste Daroussin 	    if (curly != 1)
127711fce282SBaptiste Daroussin 	    {
127811fce282SBaptiste Daroussin 		goto oops;
127911fce282SBaptiste Daroussin 	    }
128011fce282SBaptiste Daroussin 	    curly = 2;
128111fce282SBaptiste Daroussin 	    break;
128211fce282SBaptiste Daroussin 	case '\n':
128311fce282SBaptiste Daroussin 	    if (curly == 0)
128411fce282SBaptiste Daroussin 	    {
128511fce282SBaptiste Daroussin 		goto oops;
128611fce282SBaptiste Daroussin 	    }
128711fce282SBaptiste Daroussin 	    break;
128811fce282SBaptiste Daroussin 	case '%':
128911fce282SBaptiste Daroussin 	    if ((curly == 1) && (cptr == line))
129011fce282SBaptiste Daroussin 	    {
129111fce282SBaptiste Daroussin 		lineno = st_lineno;
129211fce282SBaptiste Daroussin 		missing_brace();
129311fce282SBaptiste Daroussin 	    }
129411fce282SBaptiste Daroussin 	    /* FALLTHRU */
129511fce282SBaptiste Daroussin 	case '"':
129611fce282SBaptiste Daroussin 	case '\'':
129711fce282SBaptiste Daroussin 	    goto oops;
129811fce282SBaptiste Daroussin 	default:
129911fce282SBaptiste Daroussin 	    if (curly == 0 && !isspace(UCH(c)))
130011fce282SBaptiste Daroussin 	    {
130111fce282SBaptiste Daroussin 		goto oops;
130211fce282SBaptiste Daroussin 	    }
130311fce282SBaptiste Daroussin 	    break;
130411fce282SBaptiste Daroussin 	}
130511fce282SBaptiste Daroussin 	if (buf == 0)
130611fce282SBaptiste Daroussin 	{
130711fce282SBaptiste Daroussin 	    buf_size = (size_t)linesize;
130811fce282SBaptiste Daroussin 	    buf = TMALLOC(char, buf_size);
13098e022d3cSDag-Erling Smørgrav 	    NO_SPACE(buf);
131011fce282SBaptiste Daroussin 	}
131111fce282SBaptiste Daroussin 	else if (c == '\n')
131211fce282SBaptiste Daroussin 	{
13138e022d3cSDag-Erling Smørgrav 	    char *tmp;
13148e022d3cSDag-Erling Smørgrav 
131511fce282SBaptiste Daroussin 	    get_line();
1316c5b5d71aSJung-uk Kim 	    if (line == NULL)
131711fce282SBaptiste Daroussin 		unexpected_EOF();
131811fce282SBaptiste Daroussin 	    --cptr;
131911fce282SBaptiste Daroussin 	    buf_size += (size_t)linesize;
13208e022d3cSDag-Erling Smørgrav 	    tmp = TREALLOC(char, buf, buf_size);
13218e022d3cSDag-Erling Smørgrav 	    NO_SPACE(tmp);
13228e022d3cSDag-Erling Smørgrav 	    buf = tmp;
132311fce282SBaptiste Daroussin 	}
132411fce282SBaptiste Daroussin 	if (curly)
132511fce282SBaptiste Daroussin 	{
132611fce282SBaptiste Daroussin 	    if ((state == 2) && (c == L_CURL))
132711fce282SBaptiste Daroussin 	    {
132811fce282SBaptiste Daroussin 		buf[++i] = ',';
132911fce282SBaptiste Daroussin 	    }
133011fce282SBaptiste Daroussin 	    else if ((state == 2) && isspace(UCH(c)))
133111fce282SBaptiste Daroussin 	    {
133211fce282SBaptiste Daroussin 		;
133311fce282SBaptiste Daroussin 	    }
133411fce282SBaptiste Daroussin 	    else if ((c != L_CURL) && (c != R_CURL))
133511fce282SBaptiste Daroussin 	    {
133611fce282SBaptiste Daroussin 		buf[++i] = (char)c;
133711fce282SBaptiste Daroussin 	    }
133811fce282SBaptiste Daroussin 	}
133911fce282SBaptiste Daroussin 	cptr++;
134011fce282SBaptiste Daroussin     }
134111fce282SBaptiste Daroussin     while (curly < 2 || more_curly());
134211fce282SBaptiste Daroussin 
134311fce282SBaptiste Daroussin     if (i == 0)
134411fce282SBaptiste Daroussin     {
134511fce282SBaptiste Daroussin 	if (curly == 1)
134611fce282SBaptiste Daroussin 	{
134711fce282SBaptiste Daroussin 	    lineno = st_lineno;
134811fce282SBaptiste Daroussin 	    missing_brace();
134911fce282SBaptiste Daroussin 	}
135011fce282SBaptiste Daroussin 	goto oops;
135111fce282SBaptiste Daroussin     }
135211fce282SBaptiste Daroussin 
13532aca18c7SJung-uk Kim     buf[++i] = '\0';
135420afc491SJung-uk Kim     (void)trim_blanks(buf);
135511fce282SBaptiste Daroussin 
135611fce282SBaptiste Daroussin     comma = buf - 1;
135711fce282SBaptiste Daroussin     do
135811fce282SBaptiste Daroussin     {
135911fce282SBaptiste Daroussin 	char *parms = (comma + 1);
136011fce282SBaptiste Daroussin 	comma = strchr(parms, ',');
136111fce282SBaptiste Daroussin 	if (comma != 0)
136211fce282SBaptiste Daroussin 	    *comma = '\0';
136311fce282SBaptiste Daroussin 
136411fce282SBaptiste Daroussin 	(void)trim_blanks(parms);
136511fce282SBaptiste Daroussin 	i = (int)strlen(parms) - 1;
136611fce282SBaptiste Daroussin 	if (i < 0)
136711fce282SBaptiste Daroussin 	{
136811fce282SBaptiste Daroussin 	    goto oops;
136911fce282SBaptiste Daroussin 	}
137011fce282SBaptiste Daroussin 
137111fce282SBaptiste Daroussin 	if (parms[i] == ']')
137211fce282SBaptiste Daroussin 	{
137311fce282SBaptiste Daroussin 	    int level = 1;
13748e022d3cSDag-Erling Smørgrav 	    while (i >= 0)
137511fce282SBaptiste Daroussin 	    {
13768e022d3cSDag-Erling Smørgrav 		char ch = parms[i--];
13778e022d3cSDag-Erling Smørgrav 		if (ch == ']')
13788e022d3cSDag-Erling Smørgrav 		{
137911fce282SBaptiste Daroussin 		    ++level;
13808e022d3cSDag-Erling Smørgrav 		}
13818e022d3cSDag-Erling Smørgrav 		else if (ch == '[')
13828e022d3cSDag-Erling Smørgrav 		{
13838e022d3cSDag-Erling Smørgrav 		    if (--level <= 1)
13848e022d3cSDag-Erling Smørgrav 		    {
13858e022d3cSDag-Erling Smørgrav 			++i;
13868e022d3cSDag-Erling Smørgrav 			break;
13878e022d3cSDag-Erling Smørgrav 		    }
13888e022d3cSDag-Erling Smørgrav 		}
138911fce282SBaptiste Daroussin 	    }
139011fce282SBaptiste Daroussin 	    if (i <= 0)
139111fce282SBaptiste Daroussin 		unexpected_EOF();
139211fce282SBaptiste Daroussin 	    type2 = i--;
139311fce282SBaptiste Daroussin 	}
139411fce282SBaptiste Daroussin 	else
139511fce282SBaptiste Daroussin 	{
139611fce282SBaptiste Daroussin 	    type2 = i + 1;
139711fce282SBaptiste Daroussin 	}
139811fce282SBaptiste Daroussin 
1399*822ca327SBaptiste Daroussin 	while (i > 0 && IS_ALNUM(UCH(parms[i])))
140011fce282SBaptiste Daroussin 	    i--;
140111fce282SBaptiste Daroussin 
140211fce282SBaptiste Daroussin 	if (!isspace(UCH(parms[i])) && parms[i] != '*')
140311fce282SBaptiste Daroussin 	    goto oops;
140411fce282SBaptiste Daroussin 
140511fce282SBaptiste Daroussin 	name = i + 1;
140611fce282SBaptiste Daroussin 
140711fce282SBaptiste Daroussin 	save_param(k, parms, name, type2);
140811fce282SBaptiste Daroussin     }
140911fce282SBaptiste Daroussin     while (comma != 0);
141011fce282SBaptiste Daroussin     FREE(buf);
141198e903e7SBaptiste Daroussin     return;
141298e903e7SBaptiste Daroussin 
141311fce282SBaptiste Daroussin   oops:
141411fce282SBaptiste Daroussin     FREE(buf);
141598e903e7SBaptiste Daroussin     syntax_error(lineno, line, cptr);
141698e903e7SBaptiste Daroussin }
141798e903e7SBaptiste Daroussin 
141898e903e7SBaptiste Daroussin static int
hexval(int c)141998e903e7SBaptiste Daroussin hexval(int c)
142098e903e7SBaptiste Daroussin {
142198e903e7SBaptiste Daroussin     if (c >= '0' && c <= '9')
142298e903e7SBaptiste Daroussin 	return (c - '0');
142398e903e7SBaptiste Daroussin     if (c >= 'A' && c <= 'F')
142498e903e7SBaptiste Daroussin 	return (c - 'A' + 10);
142598e903e7SBaptiste Daroussin     if (c >= 'a' && c <= 'f')
142698e903e7SBaptiste Daroussin 	return (c - 'a' + 10);
142798e903e7SBaptiste Daroussin     return (-1);
142898e903e7SBaptiste Daroussin }
142998e903e7SBaptiste Daroussin 
143098e903e7SBaptiste Daroussin static bucket *
get_literal(void)143198e903e7SBaptiste Daroussin get_literal(void)
143298e903e7SBaptiste Daroussin {
143398e903e7SBaptiste Daroussin     int c, quote;
143498e903e7SBaptiste Daroussin     int i;
143598e903e7SBaptiste Daroussin     int n;
143698e903e7SBaptiste Daroussin     char *s;
143798e903e7SBaptiste Daroussin     bucket *bp;
14382aca18c7SJung-uk Kim     struct ainfo a;
1439*822ca327SBaptiste Daroussin 
1440*822ca327SBaptiste Daroussin     begin_ainfo(a, 0);
144198e903e7SBaptiste Daroussin 
144298e903e7SBaptiste Daroussin     quote = *cptr++;
144398e903e7SBaptiste Daroussin     cinc = 0;
144498e903e7SBaptiste Daroussin     for (;;)
144598e903e7SBaptiste Daroussin     {
144698e903e7SBaptiste Daroussin 	c = *cptr++;
144798e903e7SBaptiste Daroussin 	if (c == quote)
144898e903e7SBaptiste Daroussin 	    break;
144998e903e7SBaptiste Daroussin 	if (c == '\n')
14502aca18c7SJung-uk Kim 	    unterminated_string(&a);
145198e903e7SBaptiste Daroussin 	if (c == '\\')
145298e903e7SBaptiste Daroussin 	{
145398e903e7SBaptiste Daroussin 	    char *c_cptr = cptr - 1;
145498e903e7SBaptiste Daroussin 
145598e903e7SBaptiste Daroussin 	    c = *cptr++;
145698e903e7SBaptiste Daroussin 	    switch (c)
145798e903e7SBaptiste Daroussin 	    {
145898e903e7SBaptiste Daroussin 	    case '\n':
145998e903e7SBaptiste Daroussin 		get_line();
1460c5b5d71aSJung-uk Kim 		if (line == NULL)
14612aca18c7SJung-uk Kim 		    unterminated_string(&a);
146298e903e7SBaptiste Daroussin 		continue;
146398e903e7SBaptiste Daroussin 
146498e903e7SBaptiste Daroussin 	    case '0':
146598e903e7SBaptiste Daroussin 	    case '1':
146698e903e7SBaptiste Daroussin 	    case '2':
146798e903e7SBaptiste Daroussin 	    case '3':
146898e903e7SBaptiste Daroussin 	    case '4':
146998e903e7SBaptiste Daroussin 	    case '5':
147098e903e7SBaptiste Daroussin 	    case '6':
147198e903e7SBaptiste Daroussin 	    case '7':
147298e903e7SBaptiste Daroussin 		n = c - '0';
147398e903e7SBaptiste Daroussin 		c = *cptr;
147498e903e7SBaptiste Daroussin 		if (IS_OCTAL(c))
147598e903e7SBaptiste Daroussin 		{
147698e903e7SBaptiste Daroussin 		    n = (n << 3) + (c - '0');
147798e903e7SBaptiste Daroussin 		    c = *++cptr;
147898e903e7SBaptiste Daroussin 		    if (IS_OCTAL(c))
147998e903e7SBaptiste Daroussin 		    {
148098e903e7SBaptiste Daroussin 			n = (n << 3) + (c - '0');
148198e903e7SBaptiste Daroussin 			++cptr;
148298e903e7SBaptiste Daroussin 		    }
148398e903e7SBaptiste Daroussin 		}
148498e903e7SBaptiste Daroussin 		if (n > MAXCHAR)
148598e903e7SBaptiste Daroussin 		    illegal_character(c_cptr);
148698e903e7SBaptiste Daroussin 		c = n;
148798e903e7SBaptiste Daroussin 		break;
148898e903e7SBaptiste Daroussin 
148998e903e7SBaptiste Daroussin 	    case 'x':
149098e903e7SBaptiste Daroussin 		c = *cptr++;
149198e903e7SBaptiste Daroussin 		n = hexval(c);
149298e903e7SBaptiste Daroussin 		if (n < 0 || n >= 16)
149398e903e7SBaptiste Daroussin 		    illegal_character(c_cptr);
149498e903e7SBaptiste Daroussin 		for (;;)
149598e903e7SBaptiste Daroussin 		{
149698e903e7SBaptiste Daroussin 		    c = *cptr;
149798e903e7SBaptiste Daroussin 		    i = hexval(c);
149898e903e7SBaptiste Daroussin 		    if (i < 0 || i >= 16)
149998e903e7SBaptiste Daroussin 			break;
150098e903e7SBaptiste Daroussin 		    ++cptr;
150198e903e7SBaptiste Daroussin 		    n = (n << 4) + i;
150298e903e7SBaptiste Daroussin 		    if (n > MAXCHAR)
150398e903e7SBaptiste Daroussin 			illegal_character(c_cptr);
150498e903e7SBaptiste Daroussin 		}
150598e903e7SBaptiste Daroussin 		c = n;
150698e903e7SBaptiste Daroussin 		break;
150798e903e7SBaptiste Daroussin 
150898e903e7SBaptiste Daroussin 	    case 'a':
150998e903e7SBaptiste Daroussin 		c = 7;
151098e903e7SBaptiste Daroussin 		break;
151198e903e7SBaptiste Daroussin 	    case 'b':
151298e903e7SBaptiste Daroussin 		c = '\b';
151398e903e7SBaptiste Daroussin 		break;
151498e903e7SBaptiste Daroussin 	    case 'f':
151598e903e7SBaptiste Daroussin 		c = '\f';
151698e903e7SBaptiste Daroussin 		break;
151798e903e7SBaptiste Daroussin 	    case 'n':
151898e903e7SBaptiste Daroussin 		c = '\n';
151998e903e7SBaptiste Daroussin 		break;
152098e903e7SBaptiste Daroussin 	    case 'r':
152198e903e7SBaptiste Daroussin 		c = '\r';
152298e903e7SBaptiste Daroussin 		break;
152398e903e7SBaptiste Daroussin 	    case 't':
152498e903e7SBaptiste Daroussin 		c = '\t';
152598e903e7SBaptiste Daroussin 		break;
152698e903e7SBaptiste Daroussin 	    case 'v':
152798e903e7SBaptiste Daroussin 		c = '\v';
152898e903e7SBaptiste Daroussin 		break;
152998e903e7SBaptiste Daroussin 	    }
153098e903e7SBaptiste Daroussin 	}
153198e903e7SBaptiste Daroussin 	cachec(c);
153298e903e7SBaptiste Daroussin     }
1533*822ca327SBaptiste Daroussin     end_ainfo(a);
153498e903e7SBaptiste Daroussin 
153598e903e7SBaptiste Daroussin     n = cinc;
15363e066022SBaptiste Daroussin     s = TMALLOC(char, n);
153798e903e7SBaptiste Daroussin     NO_SPACE(s);
153898e903e7SBaptiste Daroussin 
153998e903e7SBaptiste Daroussin     for (i = 0; i < n; ++i)
154098e903e7SBaptiste Daroussin 	s[i] = cache[i];
154198e903e7SBaptiste Daroussin 
154298e903e7SBaptiste Daroussin     cinc = 0;
154398e903e7SBaptiste Daroussin     if (n == 1)
154498e903e7SBaptiste Daroussin 	cachec('\'');
154598e903e7SBaptiste Daroussin     else
154698e903e7SBaptiste Daroussin 	cachec('"');
154798e903e7SBaptiste Daroussin 
154898e903e7SBaptiste Daroussin     for (i = 0; i < n; ++i)
154998e903e7SBaptiste Daroussin     {
155098e903e7SBaptiste Daroussin 	c = UCH(s[i]);
155198e903e7SBaptiste Daroussin 	if (c == '\\' || c == cache[0])
155298e903e7SBaptiste Daroussin 	{
155398e903e7SBaptiste Daroussin 	    cachec('\\');
155498e903e7SBaptiste Daroussin 	    cachec(c);
155598e903e7SBaptiste Daroussin 	}
1556b53bb29fSJung-uk Kim 	else if (isprint(UCH(c)))
155798e903e7SBaptiste Daroussin 	    cachec(c);
155898e903e7SBaptiste Daroussin 	else
155998e903e7SBaptiste Daroussin 	{
156098e903e7SBaptiste Daroussin 	    cachec('\\');
156198e903e7SBaptiste Daroussin 	    switch (c)
156298e903e7SBaptiste Daroussin 	    {
156398e903e7SBaptiste Daroussin 	    case 7:
156498e903e7SBaptiste Daroussin 		cachec('a');
156598e903e7SBaptiste Daroussin 		break;
156698e903e7SBaptiste Daroussin 	    case '\b':
156798e903e7SBaptiste Daroussin 		cachec('b');
156898e903e7SBaptiste Daroussin 		break;
156998e903e7SBaptiste Daroussin 	    case '\f':
157098e903e7SBaptiste Daroussin 		cachec('f');
157198e903e7SBaptiste Daroussin 		break;
157298e903e7SBaptiste Daroussin 	    case '\n':
157398e903e7SBaptiste Daroussin 		cachec('n');
157498e903e7SBaptiste Daroussin 		break;
157598e903e7SBaptiste Daroussin 	    case '\r':
157698e903e7SBaptiste Daroussin 		cachec('r');
157798e903e7SBaptiste Daroussin 		break;
157898e903e7SBaptiste Daroussin 	    case '\t':
157998e903e7SBaptiste Daroussin 		cachec('t');
158098e903e7SBaptiste Daroussin 		break;
158198e903e7SBaptiste Daroussin 	    case '\v':
158298e903e7SBaptiste Daroussin 		cachec('v');
158398e903e7SBaptiste Daroussin 		break;
158498e903e7SBaptiste Daroussin 	    default:
158598e903e7SBaptiste Daroussin 		cachec(((c >> 6) & 7) + '0');
158698e903e7SBaptiste Daroussin 		cachec(((c >> 3) & 7) + '0');
158798e903e7SBaptiste Daroussin 		cachec((c & 7) + '0');
158898e903e7SBaptiste Daroussin 		break;
158998e903e7SBaptiste Daroussin 	    }
159098e903e7SBaptiste Daroussin 	}
159198e903e7SBaptiste Daroussin     }
159298e903e7SBaptiste Daroussin 
159398e903e7SBaptiste Daroussin     if (n == 1)
159498e903e7SBaptiste Daroussin 	cachec('\'');
159598e903e7SBaptiste Daroussin     else
159698e903e7SBaptiste Daroussin 	cachec('"');
159798e903e7SBaptiste Daroussin 
159898e903e7SBaptiste Daroussin     cachec(NUL);
159998e903e7SBaptiste Daroussin     bp = lookup(cache);
160098e903e7SBaptiste Daroussin     bp->class = TERM;
160198e903e7SBaptiste Daroussin     if (n == 1 && bp->value == UNDEFINED)
160298e903e7SBaptiste Daroussin 	bp->value = UCH(*s);
160398e903e7SBaptiste Daroussin     FREE(s);
160498e903e7SBaptiste Daroussin 
160598e903e7SBaptiste Daroussin     return (bp);
160698e903e7SBaptiste Daroussin }
160798e903e7SBaptiste Daroussin 
160898e903e7SBaptiste Daroussin static int
is_reserved(char * name)160998e903e7SBaptiste Daroussin is_reserved(char *name)
161098e903e7SBaptiste Daroussin {
161198e903e7SBaptiste Daroussin     if (strcmp(name, ".") == 0 ||
161298e903e7SBaptiste Daroussin 	strcmp(name, "$accept") == 0 ||
161398e903e7SBaptiste Daroussin 	strcmp(name, "$end") == 0)
161498e903e7SBaptiste Daroussin 	return (1);
161598e903e7SBaptiste Daroussin 
161698e903e7SBaptiste Daroussin     if (name[0] == '$' && name[1] == '$' && isdigit(UCH(name[2])))
161798e903e7SBaptiste Daroussin     {
16188e022d3cSDag-Erling Smørgrav 	char *s = name + 3;
16198e022d3cSDag-Erling Smørgrav 
162098e903e7SBaptiste Daroussin 	while (isdigit(UCH(*s)))
162198e903e7SBaptiste Daroussin 	    ++s;
162298e903e7SBaptiste Daroussin 	if (*s == NUL)
162398e903e7SBaptiste Daroussin 	    return (1);
162498e903e7SBaptiste Daroussin     }
162598e903e7SBaptiste Daroussin 
162698e903e7SBaptiste Daroussin     return (0);
162798e903e7SBaptiste Daroussin }
162898e903e7SBaptiste Daroussin 
162998e903e7SBaptiste Daroussin static bucket *
get_name(void)163098e903e7SBaptiste Daroussin get_name(void)
163198e903e7SBaptiste Daroussin {
163298e903e7SBaptiste Daroussin     int c;
163398e903e7SBaptiste Daroussin 
163498e903e7SBaptiste Daroussin     cinc = 0;
163598e903e7SBaptiste Daroussin     for (c = *cptr; IS_IDENT(c); c = *++cptr)
163698e903e7SBaptiste Daroussin 	cachec(c);
163798e903e7SBaptiste Daroussin     cachec(NUL);
163898e903e7SBaptiste Daroussin 
163998e903e7SBaptiste Daroussin     if (is_reserved(cache))
164098e903e7SBaptiste Daroussin 	used_reserved(cache);
164198e903e7SBaptiste Daroussin 
164298e903e7SBaptiste Daroussin     return (lookup(cache));
164398e903e7SBaptiste Daroussin }
164498e903e7SBaptiste Daroussin 
164598e903e7SBaptiste Daroussin static Value_t
get_number(void)164698e903e7SBaptiste Daroussin get_number(void)
164798e903e7SBaptiste Daroussin {
164898e903e7SBaptiste Daroussin     int c;
1649b53bb29fSJung-uk Kim     long n;
1650b53bb29fSJung-uk Kim     char *base = cptr;
165198e903e7SBaptiste Daroussin 
165298e903e7SBaptiste Daroussin     n = 0;
1653b53bb29fSJung-uk Kim     for (c = *cptr; isdigit(UCH(c)); c = *++cptr)
1654b53bb29fSJung-uk Kim     {
1655b53bb29fSJung-uk Kim 	n = (10 * n + (c - '0'));
1656b53bb29fSJung-uk Kim 	if (n > MAXYYINT)
1657b53bb29fSJung-uk Kim 	{
1658b53bb29fSJung-uk Kim 	    syntax_error(lineno, line, base);
1659b53bb29fSJung-uk Kim 	    /*NOTREACHED */
1660b53bb29fSJung-uk Kim 	}
1661b53bb29fSJung-uk Kim     }
166298e903e7SBaptiste Daroussin 
1663b53bb29fSJung-uk Kim     return (Value_t)(n);
166498e903e7SBaptiste Daroussin }
166598e903e7SBaptiste Daroussin 
166698e903e7SBaptiste Daroussin static char *
cache_tag(char * tag,size_t len)16670c8de5b0SBaptiste Daroussin cache_tag(char *tag, size_t len)
16680c8de5b0SBaptiste Daroussin {
16690c8de5b0SBaptiste Daroussin     int i;
16700c8de5b0SBaptiste Daroussin     char *s;
16710c8de5b0SBaptiste Daroussin 
16720c8de5b0SBaptiste Daroussin     for (i = 0; i < ntags; ++i)
16730c8de5b0SBaptiste Daroussin     {
16740c8de5b0SBaptiste Daroussin 	if (strncmp(tag, tag_table[i], len) == 0 &&
16750c8de5b0SBaptiste Daroussin 	    tag_table[i][len] == NUL)
16760c8de5b0SBaptiste Daroussin 	    return (tag_table[i]);
16770c8de5b0SBaptiste Daroussin     }
16780c8de5b0SBaptiste Daroussin 
16790c8de5b0SBaptiste Daroussin     if (ntags >= tagmax)
16800c8de5b0SBaptiste Daroussin     {
16810c8de5b0SBaptiste Daroussin 	tagmax += 16;
16820c8de5b0SBaptiste Daroussin 	tag_table =
16830c8de5b0SBaptiste Daroussin 	    (tag_table
16840c8de5b0SBaptiste Daroussin 	     ? TREALLOC(char *, tag_table, tagmax)
16850c8de5b0SBaptiste Daroussin 	     : TMALLOC(char *, tagmax));
16860c8de5b0SBaptiste Daroussin 	NO_SPACE(tag_table);
16870c8de5b0SBaptiste Daroussin     }
16880c8de5b0SBaptiste Daroussin 
16890c8de5b0SBaptiste Daroussin     s = TMALLOC(char, len + 1);
16900c8de5b0SBaptiste Daroussin     NO_SPACE(s);
16910c8de5b0SBaptiste Daroussin 
16920c8de5b0SBaptiste Daroussin     strncpy(s, tag, len);
16930c8de5b0SBaptiste Daroussin     s[len] = 0;
16940c8de5b0SBaptiste Daroussin     tag_table[ntags++] = s;
16950c8de5b0SBaptiste Daroussin     return s;
16960c8de5b0SBaptiste Daroussin }
16970c8de5b0SBaptiste Daroussin 
16980c8de5b0SBaptiste Daroussin static char *
get_tag(void)169998e903e7SBaptiste Daroussin get_tag(void)
170098e903e7SBaptiste Daroussin {
170198e903e7SBaptiste Daroussin     int c;
170298e903e7SBaptiste Daroussin     int t_lineno = lineno;
170398e903e7SBaptiste Daroussin     char *t_line = dup_line();
170498e903e7SBaptiste Daroussin     char *t_cptr = t_line + (cptr - line);
170598e903e7SBaptiste Daroussin 
170698e903e7SBaptiste Daroussin     ++cptr;
170798e903e7SBaptiste Daroussin     c = nextc();
170898e903e7SBaptiste Daroussin     if (c == EOF)
170998e903e7SBaptiste Daroussin 	unexpected_EOF();
1710b53bb29fSJung-uk Kim     if (!IS_NAME1(c))
171198e903e7SBaptiste Daroussin 	illegal_tag(t_lineno, t_line, t_cptr);
171298e903e7SBaptiste Daroussin 
171398e903e7SBaptiste Daroussin     cinc = 0;
171498e903e7SBaptiste Daroussin     do
171598e903e7SBaptiste Daroussin     {
171698e903e7SBaptiste Daroussin 	cachec(c);
171798e903e7SBaptiste Daroussin 	c = *++cptr;
171898e903e7SBaptiste Daroussin     }
171998e903e7SBaptiste Daroussin     while (IS_IDENT(c));
172098e903e7SBaptiste Daroussin     cachec(NUL);
172198e903e7SBaptiste Daroussin 
172298e903e7SBaptiste Daroussin     c = nextc();
172398e903e7SBaptiste Daroussin     if (c == EOF)
172498e903e7SBaptiste Daroussin 	unexpected_EOF();
172598e903e7SBaptiste Daroussin     if (c != '>')
172698e903e7SBaptiste Daroussin 	illegal_tag(t_lineno, t_line, t_cptr);
172798e903e7SBaptiste Daroussin     ++cptr;
172898e903e7SBaptiste Daroussin 
172998e903e7SBaptiste Daroussin     FREE(t_line);
17300c8de5b0SBaptiste Daroussin     havetags = 1;
17310c8de5b0SBaptiste Daroussin     return cache_tag(cache, (size_t)cinc);
173298e903e7SBaptiste Daroussin }
173398e903e7SBaptiste Daroussin 
17340c8de5b0SBaptiste Daroussin #if defined(YYBTYACC)
17350c8de5b0SBaptiste Daroussin static char *
scan_id(void)17360c8de5b0SBaptiste Daroussin scan_id(void)
173798e903e7SBaptiste Daroussin {
17380c8de5b0SBaptiste Daroussin     char *b = cptr;
173998e903e7SBaptiste Daroussin 
1740b53bb29fSJung-uk Kim     while (IS_NAME2(UCH(*cptr)))
17410c8de5b0SBaptiste Daroussin 	cptr++;
17420c8de5b0SBaptiste Daroussin     return cache_tag(b, (size_t)(cptr - b));
174398e903e7SBaptiste Daroussin }
17440c8de5b0SBaptiste Daroussin #endif
174598e903e7SBaptiste Daroussin 
174698e903e7SBaptiste Daroussin static void
declare_tokens(int assoc)174798e903e7SBaptiste Daroussin declare_tokens(int assoc)
174898e903e7SBaptiste Daroussin {
174998e903e7SBaptiste Daroussin     int c;
175098e903e7SBaptiste Daroussin     bucket *bp;
175198e903e7SBaptiste Daroussin     Value_t value;
175298e903e7SBaptiste Daroussin     char *tag = 0;
175398e903e7SBaptiste Daroussin 
175498e903e7SBaptiste Daroussin     if (assoc != TOKEN)
175598e903e7SBaptiste Daroussin 	++prec;
175698e903e7SBaptiste Daroussin 
175798e903e7SBaptiste Daroussin     c = nextc();
175898e903e7SBaptiste Daroussin     if (c == EOF)
175998e903e7SBaptiste Daroussin 	unexpected_EOF();
176098e903e7SBaptiste Daroussin     if (c == '<')
176198e903e7SBaptiste Daroussin     {
176298e903e7SBaptiste Daroussin 	tag = get_tag();
176398e903e7SBaptiste Daroussin 	c = nextc();
176498e903e7SBaptiste Daroussin 	if (c == EOF)
176598e903e7SBaptiste Daroussin 	    unexpected_EOF();
176698e903e7SBaptiste Daroussin     }
176798e903e7SBaptiste Daroussin 
176898e903e7SBaptiste Daroussin     for (;;)
176998e903e7SBaptiste Daroussin     {
1770b53bb29fSJung-uk Kim 	if (isalpha(UCH(c)) || c == '_' || c == '.' || c == '$')
177198e903e7SBaptiste Daroussin 	    bp = get_name();
177298e903e7SBaptiste Daroussin 	else if (c == '\'' || c == '"')
177398e903e7SBaptiste Daroussin 	    bp = get_literal();
177498e903e7SBaptiste Daroussin 	else
177598e903e7SBaptiste Daroussin 	    return;
177698e903e7SBaptiste Daroussin 
177798e903e7SBaptiste Daroussin 	if (bp == goal)
177898e903e7SBaptiste Daroussin 	    tokenized_start(bp->name);
177998e903e7SBaptiste Daroussin 	bp->class = TERM;
178098e903e7SBaptiste Daroussin 
178198e903e7SBaptiste Daroussin 	if (tag)
178298e903e7SBaptiste Daroussin 	{
178398e903e7SBaptiste Daroussin 	    if (bp->tag && tag != bp->tag)
178498e903e7SBaptiste Daroussin 		retyped_warning(bp->name);
178598e903e7SBaptiste Daroussin 	    bp->tag = tag;
178698e903e7SBaptiste Daroussin 	}
178798e903e7SBaptiste Daroussin 
178898e903e7SBaptiste Daroussin 	if (assoc != TOKEN)
178998e903e7SBaptiste Daroussin 	{
179098e903e7SBaptiste Daroussin 	    if (bp->prec && prec != bp->prec)
179198e903e7SBaptiste Daroussin 		reprec_warning(bp->name);
179298e903e7SBaptiste Daroussin 	    bp->assoc = (Assoc_t)assoc;
179398e903e7SBaptiste Daroussin 	    bp->prec = prec;
179498e903e7SBaptiste Daroussin 	}
179598e903e7SBaptiste Daroussin 
179698e903e7SBaptiste Daroussin 	c = nextc();
179798e903e7SBaptiste Daroussin 	if (c == EOF)
179898e903e7SBaptiste Daroussin 	    unexpected_EOF();
179998e903e7SBaptiste Daroussin 
1800b53bb29fSJung-uk Kim 	if (isdigit(UCH(c)))
180198e903e7SBaptiste Daroussin 	{
180298e903e7SBaptiste Daroussin 	    value = get_number();
180398e903e7SBaptiste Daroussin 	    if (bp->value != UNDEFINED && value != bp->value)
180498e903e7SBaptiste Daroussin 		revalued_warning(bp->name);
180598e903e7SBaptiste Daroussin 	    bp->value = value;
180698e903e7SBaptiste Daroussin 	    c = nextc();
180798e903e7SBaptiste Daroussin 	    if (c == EOF)
180898e903e7SBaptiste Daroussin 		unexpected_EOF();
180998e903e7SBaptiste Daroussin 	}
181098e903e7SBaptiste Daroussin     }
181198e903e7SBaptiste Daroussin }
181298e903e7SBaptiste Daroussin 
181398e903e7SBaptiste Daroussin /*
181498e903e7SBaptiste Daroussin  * %expect requires special handling
181598e903e7SBaptiste Daroussin  * as it really isn't part of the yacc
181698e903e7SBaptiste Daroussin  * grammar only a flag for yacc proper.
181798e903e7SBaptiste Daroussin  */
181898e903e7SBaptiste Daroussin static void
declare_expect(int assoc)181998e903e7SBaptiste Daroussin declare_expect(int assoc)
182098e903e7SBaptiste Daroussin {
182198e903e7SBaptiste Daroussin     int c;
182298e903e7SBaptiste Daroussin 
182398e903e7SBaptiste Daroussin     if (assoc != EXPECT && assoc != EXPECT_RR)
182498e903e7SBaptiste Daroussin 	++prec;
182598e903e7SBaptiste Daroussin 
182698e903e7SBaptiste Daroussin     /*
182798e903e7SBaptiste Daroussin      * Stay away from nextc - doesn't
182898e903e7SBaptiste Daroussin      * detect EOL and will read to EOF.
182998e903e7SBaptiste Daroussin      */
183098e903e7SBaptiste Daroussin     c = *++cptr;
183198e903e7SBaptiste Daroussin     if (c == EOF)
183298e903e7SBaptiste Daroussin 	unexpected_EOF();
183398e903e7SBaptiste Daroussin 
183498e903e7SBaptiste Daroussin     for (;;)
183598e903e7SBaptiste Daroussin     {
1836b53bb29fSJung-uk Kim 	if (isdigit(UCH(c)))
183798e903e7SBaptiste Daroussin 	{
183898e903e7SBaptiste Daroussin 	    if (assoc == EXPECT)
183998e903e7SBaptiste Daroussin 		SRexpect = get_number();
184098e903e7SBaptiste Daroussin 	    else
184198e903e7SBaptiste Daroussin 		RRexpect = get_number();
184298e903e7SBaptiste Daroussin 	    break;
184398e903e7SBaptiste Daroussin 	}
184498e903e7SBaptiste Daroussin 	/*
184598e903e7SBaptiste Daroussin 	 * Looking for number before EOL.
184698e903e7SBaptiste Daroussin 	 * Spaces, tabs, and numbers are ok,
184798e903e7SBaptiste Daroussin 	 * words, punc., etc. are syntax errors.
184898e903e7SBaptiste Daroussin 	 */
1849b53bb29fSJung-uk Kim 	else if (c == '\n' || isalpha(UCH(c)) || !isspace(UCH(c)))
185098e903e7SBaptiste Daroussin 	{
185198e903e7SBaptiste Daroussin 	    syntax_error(lineno, line, cptr);
185298e903e7SBaptiste Daroussin 	}
185398e903e7SBaptiste Daroussin 	else
185498e903e7SBaptiste Daroussin 	{
185598e903e7SBaptiste Daroussin 	    c = *++cptr;
185698e903e7SBaptiste Daroussin 	    if (c == EOF)
185798e903e7SBaptiste Daroussin 		unexpected_EOF();
185898e903e7SBaptiste Daroussin 	}
185998e903e7SBaptiste Daroussin     }
186098e903e7SBaptiste Daroussin }
186198e903e7SBaptiste Daroussin 
18620c8de5b0SBaptiste Daroussin #if defined(YYBTYACC)
186398e903e7SBaptiste Daroussin static void
declare_argtypes(bucket * bp)18640c8de5b0SBaptiste Daroussin declare_argtypes(bucket *bp)
186598e903e7SBaptiste Daroussin {
18660c8de5b0SBaptiste Daroussin     char *tags[MAXARGS];
18678e022d3cSDag-Erling Smørgrav     int args = 0;
186898e903e7SBaptiste Daroussin 
18690c8de5b0SBaptiste Daroussin     if (bp->args >= 0)
18700c8de5b0SBaptiste Daroussin 	retyped_warning(bp->name);
18710c8de5b0SBaptiste Daroussin     cptr++;			/* skip open paren */
18720c8de5b0SBaptiste Daroussin     for (;;)
18730c8de5b0SBaptiste Daroussin     {
18748e022d3cSDag-Erling Smørgrav 	int c = nextc();
187598e903e7SBaptiste Daroussin 	if (c == EOF)
187698e903e7SBaptiste Daroussin 	    unexpected_EOF();
187798e903e7SBaptiste Daroussin 	if (c != '<')
187898e903e7SBaptiste Daroussin 	    syntax_error(lineno, line, cptr);
18790c8de5b0SBaptiste Daroussin 	tags[args++] = get_tag();
18800c8de5b0SBaptiste Daroussin 	c = nextc();
18810c8de5b0SBaptiste Daroussin 	if (c == R_PAREN)
18820c8de5b0SBaptiste Daroussin 	    break;
18830c8de5b0SBaptiste Daroussin 	if (c == EOF)
18840c8de5b0SBaptiste Daroussin 	    unexpected_EOF();
18850c8de5b0SBaptiste Daroussin     }
18860c8de5b0SBaptiste Daroussin     cptr++;			/* skip close paren */
18870c8de5b0SBaptiste Daroussin     bp->args = args;
18880c8de5b0SBaptiste Daroussin     bp->argnames = TMALLOC(char *, args);
18890c8de5b0SBaptiste Daroussin     NO_SPACE(bp->argnames);
18900c8de5b0SBaptiste Daroussin     bp->argtags = CALLOC(sizeof(char *), args + 1);
18910c8de5b0SBaptiste Daroussin     NO_SPACE(bp->argtags);
18920c8de5b0SBaptiste Daroussin     while (--args >= 0)
18930c8de5b0SBaptiste Daroussin     {
18940c8de5b0SBaptiste Daroussin 	bp->argtags[args] = tags[args];
18950c8de5b0SBaptiste Daroussin 	bp->argnames[args] = NULL;
18960c8de5b0SBaptiste Daroussin     }
18970c8de5b0SBaptiste Daroussin }
18980c8de5b0SBaptiste Daroussin #endif
18990c8de5b0SBaptiste Daroussin 
1900*822ca327SBaptiste Daroussin static int
scan_blanks(void)1901*822ca327SBaptiste Daroussin scan_blanks(void)
1902*822ca327SBaptiste Daroussin {
1903*822ca327SBaptiste Daroussin     int c;
1904*822ca327SBaptiste Daroussin 
1905*822ca327SBaptiste Daroussin     do
1906*822ca327SBaptiste Daroussin     {
1907*822ca327SBaptiste Daroussin 	c = next_inline();
1908*822ca327SBaptiste Daroussin 	if (c == '\n')
1909*822ca327SBaptiste Daroussin 	{
1910*822ca327SBaptiste Daroussin 	    ++cptr;
1911*822ca327SBaptiste Daroussin 	    return 0;
1912*822ca327SBaptiste Daroussin 	}
1913*822ca327SBaptiste Daroussin 	else if (c == ' ' || c == '\t')
1914*822ca327SBaptiste Daroussin 	    ++cptr;
1915*822ca327SBaptiste Daroussin 	else
1916*822ca327SBaptiste Daroussin 	    break;
1917*822ca327SBaptiste Daroussin     }
1918*822ca327SBaptiste Daroussin     while (c == ' ' || c == '\t');
1919*822ca327SBaptiste Daroussin 
1920*822ca327SBaptiste Daroussin     return 1;
1921*822ca327SBaptiste Daroussin }
1922*822ca327SBaptiste Daroussin 
1923*822ca327SBaptiste Daroussin static int
scan_ident(void)1924*822ca327SBaptiste Daroussin scan_ident(void)
1925*822ca327SBaptiste Daroussin {
1926*822ca327SBaptiste Daroussin     int c;
1927*822ca327SBaptiste Daroussin 
1928*822ca327SBaptiste Daroussin     cinc = 0;
1929*822ca327SBaptiste Daroussin     for (c = *cptr; IS_IDENT(c); c = *++cptr)
1930*822ca327SBaptiste Daroussin 	cachec(c);
1931*822ca327SBaptiste Daroussin     cachec(NUL);
1932*822ca327SBaptiste Daroussin 
1933*822ca327SBaptiste Daroussin     return cinc;
1934*822ca327SBaptiste Daroussin }
1935*822ca327SBaptiste Daroussin 
1936*822ca327SBaptiste Daroussin static void
hack_defines(void)1937*822ca327SBaptiste Daroussin hack_defines(void)
1938*822ca327SBaptiste Daroussin {
1939*822ca327SBaptiste Daroussin     struct ainfo a;
1940*822ca327SBaptiste Daroussin 
1941*822ca327SBaptiste Daroussin     if (!scan_blanks())
1942*822ca327SBaptiste Daroussin 	return;
1943*822ca327SBaptiste Daroussin 
1944*822ca327SBaptiste Daroussin     begin_ainfo(a, 0);
1945*822ca327SBaptiste Daroussin     if (!scan_ident())
1946*822ca327SBaptiste Daroussin     {
1947*822ca327SBaptiste Daroussin 	end_ainfo(a);
1948*822ca327SBaptiste Daroussin     }
1949*822ca327SBaptiste Daroussin 
1950*822ca327SBaptiste Daroussin     if (!strcmp(cache, "api.pure"))
1951*822ca327SBaptiste Daroussin     {
1952*822ca327SBaptiste Daroussin 	end_ainfo(a);
1953*822ca327SBaptiste Daroussin 	scan_blanks();
1954*822ca327SBaptiste Daroussin 	begin_ainfo(a, 0);
1955*822ca327SBaptiste Daroussin 	scan_ident();
1956*822ca327SBaptiste Daroussin 
1957*822ca327SBaptiste Daroussin 	if (!strcmp(cache, "false"))
1958*822ca327SBaptiste Daroussin 	    pure_parser = 0;
1959*822ca327SBaptiste Daroussin 	else if (!strcmp(cache, "true")
1960*822ca327SBaptiste Daroussin 		 || !strcmp(cache, "full")
1961*822ca327SBaptiste Daroussin 		 || *cache == 0)
1962*822ca327SBaptiste Daroussin 	    pure_parser = 1;
1963*822ca327SBaptiste Daroussin 	else
1964*822ca327SBaptiste Daroussin 	    unexpected_value(&a);
1965*822ca327SBaptiste Daroussin 	end_ainfo(a);
1966*822ca327SBaptiste Daroussin     }
1967*822ca327SBaptiste Daroussin     else
1968*822ca327SBaptiste Daroussin     {
1969*822ca327SBaptiste Daroussin 	unexpected_value(&a);
1970*822ca327SBaptiste Daroussin     }
1971*822ca327SBaptiste Daroussin 
1972*822ca327SBaptiste Daroussin     while (next_inline() != '\n')
1973*822ca327SBaptiste Daroussin 	++cptr;
1974*822ca327SBaptiste Daroussin }
1975*822ca327SBaptiste Daroussin 
19760c8de5b0SBaptiste Daroussin static void
declare_types(void)19770c8de5b0SBaptiste Daroussin declare_types(void)
19780c8de5b0SBaptiste Daroussin {
19790c8de5b0SBaptiste Daroussin     int c;
1980c5b5d71aSJung-uk Kim     bucket *bp = NULL;
19810c8de5b0SBaptiste Daroussin     char *tag = NULL;
19820c8de5b0SBaptiste Daroussin 
19830c8de5b0SBaptiste Daroussin     c = nextc();
19840c8de5b0SBaptiste Daroussin     if (c == EOF)
19850c8de5b0SBaptiste Daroussin 	unexpected_EOF();
19860c8de5b0SBaptiste Daroussin     if (c == '<')
198798e903e7SBaptiste Daroussin 	tag = get_tag();
198898e903e7SBaptiste Daroussin 
198998e903e7SBaptiste Daroussin     for (;;)
199098e903e7SBaptiste Daroussin     {
199198e903e7SBaptiste Daroussin 	c = nextc();
19920c8de5b0SBaptiste Daroussin 	if (c == EOF)
19930c8de5b0SBaptiste Daroussin 	    unexpected_EOF();
1994b53bb29fSJung-uk Kim 	if (isalpha(UCH(c)) || c == '_' || c == '.' || c == '$')
19950c8de5b0SBaptiste Daroussin 	{
199698e903e7SBaptiste Daroussin 	    bp = get_name();
19970c8de5b0SBaptiste Daroussin #if defined(YYBTYACC)
19980c8de5b0SBaptiste Daroussin 	    if (nextc() == L_PAREN)
19990c8de5b0SBaptiste Daroussin 		declare_argtypes(bp);
20000c8de5b0SBaptiste Daroussin 	    else
20010c8de5b0SBaptiste Daroussin 		bp->args = 0;
20020c8de5b0SBaptiste Daroussin #endif
20030c8de5b0SBaptiste Daroussin 	}
200498e903e7SBaptiste Daroussin 	else if (c == '\'' || c == '"')
20050c8de5b0SBaptiste Daroussin 	{
200698e903e7SBaptiste Daroussin 	    bp = get_literal();
20070c8de5b0SBaptiste Daroussin #if defined(YYBTYACC)
20080c8de5b0SBaptiste Daroussin 	    bp->args = 0;
20090c8de5b0SBaptiste Daroussin #endif
20100c8de5b0SBaptiste Daroussin 	}
201198e903e7SBaptiste Daroussin 	else
201298e903e7SBaptiste Daroussin 	    return;
201398e903e7SBaptiste Daroussin 
20140c8de5b0SBaptiste Daroussin 	if (tag)
20150c8de5b0SBaptiste Daroussin 	{
201698e903e7SBaptiste Daroussin 	    if (bp->tag && tag != bp->tag)
201798e903e7SBaptiste Daroussin 		retyped_warning(bp->name);
201898e903e7SBaptiste Daroussin 	    bp->tag = tag;
201998e903e7SBaptiste Daroussin 	}
202098e903e7SBaptiste Daroussin     }
20210c8de5b0SBaptiste Daroussin }
202298e903e7SBaptiste Daroussin 
202398e903e7SBaptiste Daroussin static void
declare_start(void)202498e903e7SBaptiste Daroussin declare_start(void)
202598e903e7SBaptiste Daroussin {
202698e903e7SBaptiste Daroussin     int c;
202798e903e7SBaptiste Daroussin     bucket *bp;
202898e903e7SBaptiste Daroussin 
202998e903e7SBaptiste Daroussin     c = nextc();
203098e903e7SBaptiste Daroussin     if (c == EOF)
203198e903e7SBaptiste Daroussin 	unexpected_EOF();
2032b53bb29fSJung-uk Kim     if (!isalpha(UCH(c)) && c != '_' && c != '.' && c != '$')
203398e903e7SBaptiste Daroussin 	syntax_error(lineno, line, cptr);
203498e903e7SBaptiste Daroussin     bp = get_name();
203598e903e7SBaptiste Daroussin     if (bp->class == TERM)
203698e903e7SBaptiste Daroussin 	terminal_start(bp->name);
203798e903e7SBaptiste Daroussin     if (goal && goal != bp)
203898e903e7SBaptiste Daroussin 	restarted_warning();
203998e903e7SBaptiste Daroussin     goal = bp;
204098e903e7SBaptiste Daroussin }
204198e903e7SBaptiste Daroussin 
204298e903e7SBaptiste Daroussin static void
read_declarations(void)204398e903e7SBaptiste Daroussin read_declarations(void)
204498e903e7SBaptiste Daroussin {
20450f86d14eSJung-uk Kim     cache_size = CACHE_SIZE;
20463e066022SBaptiste Daroussin     cache = TMALLOC(char, cache_size);
204798e903e7SBaptiste Daroussin     NO_SPACE(cache);
204898e903e7SBaptiste Daroussin 
204998e903e7SBaptiste Daroussin     for (;;)
205098e903e7SBaptiste Daroussin     {
20518e022d3cSDag-Erling Smørgrav 	int k;
20528e022d3cSDag-Erling Smørgrav 	int c = nextc();
20538e022d3cSDag-Erling Smørgrav 
205498e903e7SBaptiste Daroussin 	if (c == EOF)
205598e903e7SBaptiste Daroussin 	    unexpected_EOF();
205698e903e7SBaptiste Daroussin 	if (c != '%')
205798e903e7SBaptiste Daroussin 	    syntax_error(lineno, line, cptr);
205898e903e7SBaptiste Daroussin 	switch (k = keyword())
205998e903e7SBaptiste Daroussin 	{
206098e903e7SBaptiste Daroussin 	case MARK:
206198e903e7SBaptiste Daroussin 	    return;
206298e903e7SBaptiste Daroussin 
206398e903e7SBaptiste Daroussin 	case IDENT:
206498e903e7SBaptiste Daroussin 	    copy_ident();
206598e903e7SBaptiste Daroussin 	    break;
206698e903e7SBaptiste Daroussin 
2067b53bb29fSJung-uk Kim 	case XCODE:
2068b53bb29fSJung-uk Kim 	    copy_code();
2069b53bb29fSJung-uk Kim 	    break;
2070b53bb29fSJung-uk Kim 
207198e903e7SBaptiste Daroussin 	case TEXT:
207298e903e7SBaptiste Daroussin 	    copy_text();
207398e903e7SBaptiste Daroussin 	    break;
207498e903e7SBaptiste Daroussin 
207598e903e7SBaptiste Daroussin 	case UNION:
207698e903e7SBaptiste Daroussin 	    copy_union();
207798e903e7SBaptiste Daroussin 	    break;
207898e903e7SBaptiste Daroussin 
207998e903e7SBaptiste Daroussin 	case TOKEN:
208098e903e7SBaptiste Daroussin 	case LEFT:
208198e903e7SBaptiste Daroussin 	case RIGHT:
208298e903e7SBaptiste Daroussin 	case NONASSOC:
208398e903e7SBaptiste Daroussin 	    declare_tokens(k);
208498e903e7SBaptiste Daroussin 	    break;
208598e903e7SBaptiste Daroussin 
208698e903e7SBaptiste Daroussin 	case EXPECT:
208798e903e7SBaptiste Daroussin 	case EXPECT_RR:
208898e903e7SBaptiste Daroussin 	    declare_expect(k);
208998e903e7SBaptiste Daroussin 	    break;
209098e903e7SBaptiste Daroussin 
209198e903e7SBaptiste Daroussin 	case TYPE:
209298e903e7SBaptiste Daroussin 	    declare_types();
209398e903e7SBaptiste Daroussin 	    break;
209498e903e7SBaptiste Daroussin 
209598e903e7SBaptiste Daroussin 	case START:
209698e903e7SBaptiste Daroussin 	    declare_start();
209798e903e7SBaptiste Daroussin 	    break;
209898e903e7SBaptiste Daroussin 
209998e903e7SBaptiste Daroussin 	case PURE_PARSER:
210098e903e7SBaptiste Daroussin 	    pure_parser = 1;
210198e903e7SBaptiste Daroussin 	    break;
210298e903e7SBaptiste Daroussin 
210398e903e7SBaptiste Daroussin 	case PARSE_PARAM:
210498e903e7SBaptiste Daroussin 	case LEX_PARAM:
210598e903e7SBaptiste Daroussin 	    copy_param(k);
210698e903e7SBaptiste Daroussin 	    break;
210798e903e7SBaptiste Daroussin 
21084b4a8fcaSBaptiste Daroussin 	case TOKEN_TABLE:
21094b4a8fcaSBaptiste Daroussin 	    token_table = 1;
21104b4a8fcaSBaptiste Daroussin 	    break;
21114b4a8fcaSBaptiste Daroussin 
21122aca18c7SJung-uk Kim 	case ERROR_VERBOSE:
21132aca18c7SJung-uk Kim 	    error_verbose = 1;
21142aca18c7SJung-uk Kim 	    break;
21152aca18c7SJung-uk Kim 
21160c8de5b0SBaptiste Daroussin #if defined(YYBTYACC)
21170c8de5b0SBaptiste Daroussin 	case LOCATIONS:
21180c8de5b0SBaptiste Daroussin 	    locations = 1;
21190c8de5b0SBaptiste Daroussin 	    break;
21200c8de5b0SBaptiste Daroussin 
21210c8de5b0SBaptiste Daroussin 	case DESTRUCTOR:
21220c8de5b0SBaptiste Daroussin 	    destructor = 1;
21230c8de5b0SBaptiste Daroussin 	    copy_destructor();
21240c8de5b0SBaptiste Daroussin 	    break;
21252aca18c7SJung-uk Kim 	case INITIAL_ACTION:
21262aca18c7SJung-uk Kim 	    copy_initial_action();
21272aca18c7SJung-uk Kim 	    break;
21280c8de5b0SBaptiste Daroussin #endif
21290c8de5b0SBaptiste Daroussin 
21308e022d3cSDag-Erling Smørgrav 	case NONPOSIX_DEBUG:
21318e022d3cSDag-Erling Smørgrav 	    tflag = 1;
21322aca18c7SJung-uk Kim 	    break;
21332aca18c7SJung-uk Kim 
2134*822ca327SBaptiste Daroussin 	case HACK_DEFINE:
2135*822ca327SBaptiste Daroussin 	    hack_defines();
2136*822ca327SBaptiste Daroussin 	    break;
2137*822ca327SBaptiste Daroussin 
213898e903e7SBaptiste Daroussin 	case POSIX_YACC:
213998e903e7SBaptiste Daroussin 	    /* noop for bison compatibility. byacc is already designed to be posix
214098e903e7SBaptiste Daroussin 	     * yacc compatible. */
214198e903e7SBaptiste Daroussin 	    break;
214298e903e7SBaptiste Daroussin 	}
214398e903e7SBaptiste Daroussin     }
214498e903e7SBaptiste Daroussin }
214598e903e7SBaptiste Daroussin 
214698e903e7SBaptiste Daroussin static void
initialize_grammar(void)214798e903e7SBaptiste Daroussin initialize_grammar(void)
214898e903e7SBaptiste Daroussin {
214998e903e7SBaptiste Daroussin     nitems = 4;
215098e903e7SBaptiste Daroussin     maxitems = 300;
215198e903e7SBaptiste Daroussin 
21523e066022SBaptiste Daroussin     pitem = TMALLOC(bucket *, maxitems);
215398e903e7SBaptiste Daroussin     NO_SPACE(pitem);
215498e903e7SBaptiste Daroussin 
215598e903e7SBaptiste Daroussin     pitem[0] = 0;
215698e903e7SBaptiste Daroussin     pitem[1] = 0;
215798e903e7SBaptiste Daroussin     pitem[2] = 0;
215898e903e7SBaptiste Daroussin     pitem[3] = 0;
215998e903e7SBaptiste Daroussin 
216098e903e7SBaptiste Daroussin     nrules = 3;
216198e903e7SBaptiste Daroussin     maxrules = 100;
216298e903e7SBaptiste Daroussin 
21633e066022SBaptiste Daroussin     plhs = TMALLOC(bucket *, maxrules);
216498e903e7SBaptiste Daroussin     NO_SPACE(plhs);
216598e903e7SBaptiste Daroussin 
216698e903e7SBaptiste Daroussin     plhs[0] = 0;
216798e903e7SBaptiste Daroussin     plhs[1] = 0;
216898e903e7SBaptiste Daroussin     plhs[2] = 0;
216998e903e7SBaptiste Daroussin 
21703e066022SBaptiste Daroussin     rprec = TMALLOC(Value_t, maxrules);
217198e903e7SBaptiste Daroussin     NO_SPACE(rprec);
217298e903e7SBaptiste Daroussin 
217398e903e7SBaptiste Daroussin     rprec[0] = 0;
217498e903e7SBaptiste Daroussin     rprec[1] = 0;
217598e903e7SBaptiste Daroussin     rprec[2] = 0;
217698e903e7SBaptiste Daroussin 
21773e066022SBaptiste Daroussin     rassoc = TMALLOC(Assoc_t, maxrules);
217898e903e7SBaptiste Daroussin     NO_SPACE(rassoc);
217998e903e7SBaptiste Daroussin 
218098e903e7SBaptiste Daroussin     rassoc[0] = TOKEN;
218198e903e7SBaptiste Daroussin     rassoc[1] = TOKEN;
218298e903e7SBaptiste Daroussin     rassoc[2] = TOKEN;
218398e903e7SBaptiste Daroussin }
218498e903e7SBaptiste Daroussin 
218598e903e7SBaptiste Daroussin static void
expand_items(void)218698e903e7SBaptiste Daroussin expand_items(void)
218798e903e7SBaptiste Daroussin {
218898e903e7SBaptiste Daroussin     maxitems += 300;
21893e066022SBaptiste Daroussin     pitem = TREALLOC(bucket *, pitem, maxitems);
219098e903e7SBaptiste Daroussin     NO_SPACE(pitem);
219198e903e7SBaptiste Daroussin }
219298e903e7SBaptiste Daroussin 
219398e903e7SBaptiste Daroussin static void
expand_rules(void)219498e903e7SBaptiste Daroussin expand_rules(void)
219598e903e7SBaptiste Daroussin {
219698e903e7SBaptiste Daroussin     maxrules += 100;
219798e903e7SBaptiste Daroussin 
21983e066022SBaptiste Daroussin     plhs = TREALLOC(bucket *, plhs, maxrules);
219998e903e7SBaptiste Daroussin     NO_SPACE(plhs);
220098e903e7SBaptiste Daroussin 
22013e066022SBaptiste Daroussin     rprec = TREALLOC(Value_t, rprec, maxrules);
220298e903e7SBaptiste Daroussin     NO_SPACE(rprec);
220398e903e7SBaptiste Daroussin 
22043e066022SBaptiste Daroussin     rassoc = TREALLOC(Assoc_t, rassoc, maxrules);
220598e903e7SBaptiste Daroussin     NO_SPACE(rassoc);
220698e903e7SBaptiste Daroussin }
220798e903e7SBaptiste Daroussin 
22080c8de5b0SBaptiste Daroussin /* set immediately prior to where copy_args() could be called, and incremented by
22090c8de5b0SBaptiste Daroussin    the various routines that will rescan the argument list as appropriate */
22100c8de5b0SBaptiste Daroussin static int rescan_lineno;
22110c8de5b0SBaptiste Daroussin #if defined(YYBTYACC)
22120c8de5b0SBaptiste Daroussin 
22130c8de5b0SBaptiste Daroussin static char *
copy_args(int * alen)22140c8de5b0SBaptiste Daroussin copy_args(int *alen)
22150c8de5b0SBaptiste Daroussin {
22160c8de5b0SBaptiste Daroussin     struct mstring *s = msnew();
22170c8de5b0SBaptiste Daroussin     int depth = 0, len = 1;
22180c8de5b0SBaptiste Daroussin     char c, quote = 0;
22192aca18c7SJung-uk Kim     struct ainfo a;
22202aca18c7SJung-uk Kim 
2221*822ca327SBaptiste Daroussin     begin_ainfo(a, 1);
22220c8de5b0SBaptiste Daroussin 
22230c8de5b0SBaptiste Daroussin     while ((c = *cptr++) != R_PAREN || depth || quote)
22240c8de5b0SBaptiste Daroussin     {
22250c8de5b0SBaptiste Daroussin 	if (c == ',' && !quote && !depth)
22260c8de5b0SBaptiste Daroussin 	{
22270c8de5b0SBaptiste Daroussin 	    len++;
22280c8de5b0SBaptiste Daroussin 	    mputc(s, 0);
22290c8de5b0SBaptiste Daroussin 	    continue;
22300c8de5b0SBaptiste Daroussin 	}
22310c8de5b0SBaptiste Daroussin 	mputc(s, c);
22320c8de5b0SBaptiste Daroussin 	if (c == '\n')
22330c8de5b0SBaptiste Daroussin 	{
22340c8de5b0SBaptiste Daroussin 	    get_line();
22350c8de5b0SBaptiste Daroussin 	    if (!line)
22360c8de5b0SBaptiste Daroussin 	    {
22370c8de5b0SBaptiste Daroussin 		if (quote)
22382aca18c7SJung-uk Kim 		    unterminated_string(&a);
22390c8de5b0SBaptiste Daroussin 		else
22402aca18c7SJung-uk Kim 		    unterminated_arglist(&a);
22410c8de5b0SBaptiste Daroussin 	    }
22420c8de5b0SBaptiste Daroussin 	}
22430c8de5b0SBaptiste Daroussin 	else if (quote)
22440c8de5b0SBaptiste Daroussin 	{
22450c8de5b0SBaptiste Daroussin 	    if (c == quote)
22460c8de5b0SBaptiste Daroussin 		quote = 0;
22470c8de5b0SBaptiste Daroussin 	    else if (c == '\\')
22480c8de5b0SBaptiste Daroussin 	    {
22490c8de5b0SBaptiste Daroussin 		if (*cptr != '\n')
22500c8de5b0SBaptiste Daroussin 		    mputc(s, *cptr++);
22510c8de5b0SBaptiste Daroussin 	    }
22520c8de5b0SBaptiste Daroussin 	}
22530c8de5b0SBaptiste Daroussin 	else
22540c8de5b0SBaptiste Daroussin 	{
22550c8de5b0SBaptiste Daroussin 	    if (c == L_PAREN)
22560c8de5b0SBaptiste Daroussin 		depth++;
22570c8de5b0SBaptiste Daroussin 	    else if (c == R_PAREN)
22580c8de5b0SBaptiste Daroussin 		depth--;
22590c8de5b0SBaptiste Daroussin 	    else if (c == '\"' || c == '\'')
22600c8de5b0SBaptiste Daroussin 		quote = c;
22610c8de5b0SBaptiste Daroussin 	}
22620c8de5b0SBaptiste Daroussin     }
22630c8de5b0SBaptiste Daroussin     if (alen)
22640c8de5b0SBaptiste Daroussin 	*alen = len;
2265*822ca327SBaptiste Daroussin     end_ainfo(a);
22660c8de5b0SBaptiste Daroussin     return msdone(s);
22670c8de5b0SBaptiste Daroussin }
22680c8de5b0SBaptiste Daroussin 
22690c8de5b0SBaptiste Daroussin static char *
parse_id(char * p,char ** save)22700c8de5b0SBaptiste Daroussin parse_id(char *p, char **save)
22710c8de5b0SBaptiste Daroussin {
22720c8de5b0SBaptiste Daroussin     char *b;
22730c8de5b0SBaptiste Daroussin 
22742aca18c7SJung-uk Kim     while (isspace(UCH(*p)))
22750c8de5b0SBaptiste Daroussin 	if (*p++ == '\n')
22760c8de5b0SBaptiste Daroussin 	    rescan_lineno++;
22772aca18c7SJung-uk Kim     if (!isalpha(UCH(*p)) && *p != '_')
22780c8de5b0SBaptiste Daroussin 	return NULL;
22790c8de5b0SBaptiste Daroussin     b = p;
2280b53bb29fSJung-uk Kim     while (IS_NAME2(UCH(*p)))
22810c8de5b0SBaptiste Daroussin 	p++;
22820c8de5b0SBaptiste Daroussin     if (save)
22830c8de5b0SBaptiste Daroussin     {
22840c8de5b0SBaptiste Daroussin 	*save = cache_tag(b, (size_t)(p - b));
22850c8de5b0SBaptiste Daroussin     }
22860c8de5b0SBaptiste Daroussin     return p;
22870c8de5b0SBaptiste Daroussin }
22880c8de5b0SBaptiste Daroussin 
22890c8de5b0SBaptiste Daroussin static char *
parse_int(char * p,int * save)22900c8de5b0SBaptiste Daroussin parse_int(char *p, int *save)
22910c8de5b0SBaptiste Daroussin {
22920c8de5b0SBaptiste Daroussin     int neg = 0, val = 0;
22930c8de5b0SBaptiste Daroussin 
22942aca18c7SJung-uk Kim     while (isspace(UCH(*p)))
22950c8de5b0SBaptiste Daroussin 	if (*p++ == '\n')
22960c8de5b0SBaptiste Daroussin 	    rescan_lineno++;
22970c8de5b0SBaptiste Daroussin     if (*p == '-')
22980c8de5b0SBaptiste Daroussin     {
22990c8de5b0SBaptiste Daroussin 	neg = 1;
23000c8de5b0SBaptiste Daroussin 	p++;
23010c8de5b0SBaptiste Daroussin     }
23022aca18c7SJung-uk Kim     if (!isdigit(UCH(*p)))
23030c8de5b0SBaptiste Daroussin 	return NULL;
23042aca18c7SJung-uk Kim     while (isdigit(UCH(*p)))
23050c8de5b0SBaptiste Daroussin 	val = val * 10 + *p++ - '0';
23060c8de5b0SBaptiste Daroussin     if (neg)
23070c8de5b0SBaptiste Daroussin 	val = -val;
23080c8de5b0SBaptiste Daroussin     if (save)
23090c8de5b0SBaptiste Daroussin 	*save = val;
23100c8de5b0SBaptiste Daroussin     return p;
23110c8de5b0SBaptiste Daroussin }
23120c8de5b0SBaptiste Daroussin 
23130c8de5b0SBaptiste Daroussin static void
parse_arginfo(bucket * a,char * args,int argslen)23140c8de5b0SBaptiste Daroussin parse_arginfo(bucket *a, char *args, int argslen)
23150c8de5b0SBaptiste Daroussin {
23160c8de5b0SBaptiste Daroussin     char *p = args, *tmp;
23170c8de5b0SBaptiste Daroussin     int i, redec = 0;
23180c8de5b0SBaptiste Daroussin 
2319c5b5d71aSJung-uk Kim     if (a->args >= 0)
23200c8de5b0SBaptiste Daroussin     {
23210c8de5b0SBaptiste Daroussin 	if (a->args != argslen)
23220c8de5b0SBaptiste Daroussin 	    arg_number_disagree_warning(rescan_lineno, a->name);
23230c8de5b0SBaptiste Daroussin 	redec = 1;
23240c8de5b0SBaptiste Daroussin     }
23250c8de5b0SBaptiste Daroussin     else
23260c8de5b0SBaptiste Daroussin     {
23270c8de5b0SBaptiste Daroussin 	if ((a->args = argslen) == 0)
23280c8de5b0SBaptiste Daroussin 	    return;
23290c8de5b0SBaptiste Daroussin 	a->argnames = TMALLOC(char *, argslen);
23300c8de5b0SBaptiste Daroussin 	NO_SPACE(a->argnames);
23310c8de5b0SBaptiste Daroussin 	a->argtags = TMALLOC(char *, argslen);
23320c8de5b0SBaptiste Daroussin 	NO_SPACE(a->argtags);
23330c8de5b0SBaptiste Daroussin     }
23340c8de5b0SBaptiste Daroussin     if (!args)
23350c8de5b0SBaptiste Daroussin 	return;
23360c8de5b0SBaptiste Daroussin     for (i = 0; i < argslen; i++)
23370c8de5b0SBaptiste Daroussin     {
23382aca18c7SJung-uk Kim 	while (isspace(UCH(*p)))
23390c8de5b0SBaptiste Daroussin 	    if (*p++ == '\n')
23400c8de5b0SBaptiste Daroussin 		rescan_lineno++;
23410c8de5b0SBaptiste Daroussin 	if (*p++ != '$')
23420c8de5b0SBaptiste Daroussin 	    bad_formals();
23432aca18c7SJung-uk Kim 	while (isspace(UCH(*p)))
23440c8de5b0SBaptiste Daroussin 	    if (*p++ == '\n')
23450c8de5b0SBaptiste Daroussin 		rescan_lineno++;
23460c8de5b0SBaptiste Daroussin 	if (*p == '<')
23470c8de5b0SBaptiste Daroussin 	{
23480c8de5b0SBaptiste Daroussin 	    havetags = 1;
23490c8de5b0SBaptiste Daroussin 	    if (!(p = parse_id(p + 1, &tmp)))
23500c8de5b0SBaptiste Daroussin 		bad_formals();
23512aca18c7SJung-uk Kim 	    while (isspace(UCH(*p)))
23520c8de5b0SBaptiste Daroussin 		if (*p++ == '\n')
23530c8de5b0SBaptiste Daroussin 		    rescan_lineno++;
23540c8de5b0SBaptiste Daroussin 	    if (*p++ != '>')
23550c8de5b0SBaptiste Daroussin 		bad_formals();
23560c8de5b0SBaptiste Daroussin 	    if (redec)
23570c8de5b0SBaptiste Daroussin 	    {
23580c8de5b0SBaptiste Daroussin 		if (a->argtags[i] != tmp)
23590c8de5b0SBaptiste Daroussin 		    arg_type_disagree_warning(rescan_lineno, i + 1, a->name);
23600c8de5b0SBaptiste Daroussin 	    }
23610c8de5b0SBaptiste Daroussin 	    else
23620c8de5b0SBaptiste Daroussin 		a->argtags[i] = tmp;
23630c8de5b0SBaptiste Daroussin 	}
23640c8de5b0SBaptiste Daroussin 	else if (!redec)
23650c8de5b0SBaptiste Daroussin 	    a->argtags[i] = NULL;
23660c8de5b0SBaptiste Daroussin 	if (!(p = parse_id(p, &a->argnames[i])))
23670c8de5b0SBaptiste Daroussin 	    bad_formals();
23682aca18c7SJung-uk Kim 	while (isspace(UCH(*p)))
23690c8de5b0SBaptiste Daroussin 	    if (*p++ == '\n')
23700c8de5b0SBaptiste Daroussin 		rescan_lineno++;
23710c8de5b0SBaptiste Daroussin 	if (*p++)
23720c8de5b0SBaptiste Daroussin 	    bad_formals();
23730c8de5b0SBaptiste Daroussin     }
23740c8de5b0SBaptiste Daroussin     free(args);
23750c8de5b0SBaptiste Daroussin }
23760c8de5b0SBaptiste Daroussin 
23770c8de5b0SBaptiste Daroussin static char *
compile_arg(char ** theptr,char * yyvaltag)23780c8de5b0SBaptiste Daroussin compile_arg(char **theptr, char *yyvaltag)
23790c8de5b0SBaptiste Daroussin {
23800c8de5b0SBaptiste Daroussin     char *p = *theptr;
23810c8de5b0SBaptiste Daroussin     struct mstring *c = msnew();
23828e022d3cSDag-Erling Smørgrav     int i, n;
23830c8de5b0SBaptiste Daroussin     Value_t *offsets = NULL, maxoffset;
23840c8de5b0SBaptiste Daroussin     bucket **rhs;
23850c8de5b0SBaptiste Daroussin 
23860c8de5b0SBaptiste Daroussin     maxoffset = 0;
23870c8de5b0SBaptiste Daroussin     n = 0;
23880c8de5b0SBaptiste Daroussin     for (i = nitems - 1; pitem[i]; --i)
23890c8de5b0SBaptiste Daroussin     {
23900c8de5b0SBaptiste Daroussin 	n++;
23910c8de5b0SBaptiste Daroussin 	if (pitem[i]->class != ARGUMENT)
23920c8de5b0SBaptiste Daroussin 	    maxoffset++;
23930c8de5b0SBaptiste Daroussin     }
23940c8de5b0SBaptiste Daroussin     if (maxoffset > 0)
23950c8de5b0SBaptiste Daroussin     {
23968e022d3cSDag-Erling Smørgrav 	int j;
23978e022d3cSDag-Erling Smørgrav 
23988e022d3cSDag-Erling Smørgrav 	offsets = TCMALLOC(Value_t, maxoffset + 1);
23990c8de5b0SBaptiste Daroussin 	NO_SPACE(offsets);
240011fce282SBaptiste Daroussin 
24010c8de5b0SBaptiste Daroussin 	for (j = 0, i++; i < nitems; i++)
24020c8de5b0SBaptiste Daroussin 	    if (pitem[i]->class != ARGUMENT)
24030c8de5b0SBaptiste Daroussin 		offsets[++j] = (Value_t)(i - nitems + 1);
240411fce282SBaptiste Daroussin     }
24050c8de5b0SBaptiste Daroussin     rhs = pitem + nitems - 1;
24060c8de5b0SBaptiste Daroussin 
24070c8de5b0SBaptiste Daroussin     if (yyvaltag)
24080c8de5b0SBaptiste Daroussin 	msprintf(c, "yyval.%s = ", yyvaltag);
24090c8de5b0SBaptiste Daroussin     else
24100c8de5b0SBaptiste Daroussin 	msprintf(c, "yyval = ");
24110c8de5b0SBaptiste Daroussin     while (*p)
24120c8de5b0SBaptiste Daroussin     {
24130c8de5b0SBaptiste Daroussin 	if (*p == '$')
24140c8de5b0SBaptiste Daroussin 	{
24150c8de5b0SBaptiste Daroussin 	    char *tag = NULL;
24160c8de5b0SBaptiste Daroussin 	    if (*++p == '<')
24170c8de5b0SBaptiste Daroussin 		if (!(p = parse_id(++p, &tag)) || *p++ != '>')
24180c8de5b0SBaptiste Daroussin 		    illegal_tag(rescan_lineno, NULL, NULL);
24192aca18c7SJung-uk Kim 	    if (isdigit(UCH(*p)) || *p == '-')
24200c8de5b0SBaptiste Daroussin 	    {
24210c8de5b0SBaptiste Daroussin 		int val;
24220c8de5b0SBaptiste Daroussin 		if (!(p = parse_int(p, &val)))
24230c8de5b0SBaptiste Daroussin 		    dollar_error(rescan_lineno, NULL, NULL);
24240c8de5b0SBaptiste Daroussin 		if (val <= 0)
24250c8de5b0SBaptiste Daroussin 		    i = val - n;
24260c8de5b0SBaptiste Daroussin 		else if (val > maxoffset)
24270c8de5b0SBaptiste Daroussin 		{
24280c8de5b0SBaptiste Daroussin 		    dollar_warning(rescan_lineno, val);
24290c8de5b0SBaptiste Daroussin 		    i = val - maxoffset;
24300c8de5b0SBaptiste Daroussin 		}
243111fce282SBaptiste Daroussin 		else if (maxoffset > 0)
24320c8de5b0SBaptiste Daroussin 		{
24330c8de5b0SBaptiste Daroussin 		    i = offsets[val];
24340c8de5b0SBaptiste Daroussin 		    if (!tag && !(tag = rhs[i]->tag) && havetags)
24350c8de5b0SBaptiste Daroussin 			untyped_rhs(val, rhs[i]->name);
24360c8de5b0SBaptiste Daroussin 		}
24370c8de5b0SBaptiste Daroussin 		msprintf(c, "yystack.l_mark[%d]", i);
24380c8de5b0SBaptiste Daroussin 		if (tag)
24390c8de5b0SBaptiste Daroussin 		    msprintf(c, ".%s", tag);
24400c8de5b0SBaptiste Daroussin 		else if (havetags)
24410c8de5b0SBaptiste Daroussin 		    unknown_rhs(val);
24420c8de5b0SBaptiste Daroussin 	    }
24432aca18c7SJung-uk Kim 	    else if (isalpha(UCH(*p)) || *p == '_')
24440c8de5b0SBaptiste Daroussin 	    {
24450c8de5b0SBaptiste Daroussin 		char *arg;
24460c8de5b0SBaptiste Daroussin 		if (!(p = parse_id(p, &arg)))
24470c8de5b0SBaptiste Daroussin 		    dollar_error(rescan_lineno, NULL, NULL);
24480c8de5b0SBaptiste Daroussin 		for (i = plhs[nrules]->args - 1; i >= 0; i--)
24490c8de5b0SBaptiste Daroussin 		    if (arg == plhs[nrules]->argnames[i])
24500c8de5b0SBaptiste Daroussin 			break;
24510c8de5b0SBaptiste Daroussin 		if (i < 0)
24520c8de5b0SBaptiste Daroussin 		    unknown_arg_warning(rescan_lineno, "$", arg, NULL, NULL);
24530c8de5b0SBaptiste Daroussin 		else if (!tag)
24540c8de5b0SBaptiste Daroussin 		    tag = plhs[nrules]->argtags[i];
2455c5b5d71aSJung-uk Kim 		msprintf(c, "yystack.l_mark[%d]",
2456c5b5d71aSJung-uk Kim 			 i - plhs[nrules]->args + 1 - n);
24570c8de5b0SBaptiste Daroussin 		if (tag)
24580c8de5b0SBaptiste Daroussin 		    msprintf(c, ".%s", tag);
24590c8de5b0SBaptiste Daroussin 		else if (havetags)
24600c8de5b0SBaptiste Daroussin 		    untyped_arg_warning(rescan_lineno, "$", arg);
24610c8de5b0SBaptiste Daroussin 	    }
24620c8de5b0SBaptiste Daroussin 	    else
24630c8de5b0SBaptiste Daroussin 		dollar_error(rescan_lineno, NULL, NULL);
24640c8de5b0SBaptiste Daroussin 	}
24650c8de5b0SBaptiste Daroussin 	else if (*p == '@')
24660c8de5b0SBaptiste Daroussin 	{
24670c8de5b0SBaptiste Daroussin 	    at_error(rescan_lineno, NULL, NULL);
24680c8de5b0SBaptiste Daroussin 	}
24690c8de5b0SBaptiste Daroussin 	else
24700c8de5b0SBaptiste Daroussin 	{
24710c8de5b0SBaptiste Daroussin 	    if (*p == '\n')
24720c8de5b0SBaptiste Daroussin 		rescan_lineno++;
24730c8de5b0SBaptiste Daroussin 	    mputc(c, *p++);
24740c8de5b0SBaptiste Daroussin 	}
24750c8de5b0SBaptiste Daroussin     }
24760c8de5b0SBaptiste Daroussin     *theptr = p;
24770c8de5b0SBaptiste Daroussin     if (maxoffset > 0)
24780c8de5b0SBaptiste Daroussin 	FREE(offsets);
24790c8de5b0SBaptiste Daroussin     return msdone(c);
24800c8de5b0SBaptiste Daroussin }
24810c8de5b0SBaptiste Daroussin 
2482c5b5d71aSJung-uk Kim static int
can_elide_arg(char ** theptr,char * yyvaltag)2483c5b5d71aSJung-uk Kim can_elide_arg(char **theptr, char *yyvaltag)
2484c5b5d71aSJung-uk Kim {
2485c5b5d71aSJung-uk Kim     char *p = *theptr;
2486c5b5d71aSJung-uk Kim     int rv = 0;
24878e022d3cSDag-Erling Smørgrav     int i, n = 0;
2488c5b5d71aSJung-uk Kim     Value_t *offsets = NULL, maxoffset = 0;
2489c5b5d71aSJung-uk Kim     bucket **rhs;
2490c5b5d71aSJung-uk Kim     char *tag = 0;
2491c5b5d71aSJung-uk Kim 
2492c5b5d71aSJung-uk Kim     if (*p++ != '$')
2493c5b5d71aSJung-uk Kim 	return 0;
2494c5b5d71aSJung-uk Kim     if (*p == '<')
2495c5b5d71aSJung-uk Kim     {
2496c5b5d71aSJung-uk Kim 	if (!(p = parse_id(++p, &tag)) || *p++ != '>')
2497c5b5d71aSJung-uk Kim 	    return 0;
2498c5b5d71aSJung-uk Kim     }
2499c5b5d71aSJung-uk Kim     for (i = nitems - 1; pitem[i]; --i)
2500c5b5d71aSJung-uk Kim     {
2501c5b5d71aSJung-uk Kim 	n++;
2502c5b5d71aSJung-uk Kim 	if (pitem[i]->class != ARGUMENT)
2503c5b5d71aSJung-uk Kim 	    maxoffset++;
2504c5b5d71aSJung-uk Kim     }
2505c5b5d71aSJung-uk Kim     if (maxoffset > 0)
2506c5b5d71aSJung-uk Kim     {
25078e022d3cSDag-Erling Smørgrav 	int j;
25088e022d3cSDag-Erling Smørgrav 
25098e022d3cSDag-Erling Smørgrav 	offsets = TCMALLOC(Value_t, maxoffset + 1);
2510c5b5d71aSJung-uk Kim 	NO_SPACE(offsets);
2511c5b5d71aSJung-uk Kim 
2512c5b5d71aSJung-uk Kim 	for (j = 0, i++; i < nitems; i++)
2513c5b5d71aSJung-uk Kim 	    if (pitem[i]->class != ARGUMENT)
2514c5b5d71aSJung-uk Kim 		offsets[++j] = (Value_t)(i - nitems + 1);
2515c5b5d71aSJung-uk Kim     }
2516c5b5d71aSJung-uk Kim     rhs = pitem + nitems - 1;
2517c5b5d71aSJung-uk Kim 
25182aca18c7SJung-uk Kim     if (isdigit(UCH(*p)) || *p == '-')
2519c5b5d71aSJung-uk Kim     {
2520c5b5d71aSJung-uk Kim 	int val;
2521c5b5d71aSJung-uk Kim 	if (!(p = parse_int(p, &val)))
2522c5b5d71aSJung-uk Kim 	    rv = 0;
2523c5b5d71aSJung-uk Kim 	else
2524c5b5d71aSJung-uk Kim 	{
2525c5b5d71aSJung-uk Kim 	    if (val <= 0)
2526c5b5d71aSJung-uk Kim 		rv = 1 - val + n;
2527c5b5d71aSJung-uk Kim 	    else if (val > maxoffset)
2528c5b5d71aSJung-uk Kim 		rv = 0;
2529c5b5d71aSJung-uk Kim 	    else
2530c5b5d71aSJung-uk Kim 	    {
2531c5b5d71aSJung-uk Kim 		i = offsets[val];
2532c5b5d71aSJung-uk Kim 		rv = 1 - i;
2533c5b5d71aSJung-uk Kim 		if (!tag)
2534c5b5d71aSJung-uk Kim 		    tag = rhs[i]->tag;
2535c5b5d71aSJung-uk Kim 	    }
2536c5b5d71aSJung-uk Kim 	}
2537c5b5d71aSJung-uk Kim     }
25382aca18c7SJung-uk Kim     else if (isalpha(UCH(*p)) || *p == '_')
2539c5b5d71aSJung-uk Kim     {
2540c5b5d71aSJung-uk Kim 	char *arg;
2541c5b5d71aSJung-uk Kim 	if (!(p = parse_id(p, &arg)))
2542b53bb29fSJung-uk Kim 	{
2543b53bb29fSJung-uk Kim 	    FREE(offsets);
2544c5b5d71aSJung-uk Kim 	    return 0;
2545b53bb29fSJung-uk Kim 	}
2546c5b5d71aSJung-uk Kim 	for (i = plhs[nrules]->args - 1; i >= 0; i--)
2547c5b5d71aSJung-uk Kim 	    if (arg == plhs[nrules]->argnames[i])
2548c5b5d71aSJung-uk Kim 		break;
2549c5b5d71aSJung-uk Kim 	if (i >= 0)
2550c5b5d71aSJung-uk Kim 	{
2551c5b5d71aSJung-uk Kim 	    if (!tag)
2552c5b5d71aSJung-uk Kim 		tag = plhs[nrules]->argtags[i];
2553c5b5d71aSJung-uk Kim 	    rv = plhs[nrules]->args + n - i;
2554c5b5d71aSJung-uk Kim 	}
2555c5b5d71aSJung-uk Kim     }
2556c5b5d71aSJung-uk Kim     if (tag && yyvaltag)
2557c5b5d71aSJung-uk Kim     {
2558c5b5d71aSJung-uk Kim 	if (strcmp(tag, yyvaltag))
2559c5b5d71aSJung-uk Kim 	    rv = 0;
2560c5b5d71aSJung-uk Kim     }
2561c5b5d71aSJung-uk Kim     else if (tag || yyvaltag)
2562c5b5d71aSJung-uk Kim 	rv = 0;
2563c5b5d71aSJung-uk Kim     if (maxoffset > 0)
2564c5b5d71aSJung-uk Kim 	FREE(offsets);
2565b53bb29fSJung-uk Kim     if (p == 0 || *p || rv <= 0)
2566c5b5d71aSJung-uk Kim 	return 0;
2567c5b5d71aSJung-uk Kim     *theptr = p + 1;
2568c5b5d71aSJung-uk Kim     return rv;
2569c5b5d71aSJung-uk Kim }
2570c5b5d71aSJung-uk Kim 
25710c8de5b0SBaptiste Daroussin #define ARG_CACHE_SIZE	1024
25720c8de5b0SBaptiste Daroussin static struct arg_cache
25730c8de5b0SBaptiste Daroussin {
25740c8de5b0SBaptiste Daroussin     struct arg_cache *next;
25750c8de5b0SBaptiste Daroussin     char *code;
25760c8de5b0SBaptiste Daroussin     int rule;
25770c8de5b0SBaptiste Daroussin }
25780c8de5b0SBaptiste Daroussin  *arg_cache[ARG_CACHE_SIZE];
25790c8de5b0SBaptiste Daroussin 
25800c8de5b0SBaptiste Daroussin static int
lookup_arg_cache(char * code)25810c8de5b0SBaptiste Daroussin lookup_arg_cache(char *code)
25820c8de5b0SBaptiste Daroussin {
25830c8de5b0SBaptiste Daroussin     struct arg_cache *entry;
25840c8de5b0SBaptiste Daroussin 
25850c8de5b0SBaptiste Daroussin     entry = arg_cache[strnshash(code) % ARG_CACHE_SIZE];
25860c8de5b0SBaptiste Daroussin     while (entry)
25870c8de5b0SBaptiste Daroussin     {
25880c8de5b0SBaptiste Daroussin 	if (!strnscmp(entry->code, code))
25890c8de5b0SBaptiste Daroussin 	    return entry->rule;
25900c8de5b0SBaptiste Daroussin 	entry = entry->next;
25910c8de5b0SBaptiste Daroussin     }
25920c8de5b0SBaptiste Daroussin     return -1;
25930c8de5b0SBaptiste Daroussin }
25940c8de5b0SBaptiste Daroussin 
25950c8de5b0SBaptiste Daroussin static void
insert_arg_cache(char * code,int rule)25960c8de5b0SBaptiste Daroussin insert_arg_cache(char *code, int rule)
25970c8de5b0SBaptiste Daroussin {
25980c8de5b0SBaptiste Daroussin     struct arg_cache *entry = NEW(struct arg_cache);
25990c8de5b0SBaptiste Daroussin     int i;
26000c8de5b0SBaptiste Daroussin 
26010c8de5b0SBaptiste Daroussin     NO_SPACE(entry);
26020c8de5b0SBaptiste Daroussin     i = strnshash(code) % ARG_CACHE_SIZE;
26030c8de5b0SBaptiste Daroussin     entry->code = code;
26040c8de5b0SBaptiste Daroussin     entry->rule = rule;
26050c8de5b0SBaptiste Daroussin     entry->next = arg_cache[i];
26060c8de5b0SBaptiste Daroussin     arg_cache[i] = entry;
26070c8de5b0SBaptiste Daroussin }
26080c8de5b0SBaptiste Daroussin 
26090c8de5b0SBaptiste Daroussin static void
clean_arg_cache(void)26100c8de5b0SBaptiste Daroussin clean_arg_cache(void)
26110c8de5b0SBaptiste Daroussin {
26120c8de5b0SBaptiste Daroussin     struct arg_cache *e, *t;
26130c8de5b0SBaptiste Daroussin     int i;
26140c8de5b0SBaptiste Daroussin 
26150c8de5b0SBaptiste Daroussin     for (i = 0; i < ARG_CACHE_SIZE; i++)
26160c8de5b0SBaptiste Daroussin     {
26170c8de5b0SBaptiste Daroussin 	for (e = arg_cache[i]; (t = e); e = e->next, FREE(t))
26180c8de5b0SBaptiste Daroussin 	    free(e->code);
26190c8de5b0SBaptiste Daroussin 	arg_cache[i] = NULL;
26200c8de5b0SBaptiste Daroussin     }
26210c8de5b0SBaptiste Daroussin }
2622c5b5d71aSJung-uk Kim #endif /* defined(YYBTYACC) */
26230c8de5b0SBaptiste Daroussin 
262498e903e7SBaptiste Daroussin static void
advance_to_start(void)262598e903e7SBaptiste Daroussin advance_to_start(void)
262698e903e7SBaptiste Daroussin {
262798e903e7SBaptiste Daroussin     int c;
262898e903e7SBaptiste Daroussin     bucket *bp;
262998e903e7SBaptiste Daroussin     int s_lineno;
26300c8de5b0SBaptiste Daroussin #if defined(YYBTYACC)
26310c8de5b0SBaptiste Daroussin     char *args = NULL;
26320c8de5b0SBaptiste Daroussin     int argslen = 0;
26330c8de5b0SBaptiste Daroussin #endif
263498e903e7SBaptiste Daroussin 
263598e903e7SBaptiste Daroussin     for (;;)
263698e903e7SBaptiste Daroussin     {
26378e022d3cSDag-Erling Smørgrav 	char *s_cptr;
26388e022d3cSDag-Erling Smørgrav 
263998e903e7SBaptiste Daroussin 	c = nextc();
264098e903e7SBaptiste Daroussin 	if (c != '%')
264198e903e7SBaptiste Daroussin 	    break;
264298e903e7SBaptiste Daroussin 	s_cptr = cptr;
264398e903e7SBaptiste Daroussin 	switch (keyword())
264498e903e7SBaptiste Daroussin 	{
2645b53bb29fSJung-uk Kim 	case XCODE:
2646b53bb29fSJung-uk Kim 	    copy_code();
2647b53bb29fSJung-uk Kim 	    break;
2648b53bb29fSJung-uk Kim 
264998e903e7SBaptiste Daroussin 	case MARK:
265098e903e7SBaptiste Daroussin 	    no_grammar();
265198e903e7SBaptiste Daroussin 
265298e903e7SBaptiste Daroussin 	case TEXT:
265398e903e7SBaptiste Daroussin 	    copy_text();
265498e903e7SBaptiste Daroussin 	    break;
265598e903e7SBaptiste Daroussin 
265698e903e7SBaptiste Daroussin 	case START:
265798e903e7SBaptiste Daroussin 	    declare_start();
265898e903e7SBaptiste Daroussin 	    break;
265998e903e7SBaptiste Daroussin 
266098e903e7SBaptiste Daroussin 	default:
266198e903e7SBaptiste Daroussin 	    syntax_error(lineno, line, s_cptr);
266298e903e7SBaptiste Daroussin 	}
266398e903e7SBaptiste Daroussin     }
266498e903e7SBaptiste Daroussin 
266598e903e7SBaptiste Daroussin     c = nextc();
2666b53bb29fSJung-uk Kim     if (!isalpha(UCH(c)) && c != '_' && c != '.' && c != '_')
266798e903e7SBaptiste Daroussin 	syntax_error(lineno, line, cptr);
266898e903e7SBaptiste Daroussin     bp = get_name();
266998e903e7SBaptiste Daroussin     if (goal == 0)
267098e903e7SBaptiste Daroussin     {
267198e903e7SBaptiste Daroussin 	if (bp->class == TERM)
267298e903e7SBaptiste Daroussin 	    terminal_start(bp->name);
267398e903e7SBaptiste Daroussin 	goal = bp;
267498e903e7SBaptiste Daroussin     }
267598e903e7SBaptiste Daroussin 
267698e903e7SBaptiste Daroussin     s_lineno = lineno;
267798e903e7SBaptiste Daroussin     c = nextc();
267898e903e7SBaptiste Daroussin     if (c == EOF)
267998e903e7SBaptiste Daroussin 	unexpected_EOF();
26800c8de5b0SBaptiste Daroussin     rescan_lineno = lineno;	/* line# for possible inherited args rescan */
26810c8de5b0SBaptiste Daroussin #if defined(YYBTYACC)
26820c8de5b0SBaptiste Daroussin     if (c == L_PAREN)
26830c8de5b0SBaptiste Daroussin     {
26840c8de5b0SBaptiste Daroussin 	++cptr;
26850c8de5b0SBaptiste Daroussin 	args = copy_args(&argslen);
26860c8de5b0SBaptiste Daroussin 	NO_SPACE(args);
26870c8de5b0SBaptiste Daroussin 	c = nextc();
26880c8de5b0SBaptiste Daroussin     }
26890c8de5b0SBaptiste Daroussin #endif
269098e903e7SBaptiste Daroussin     if (c != ':')
269198e903e7SBaptiste Daroussin 	syntax_error(lineno, line, cptr);
269298e903e7SBaptiste Daroussin     start_rule(bp, s_lineno);
26930c8de5b0SBaptiste Daroussin #if defined(YYBTYACC)
26940c8de5b0SBaptiste Daroussin     parse_arginfo(bp, args, argslen);
26950c8de5b0SBaptiste Daroussin #endif
269698e903e7SBaptiste Daroussin     ++cptr;
269798e903e7SBaptiste Daroussin }
269898e903e7SBaptiste Daroussin 
269998e903e7SBaptiste Daroussin static void
start_rule(bucket * bp,int s_lineno)270098e903e7SBaptiste Daroussin start_rule(bucket *bp, int s_lineno)
270198e903e7SBaptiste Daroussin {
270298e903e7SBaptiste Daroussin     if (bp->class == TERM)
270398e903e7SBaptiste Daroussin 	terminal_lhs(s_lineno);
270498e903e7SBaptiste Daroussin     bp->class = NONTERM;
27050c8de5b0SBaptiste Daroussin     if (!bp->index)
27060c8de5b0SBaptiste Daroussin 	bp->index = nrules;
270798e903e7SBaptiste Daroussin     if (nrules >= maxrules)
270898e903e7SBaptiste Daroussin 	expand_rules();
270998e903e7SBaptiste Daroussin     plhs[nrules] = bp;
271098e903e7SBaptiste Daroussin     rprec[nrules] = UNDEFINED;
271198e903e7SBaptiste Daroussin     rassoc[nrules] = TOKEN;
271298e903e7SBaptiste Daroussin }
271398e903e7SBaptiste Daroussin 
271498e903e7SBaptiste Daroussin static void
end_rule(void)271598e903e7SBaptiste Daroussin end_rule(void)
271698e903e7SBaptiste Daroussin {
271798e903e7SBaptiste Daroussin     if (!last_was_action && plhs[nrules]->tag)
271898e903e7SBaptiste Daroussin     {
271998e903e7SBaptiste Daroussin 	if (pitem[nitems - 1])
272098e903e7SBaptiste Daroussin 	{
27218e022d3cSDag-Erling Smørgrav 	    int i;
27228e022d3cSDag-Erling Smørgrav 
272398e903e7SBaptiste Daroussin 	    for (i = nitems - 1; (i > 0) && pitem[i]; --i)
272498e903e7SBaptiste Daroussin 		continue;
272598e903e7SBaptiste Daroussin 	    if (pitem[i + 1] == 0 || pitem[i + 1]->tag != plhs[nrules]->tag)
2726c5b5d71aSJung-uk Kim 		default_action_warning(plhs[nrules]->name);
272798e903e7SBaptiste Daroussin 	}
272898e903e7SBaptiste Daroussin 	else
2729c5b5d71aSJung-uk Kim 	    default_action_warning(plhs[nrules]->name);
273098e903e7SBaptiste Daroussin     }
273198e903e7SBaptiste Daroussin 
273298e903e7SBaptiste Daroussin     last_was_action = 0;
273398e903e7SBaptiste Daroussin     if (nitems >= maxitems)
273498e903e7SBaptiste Daroussin 	expand_items();
273598e903e7SBaptiste Daroussin     pitem[nitems] = 0;
273698e903e7SBaptiste Daroussin     ++nitems;
273798e903e7SBaptiste Daroussin     ++nrules;
273898e903e7SBaptiste Daroussin }
273998e903e7SBaptiste Daroussin 
274098e903e7SBaptiste Daroussin static void
insert_empty_rule(void)274198e903e7SBaptiste Daroussin insert_empty_rule(void)
274298e903e7SBaptiste Daroussin {
274398e903e7SBaptiste Daroussin     bucket *bp, **bpp;
274498e903e7SBaptiste Daroussin 
274598e903e7SBaptiste Daroussin     assert(cache);
27460f86d14eSJung-uk Kim     assert(cache_size >= CACHE_SIZE);
274798e903e7SBaptiste Daroussin     sprintf(cache, "$$%d", ++gensym);
274898e903e7SBaptiste Daroussin     bp = make_bucket(cache);
274998e903e7SBaptiste Daroussin     last_symbol->next = bp;
275098e903e7SBaptiste Daroussin     last_symbol = bp;
275198e903e7SBaptiste Daroussin     bp->tag = plhs[nrules]->tag;
27520c8de5b0SBaptiste Daroussin     bp->class = ACTION;
27530c8de5b0SBaptiste Daroussin #if defined(YYBTYACC)
27540c8de5b0SBaptiste Daroussin     bp->args = 0;
27550c8de5b0SBaptiste Daroussin #endif
275698e903e7SBaptiste Daroussin 
27570c8de5b0SBaptiste Daroussin     nitems = (Value_t)(nitems + 2);
27580c8de5b0SBaptiste Daroussin     if (nitems > maxitems)
275998e903e7SBaptiste Daroussin 	expand_items();
276098e903e7SBaptiste Daroussin     bpp = pitem + nitems - 1;
276198e903e7SBaptiste Daroussin     *bpp-- = bp;
276298e903e7SBaptiste Daroussin     while ((bpp[0] = bpp[-1]) != 0)
276398e903e7SBaptiste Daroussin 	--bpp;
276498e903e7SBaptiste Daroussin 
276598e903e7SBaptiste Daroussin     if (++nrules >= maxrules)
276698e903e7SBaptiste Daroussin 	expand_rules();
276798e903e7SBaptiste Daroussin     plhs[nrules] = plhs[nrules - 1];
276898e903e7SBaptiste Daroussin     plhs[nrules - 1] = bp;
276998e903e7SBaptiste Daroussin     rprec[nrules] = rprec[nrules - 1];
277098e903e7SBaptiste Daroussin     rprec[nrules - 1] = 0;
277198e903e7SBaptiste Daroussin     rassoc[nrules] = rassoc[nrules - 1];
277298e903e7SBaptiste Daroussin     rassoc[nrules - 1] = TOKEN;
277398e903e7SBaptiste Daroussin }
277498e903e7SBaptiste Daroussin 
27750c8de5b0SBaptiste Daroussin #if defined(YYBTYACC)
27760c8de5b0SBaptiste Daroussin static char *
insert_arg_rule(char * arg,char * tag)27770c8de5b0SBaptiste Daroussin insert_arg_rule(char *arg, char *tag)
27780c8de5b0SBaptiste Daroussin {
27790c8de5b0SBaptiste Daroussin     int line_number = rescan_lineno;
27800c8de5b0SBaptiste Daroussin     char *code = compile_arg(&arg, tag);
27810c8de5b0SBaptiste Daroussin     int rule = lookup_arg_cache(code);
27820c8de5b0SBaptiste Daroussin     FILE *f = action_file;
27830c8de5b0SBaptiste Daroussin 
27840c8de5b0SBaptiste Daroussin     if (rule < 0)
27850c8de5b0SBaptiste Daroussin     {
27860c8de5b0SBaptiste Daroussin 	rule = nrules;
27870c8de5b0SBaptiste Daroussin 	insert_arg_cache(code, rule);
2788c5b5d71aSJung-uk Kim 	trialaction = 1;	/* arg rules always run in trial mode */
27898e022d3cSDag-Erling Smørgrav 	begin_case(f, rule - 2);
27908e022d3cSDag-Erling Smørgrav 	fprintf_lineno(f, line_number, input_file_name);
27918e022d3cSDag-Erling Smørgrav 	fprintf(f, "%s;", code);
27928e022d3cSDag-Erling Smørgrav 	end_case(f);
27930c8de5b0SBaptiste Daroussin 	insert_empty_rule();
2794c5b5d71aSJung-uk Kim 	plhs[rule]->tag = cache_tag(tag, strlen(tag));
27950c8de5b0SBaptiste Daroussin 	plhs[rule]->class = ARGUMENT;
27960c8de5b0SBaptiste Daroussin     }
27970c8de5b0SBaptiste Daroussin     else
27980c8de5b0SBaptiste Daroussin     {
27990c8de5b0SBaptiste Daroussin 	if (++nitems > maxitems)
28000c8de5b0SBaptiste Daroussin 	    expand_items();
28010c8de5b0SBaptiste Daroussin 	pitem[nitems - 1] = plhs[rule];
28020c8de5b0SBaptiste Daroussin 	free(code);
28030c8de5b0SBaptiste Daroussin     }
28040c8de5b0SBaptiste Daroussin     return arg + 1;
28050c8de5b0SBaptiste Daroussin }
28060c8de5b0SBaptiste Daroussin #endif
28070c8de5b0SBaptiste Daroussin 
280898e903e7SBaptiste Daroussin static void
add_symbol(void)280998e903e7SBaptiste Daroussin add_symbol(void)
281098e903e7SBaptiste Daroussin {
281198e903e7SBaptiste Daroussin     int c;
281298e903e7SBaptiste Daroussin     bucket *bp;
281398e903e7SBaptiste Daroussin     int s_lineno = lineno;
28140c8de5b0SBaptiste Daroussin #if defined(YYBTYACC)
28150c8de5b0SBaptiste Daroussin     char *args = NULL;
28160c8de5b0SBaptiste Daroussin     int argslen = 0;
28170c8de5b0SBaptiste Daroussin #endif
281898e903e7SBaptiste Daroussin 
281998e903e7SBaptiste Daroussin     c = *cptr;
282098e903e7SBaptiste Daroussin     if (c == '\'' || c == '"')
282198e903e7SBaptiste Daroussin 	bp = get_literal();
282298e903e7SBaptiste Daroussin     else
282398e903e7SBaptiste Daroussin 	bp = get_name();
282498e903e7SBaptiste Daroussin 
282598e903e7SBaptiste Daroussin     c = nextc();
28260c8de5b0SBaptiste Daroussin     rescan_lineno = lineno;	/* line# for possible inherited args rescan */
28270c8de5b0SBaptiste Daroussin #if defined(YYBTYACC)
28280c8de5b0SBaptiste Daroussin     if (c == L_PAREN)
28290c8de5b0SBaptiste Daroussin     {
28300c8de5b0SBaptiste Daroussin 	++cptr;
28310c8de5b0SBaptiste Daroussin 	args = copy_args(&argslen);
28320c8de5b0SBaptiste Daroussin 	NO_SPACE(args);
28330c8de5b0SBaptiste Daroussin 	c = nextc();
28340c8de5b0SBaptiste Daroussin     }
28350c8de5b0SBaptiste Daroussin #endif
283698e903e7SBaptiste Daroussin     if (c == ':')
283798e903e7SBaptiste Daroussin     {
283898e903e7SBaptiste Daroussin 	end_rule();
283998e903e7SBaptiste Daroussin 	start_rule(bp, s_lineno);
28400c8de5b0SBaptiste Daroussin #if defined(YYBTYACC)
28410c8de5b0SBaptiste Daroussin 	parse_arginfo(bp, args, argslen);
28420c8de5b0SBaptiste Daroussin #endif
284398e903e7SBaptiste Daroussin 	++cptr;
284498e903e7SBaptiste Daroussin 	return;
284598e903e7SBaptiste Daroussin     }
284698e903e7SBaptiste Daroussin 
284798e903e7SBaptiste Daroussin     if (last_was_action)
284898e903e7SBaptiste Daroussin 	insert_empty_rule();
284998e903e7SBaptiste Daroussin     last_was_action = 0;
285098e903e7SBaptiste Daroussin 
28510c8de5b0SBaptiste Daroussin #if defined(YYBTYACC)
28520c8de5b0SBaptiste Daroussin     if (bp->args < 0)
28530c8de5b0SBaptiste Daroussin 	bp->args = argslen;
28540c8de5b0SBaptiste Daroussin     if (argslen == 0 && bp->args > 0 && pitem[nitems - 1] == NULL)
28550c8de5b0SBaptiste Daroussin     {
28560c8de5b0SBaptiste Daroussin 	int i;
28570c8de5b0SBaptiste Daroussin 	if (plhs[nrules]->args != bp->args)
28580c8de5b0SBaptiste Daroussin 	    wrong_number_args_warning("default ", bp->name);
28590c8de5b0SBaptiste Daroussin 	for (i = bp->args - 1; i >= 0; i--)
28600c8de5b0SBaptiste Daroussin 	    if (plhs[nrules]->argtags[i] != bp->argtags[i])
28610c8de5b0SBaptiste Daroussin 		wrong_type_for_arg_warning(i + 1, bp->name);
28620c8de5b0SBaptiste Daroussin     }
28630c8de5b0SBaptiste Daroussin     else if (bp->args != argslen)
28640c8de5b0SBaptiste Daroussin 	wrong_number_args_warning("", bp->name);
2865c5b5d71aSJung-uk Kim     if (args != 0)
28660c8de5b0SBaptiste Daroussin     {
2867c5b5d71aSJung-uk Kim 	char *ap = args;
2868c5b5d71aSJung-uk Kim 	int i = 0;
2869c5b5d71aSJung-uk Kim 	int elide_cnt = can_elide_arg(&ap, bp->argtags[0]);
2870c5b5d71aSJung-uk Kim 
2871c5b5d71aSJung-uk Kim 	if (elide_cnt > argslen)
2872c5b5d71aSJung-uk Kim 	    elide_cnt = 0;
2873c5b5d71aSJung-uk Kim 	if (elide_cnt)
2874c5b5d71aSJung-uk Kim 	{
2875c5b5d71aSJung-uk Kim 	    for (i = 1; i < elide_cnt; i++)
2876c5b5d71aSJung-uk Kim 		if (can_elide_arg(&ap, bp->argtags[i]) != elide_cnt - i)
2877c5b5d71aSJung-uk Kim 		{
2878c5b5d71aSJung-uk Kim 		    elide_cnt = 0;
2879c5b5d71aSJung-uk Kim 		    break;
2880c5b5d71aSJung-uk Kim 		}
2881c5b5d71aSJung-uk Kim 	}
2882c5b5d71aSJung-uk Kim 	if (elide_cnt)
2883c5b5d71aSJung-uk Kim 	{
2884c5b5d71aSJung-uk Kim 	    assert(i == elide_cnt);
2885c5b5d71aSJung-uk Kim 	}
2886c5b5d71aSJung-uk Kim 	else
2887c5b5d71aSJung-uk Kim 	{
2888c5b5d71aSJung-uk Kim 	    ap = args;
2889c5b5d71aSJung-uk Kim 	    i = 0;
2890c5b5d71aSJung-uk Kim 	}
2891c5b5d71aSJung-uk Kim 	for (; i < argslen; i++)
28920c8de5b0SBaptiste Daroussin 	    ap = insert_arg_rule(ap, bp->argtags[i]);
28930c8de5b0SBaptiste Daroussin 	free(args);
28940c8de5b0SBaptiste Daroussin     }
28950c8de5b0SBaptiste Daroussin #endif /* defined(YYBTYACC) */
28960c8de5b0SBaptiste Daroussin 
289798e903e7SBaptiste Daroussin     if (++nitems > maxitems)
289898e903e7SBaptiste Daroussin 	expand_items();
289998e903e7SBaptiste Daroussin     pitem[nitems - 1] = bp;
290098e903e7SBaptiste Daroussin }
290198e903e7SBaptiste Daroussin 
290298e903e7SBaptiste Daroussin static void
copy_action(void)290398e903e7SBaptiste Daroussin copy_action(void)
290498e903e7SBaptiste Daroussin {
290598e903e7SBaptiste Daroussin     int c;
29060c8de5b0SBaptiste Daroussin     int i, j, n;
290798e903e7SBaptiste Daroussin     int depth;
29080c8de5b0SBaptiste Daroussin #if defined(YYBTYACC)
29090c8de5b0SBaptiste Daroussin     int haveyyval = 0;
29100c8de5b0SBaptiste Daroussin #endif
291198e903e7SBaptiste Daroussin     char *tag;
291298e903e7SBaptiste Daroussin     FILE *f = action_file;
29132aca18c7SJung-uk Kim     struct ainfo a;
29140c8de5b0SBaptiste Daroussin     Value_t *offsets = NULL, maxoffset;
29150c8de5b0SBaptiste Daroussin     bucket **rhs;
291698e903e7SBaptiste Daroussin 
2917*822ca327SBaptiste Daroussin     begin_ainfo(a, 0);
29182aca18c7SJung-uk Kim 
291998e903e7SBaptiste Daroussin     if (last_was_action)
292098e903e7SBaptiste Daroussin 	insert_empty_rule();
292198e903e7SBaptiste Daroussin     last_was_action = 1;
2922c5b5d71aSJung-uk Kim #if defined(YYBTYACC)
2923c5b5d71aSJung-uk Kim     trialaction = (*cptr == L_BRAC);
2924c5b5d71aSJung-uk Kim #endif
292598e903e7SBaptiste Daroussin 
29268e022d3cSDag-Erling Smørgrav     begin_case(f, nrules - 2);
29270c8de5b0SBaptiste Daroussin #if defined(YYBTYACC)
29280c8de5b0SBaptiste Daroussin     if (backtrack)
29290c8de5b0SBaptiste Daroussin     {
2930c5b5d71aSJung-uk Kim 	if (!trialaction)
29310c8de5b0SBaptiste Daroussin 	    fprintf(f, "  if (!yytrial)\n");
29320c8de5b0SBaptiste Daroussin     }
29330c8de5b0SBaptiste Daroussin #endif
29348e022d3cSDag-Erling Smørgrav     fprintf_lineno(f, lineno, input_file_name);
293598e903e7SBaptiste Daroussin     if (*cptr == '=')
293698e903e7SBaptiste Daroussin 	++cptr;
293798e903e7SBaptiste Daroussin 
293898e903e7SBaptiste Daroussin     /* avoid putting curly-braces in first column, to ease editing */
293998e903e7SBaptiste Daroussin     if (*after_blanks(cptr) == L_CURL)
294098e903e7SBaptiste Daroussin     {
294198e903e7SBaptiste Daroussin 	putc('\t', f);
294298e903e7SBaptiste Daroussin 	cptr = after_blanks(cptr);
294398e903e7SBaptiste Daroussin     }
294498e903e7SBaptiste Daroussin 
29450c8de5b0SBaptiste Daroussin     maxoffset = 0;
294698e903e7SBaptiste Daroussin     n = 0;
294798e903e7SBaptiste Daroussin     for (i = nitems - 1; pitem[i]; --i)
29480c8de5b0SBaptiste Daroussin     {
294998e903e7SBaptiste Daroussin 	++n;
29500c8de5b0SBaptiste Daroussin 	if (pitem[i]->class != ARGUMENT)
29510c8de5b0SBaptiste Daroussin 	    maxoffset++;
29520c8de5b0SBaptiste Daroussin     }
29530c8de5b0SBaptiste Daroussin     if (maxoffset > 0)
29540c8de5b0SBaptiste Daroussin     {
29550c8de5b0SBaptiste Daroussin 	offsets = TMALLOC(Value_t, maxoffset + 1);
29560c8de5b0SBaptiste Daroussin 	NO_SPACE(offsets);
295711fce282SBaptiste Daroussin 
29580c8de5b0SBaptiste Daroussin 	for (j = 0, i++; i < nitems; i++)
29590c8de5b0SBaptiste Daroussin 	{
29600c8de5b0SBaptiste Daroussin 	    if (pitem[i]->class != ARGUMENT)
29610c8de5b0SBaptiste Daroussin 	    {
29620c8de5b0SBaptiste Daroussin 		offsets[++j] = (Value_t)(i - nitems + 1);
29630c8de5b0SBaptiste Daroussin 	    }
29640c8de5b0SBaptiste Daroussin 	}
296511fce282SBaptiste Daroussin     }
29660c8de5b0SBaptiste Daroussin     rhs = pitem + nitems - 1;
296798e903e7SBaptiste Daroussin 
296898e903e7SBaptiste Daroussin     depth = 0;
296998e903e7SBaptiste Daroussin   loop:
297098e903e7SBaptiste Daroussin     c = *cptr;
297198e903e7SBaptiste Daroussin     if (c == '$')
297298e903e7SBaptiste Daroussin     {
297398e903e7SBaptiste Daroussin 	if (cptr[1] == '<')
297498e903e7SBaptiste Daroussin 	{
297598e903e7SBaptiste Daroussin 	    int d_lineno = lineno;
297698e903e7SBaptiste Daroussin 	    char *d_line = dup_line();
297798e903e7SBaptiste Daroussin 	    char *d_cptr = d_line + (cptr - line);
297898e903e7SBaptiste Daroussin 
297998e903e7SBaptiste Daroussin 	    ++cptr;
298098e903e7SBaptiste Daroussin 	    tag = get_tag();
298198e903e7SBaptiste Daroussin 	    c = *cptr;
298298e903e7SBaptiste Daroussin 	    if (c == '$')
298398e903e7SBaptiste Daroussin 	    {
298498e903e7SBaptiste Daroussin 		fprintf(f, "yyval.%s", tag);
298598e903e7SBaptiste Daroussin 		++cptr;
298698e903e7SBaptiste Daroussin 		FREE(d_line);
298798e903e7SBaptiste Daroussin 		goto loop;
298898e903e7SBaptiste Daroussin 	    }
2989b53bb29fSJung-uk Kim 	    else if (isdigit(UCH(c)))
299098e903e7SBaptiste Daroussin 	    {
299198e903e7SBaptiste Daroussin 		i = get_number();
29920c8de5b0SBaptiste Daroussin 		if (i == 0)
29930c8de5b0SBaptiste Daroussin 		    fprintf(f, "yystack.l_mark[%d].%s", -n, tag);
29940c8de5b0SBaptiste Daroussin 		else if (i > maxoffset)
29950c8de5b0SBaptiste Daroussin 		{
299698e903e7SBaptiste Daroussin 		    dollar_warning(d_lineno, i);
29978e022d3cSDag-Erling Smørgrav 		    fprintf(f, "yystack.l_mark[%ld].%s",
29988e022d3cSDag-Erling Smørgrav 			    (long)(i - maxoffset), tag);
29990c8de5b0SBaptiste Daroussin 		}
30000c8de5b0SBaptiste Daroussin 		else if (offsets)
30018e022d3cSDag-Erling Smørgrav 		    fprintf(f, "yystack.l_mark[%ld].%s",
30028e022d3cSDag-Erling Smørgrav 			    (long)offsets[i], tag);
300398e903e7SBaptiste Daroussin 		FREE(d_line);
300498e903e7SBaptiste Daroussin 		goto loop;
300598e903e7SBaptiste Daroussin 	    }
300698e903e7SBaptiste Daroussin 	    else if (c == '-' && isdigit(UCH(cptr[1])))
300798e903e7SBaptiste Daroussin 	    {
300898e903e7SBaptiste Daroussin 		++cptr;
300998e903e7SBaptiste Daroussin 		i = -get_number() - n;
301098e903e7SBaptiste Daroussin 		fprintf(f, "yystack.l_mark[%d].%s", i, tag);
301198e903e7SBaptiste Daroussin 		FREE(d_line);
301298e903e7SBaptiste Daroussin 		goto loop;
301398e903e7SBaptiste Daroussin 	    }
30140c8de5b0SBaptiste Daroussin #if defined(YYBTYACC)
3015b53bb29fSJung-uk Kim 	    else if (isalpha(UCH(c)) || c == '_')
30160c8de5b0SBaptiste Daroussin 	    {
30170c8de5b0SBaptiste Daroussin 		char *arg = scan_id();
30180c8de5b0SBaptiste Daroussin 		for (i = plhs[nrules]->args - 1; i >= 0; i--)
30190c8de5b0SBaptiste Daroussin 		    if (arg == plhs[nrules]->argnames[i])
30200c8de5b0SBaptiste Daroussin 			break;
30210c8de5b0SBaptiste Daroussin 		if (i < 0)
30220c8de5b0SBaptiste Daroussin 		    unknown_arg_warning(d_lineno, "$", arg, d_line, d_cptr);
3023c5b5d71aSJung-uk Kim 		fprintf(f, "yystack.l_mark[%d].%s",
3024c5b5d71aSJung-uk Kim 			i - plhs[nrules]->args + 1 - n, tag);
30250c8de5b0SBaptiste Daroussin 		FREE(d_line);
30260c8de5b0SBaptiste Daroussin 		goto loop;
30270c8de5b0SBaptiste Daroussin 	    }
30280c8de5b0SBaptiste Daroussin #endif
302998e903e7SBaptiste Daroussin 	    else
303098e903e7SBaptiste Daroussin 		dollar_error(d_lineno, d_line, d_cptr);
303198e903e7SBaptiste Daroussin 	}
303298e903e7SBaptiste Daroussin 	else if (cptr[1] == '$')
303398e903e7SBaptiste Daroussin 	{
30340c8de5b0SBaptiste Daroussin 	    if (havetags)
303598e903e7SBaptiste Daroussin 	    {
303698e903e7SBaptiste Daroussin 		tag = plhs[nrules]->tag;
303798e903e7SBaptiste Daroussin 		if (tag == 0)
303898e903e7SBaptiste Daroussin 		    untyped_lhs();
303998e903e7SBaptiste Daroussin 		fprintf(f, "yyval.%s", tag);
304098e903e7SBaptiste Daroussin 	    }
304198e903e7SBaptiste Daroussin 	    else
304298e903e7SBaptiste Daroussin 		fprintf(f, "yyval");
304398e903e7SBaptiste Daroussin 	    cptr += 2;
30440c8de5b0SBaptiste Daroussin #if defined(YYBTYACC)
30450c8de5b0SBaptiste Daroussin 	    haveyyval = 1;
30460c8de5b0SBaptiste Daroussin #endif
304798e903e7SBaptiste Daroussin 	    goto loop;
304898e903e7SBaptiste Daroussin 	}
304998e903e7SBaptiste Daroussin 	else if (isdigit(UCH(cptr[1])))
305098e903e7SBaptiste Daroussin 	{
305198e903e7SBaptiste Daroussin 	    ++cptr;
305298e903e7SBaptiste Daroussin 	    i = get_number();
305311fce282SBaptiste Daroussin 	    if (havetags && offsets)
305498e903e7SBaptiste Daroussin 	    {
30550c8de5b0SBaptiste Daroussin 		if (i <= 0 || i > maxoffset)
305698e903e7SBaptiste Daroussin 		    unknown_rhs(i);
30570c8de5b0SBaptiste Daroussin 		tag = rhs[offsets[i]]->tag;
305898e903e7SBaptiste Daroussin 		if (tag == 0)
30590c8de5b0SBaptiste Daroussin 		    untyped_rhs(i, rhs[offsets[i]]->name);
30608e022d3cSDag-Erling Smørgrav 		fprintf(f, "yystack.l_mark[%ld].%s", (long)offsets[i], tag);
306198e903e7SBaptiste Daroussin 	    }
306298e903e7SBaptiste Daroussin 	    else
306398e903e7SBaptiste Daroussin 	    {
30640c8de5b0SBaptiste Daroussin 		if (i == 0)
30650c8de5b0SBaptiste Daroussin 		    fprintf(f, "yystack.l_mark[%d]", -n);
30660c8de5b0SBaptiste Daroussin 		else if (i > maxoffset)
30670c8de5b0SBaptiste Daroussin 		{
306898e903e7SBaptiste Daroussin 		    dollar_warning(lineno, i);
30698e022d3cSDag-Erling Smørgrav 		    fprintf(f, "yystack.l_mark[%ld]", (long)(i - maxoffset));
30700c8de5b0SBaptiste Daroussin 		}
30710c8de5b0SBaptiste Daroussin 		else if (offsets)
30728e022d3cSDag-Erling Smørgrav 		    fprintf(f, "yystack.l_mark[%ld]", (long)offsets[i]);
307398e903e7SBaptiste Daroussin 	    }
307498e903e7SBaptiste Daroussin 	    goto loop;
307598e903e7SBaptiste Daroussin 	}
307698e903e7SBaptiste Daroussin 	else if (cptr[1] == '-')
307798e903e7SBaptiste Daroussin 	{
307898e903e7SBaptiste Daroussin 	    cptr += 2;
307998e903e7SBaptiste Daroussin 	    i = get_number();
30800c8de5b0SBaptiste Daroussin 	    if (havetags)
308198e903e7SBaptiste Daroussin 		unknown_rhs(-i);
308298e903e7SBaptiste Daroussin 	    fprintf(f, "yystack.l_mark[%d]", -i - n);
308398e903e7SBaptiste Daroussin 	    goto loop;
308498e903e7SBaptiste Daroussin 	}
30850c8de5b0SBaptiste Daroussin #if defined(YYBTYACC)
30862aca18c7SJung-uk Kim 	else if (isalpha(UCH(cptr[1])) || cptr[1] == '_')
30870c8de5b0SBaptiste Daroussin 	{
30880c8de5b0SBaptiste Daroussin 	    char *arg;
30890c8de5b0SBaptiste Daroussin 	    ++cptr;
30900c8de5b0SBaptiste Daroussin 	    arg = scan_id();
30910c8de5b0SBaptiste Daroussin 	    for (i = plhs[nrules]->args - 1; i >= 0; i--)
30920c8de5b0SBaptiste Daroussin 		if (arg == plhs[nrules]->argnames[i])
30930c8de5b0SBaptiste Daroussin 		    break;
30940c8de5b0SBaptiste Daroussin 	    if (i < 0)
30950c8de5b0SBaptiste Daroussin 		unknown_arg_warning(lineno, "$", arg, line, cptr);
30960c8de5b0SBaptiste Daroussin 	    tag = (i < 0 ? NULL : plhs[nrules]->argtags[i]);
30970c8de5b0SBaptiste Daroussin 	    fprintf(f, "yystack.l_mark[%d]", i - plhs[nrules]->args + 1 - n);
30980c8de5b0SBaptiste Daroussin 	    if (tag)
30990c8de5b0SBaptiste Daroussin 		fprintf(f, ".%s", tag);
31000c8de5b0SBaptiste Daroussin 	    else if (havetags)
31010c8de5b0SBaptiste Daroussin 		untyped_arg_warning(lineno, "$", arg);
31020c8de5b0SBaptiste Daroussin 	    goto loop;
310398e903e7SBaptiste Daroussin 	}
31040c8de5b0SBaptiste Daroussin #endif
31050c8de5b0SBaptiste Daroussin     }
31060c8de5b0SBaptiste Daroussin #if defined(YYBTYACC)
31070c8de5b0SBaptiste Daroussin     if (c == '@')
31080c8de5b0SBaptiste Daroussin     {
31090c8de5b0SBaptiste Daroussin 	if (!locations)
31100c8de5b0SBaptiste Daroussin 	{
3111*822ca327SBaptiste Daroussin 	    dislocations_warning();
3112*822ca327SBaptiste Daroussin 	    locations = 1;
31130c8de5b0SBaptiste Daroussin 	}
31140c8de5b0SBaptiste Daroussin 	if (cptr[1] == '$')
31150c8de5b0SBaptiste Daroussin 	{
31160c8de5b0SBaptiste Daroussin 	    fprintf(f, "yyloc");
31170c8de5b0SBaptiste Daroussin 	    cptr += 2;
31180c8de5b0SBaptiste Daroussin 	    goto loop;
31190c8de5b0SBaptiste Daroussin 	}
31200c8de5b0SBaptiste Daroussin 	else if (isdigit(UCH(cptr[1])))
31210c8de5b0SBaptiste Daroussin 	{
31220c8de5b0SBaptiste Daroussin 	    ++cptr;
31230c8de5b0SBaptiste Daroussin 	    i = get_number();
31240c8de5b0SBaptiste Daroussin 	    if (i == 0)
31250c8de5b0SBaptiste Daroussin 		fprintf(f, "yystack.p_mark[%d]", -n);
31260c8de5b0SBaptiste Daroussin 	    else if (i > maxoffset)
31270c8de5b0SBaptiste Daroussin 	    {
31280c8de5b0SBaptiste Daroussin 		at_warning(lineno, i);
31290c8de5b0SBaptiste Daroussin 		fprintf(f, "yystack.p_mark[%d]", i - maxoffset);
31300c8de5b0SBaptiste Daroussin 	    }
31310c8de5b0SBaptiste Daroussin 	    else if (offsets)
31320c8de5b0SBaptiste Daroussin 		fprintf(f, "yystack.p_mark[%d]", offsets[i]);
31330c8de5b0SBaptiste Daroussin 	    goto loop;
31340c8de5b0SBaptiste Daroussin 	}
3135c5b5d71aSJung-uk Kim 	else if (cptr[1] == '-')
3136c5b5d71aSJung-uk Kim 	{
3137c5b5d71aSJung-uk Kim 	    cptr += 2;
3138c5b5d71aSJung-uk Kim 	    i = get_number();
3139c5b5d71aSJung-uk Kim 	    fprintf(f, "yystack.p_mark[%d]", -i - n);
3140c5b5d71aSJung-uk Kim 	    goto loop;
3141c5b5d71aSJung-uk Kim 	}
31420c8de5b0SBaptiste Daroussin     }
31430c8de5b0SBaptiste Daroussin #endif
3144b53bb29fSJung-uk Kim     if (IS_NAME1(c))
314598e903e7SBaptiste Daroussin     {
314698e903e7SBaptiste Daroussin 	do
314798e903e7SBaptiste Daroussin 	{
314898e903e7SBaptiste Daroussin 	    putc(c, f);
314998e903e7SBaptiste Daroussin 	    c = *++cptr;
315098e903e7SBaptiste Daroussin 	}
3151b53bb29fSJung-uk Kim 	while (IS_NAME2(c));
315298e903e7SBaptiste Daroussin 	goto loop;
315398e903e7SBaptiste Daroussin     }
315498e903e7SBaptiste Daroussin     ++cptr;
31550c8de5b0SBaptiste Daroussin #if defined(YYBTYACC)
31560c8de5b0SBaptiste Daroussin     if (backtrack)
31570c8de5b0SBaptiste Daroussin     {
31580c8de5b0SBaptiste Daroussin 	if (trialaction && c == L_BRAC && depth == 0)
31590c8de5b0SBaptiste Daroussin 	{
31600c8de5b0SBaptiste Daroussin 	    ++depth;
31610c8de5b0SBaptiste Daroussin 	    putc(L_CURL, f);
31620c8de5b0SBaptiste Daroussin 	    goto loop;
31630c8de5b0SBaptiste Daroussin 	}
31640c8de5b0SBaptiste Daroussin 	if (trialaction && c == R_BRAC && depth == 1)
31650c8de5b0SBaptiste Daroussin 	{
31660c8de5b0SBaptiste Daroussin 	    --depth;
31670c8de5b0SBaptiste Daroussin 	    putc(R_CURL, f);
31680c8de5b0SBaptiste Daroussin 	    c = nextc();
31690c8de5b0SBaptiste Daroussin 	    if (c == L_BRAC && !haveyyval)
31700c8de5b0SBaptiste Daroussin 	    {
31710c8de5b0SBaptiste Daroussin 		goto loop;
31720c8de5b0SBaptiste Daroussin 	    }
31730c8de5b0SBaptiste Daroussin 	    if (c == L_CURL && !haveyyval)
31740c8de5b0SBaptiste Daroussin 	    {
31750c8de5b0SBaptiste Daroussin 		fprintf(f, "  if (!yytrial)\n");
31768e022d3cSDag-Erling Smørgrav 		fprintf_lineno(f, lineno, input_file_name);
31770c8de5b0SBaptiste Daroussin 		trialaction = 0;
31780c8de5b0SBaptiste Daroussin 		goto loop;
31790c8de5b0SBaptiste Daroussin 	    }
31808e022d3cSDag-Erling Smørgrav 	    end_case(f);
3181*822ca327SBaptiste Daroussin 	    end_ainfo(a);
31820c8de5b0SBaptiste Daroussin 	    if (maxoffset > 0)
31830c8de5b0SBaptiste Daroussin 		FREE(offsets);
31840c8de5b0SBaptiste Daroussin 	    return;
31850c8de5b0SBaptiste Daroussin 	}
31860c8de5b0SBaptiste Daroussin     }
31870c8de5b0SBaptiste Daroussin #endif
31880c8de5b0SBaptiste Daroussin     putc(c, f);
318998e903e7SBaptiste Daroussin     switch (c)
319098e903e7SBaptiste Daroussin     {
319198e903e7SBaptiste Daroussin     case '\n':
319298e903e7SBaptiste Daroussin 	get_line();
319398e903e7SBaptiste Daroussin 	if (line)
319498e903e7SBaptiste Daroussin 	    goto loop;
31952aca18c7SJung-uk Kim 	unterminated_action(&a);
319698e903e7SBaptiste Daroussin 
319798e903e7SBaptiste Daroussin     case ';':
319898e903e7SBaptiste Daroussin 	if (depth > 0)
319998e903e7SBaptiste Daroussin 	    goto loop;
32008e022d3cSDag-Erling Smørgrav 	end_case(f);
3201*822ca327SBaptiste Daroussin 	end_ainfo(a);
32020c8de5b0SBaptiste Daroussin 	if (maxoffset > 0)
32030c8de5b0SBaptiste Daroussin 	    FREE(offsets);
320498e903e7SBaptiste Daroussin 	return;
320598e903e7SBaptiste Daroussin 
32060c8de5b0SBaptiste Daroussin #if defined(YYBTYACC)
32070c8de5b0SBaptiste Daroussin     case L_BRAC:
32080c8de5b0SBaptiste Daroussin 	if (backtrack)
32090c8de5b0SBaptiste Daroussin 	    ++depth;
32100c8de5b0SBaptiste Daroussin 	goto loop;
32110c8de5b0SBaptiste Daroussin 
32120c8de5b0SBaptiste Daroussin     case R_BRAC:
32130c8de5b0SBaptiste Daroussin 	if (backtrack)
32140c8de5b0SBaptiste Daroussin 	    --depth;
32150c8de5b0SBaptiste Daroussin 	goto loop;
32160c8de5b0SBaptiste Daroussin #endif
32170c8de5b0SBaptiste Daroussin 
321898e903e7SBaptiste Daroussin     case L_CURL:
321998e903e7SBaptiste Daroussin 	++depth;
322098e903e7SBaptiste Daroussin 	goto loop;
322198e903e7SBaptiste Daroussin 
322298e903e7SBaptiste Daroussin     case R_CURL:
322398e903e7SBaptiste Daroussin 	if (--depth > 0)
322498e903e7SBaptiste Daroussin 	    goto loop;
32250c8de5b0SBaptiste Daroussin #if defined(YYBTYACC)
32260c8de5b0SBaptiste Daroussin 	if (backtrack)
32270c8de5b0SBaptiste Daroussin 	{
32280c8de5b0SBaptiste Daroussin 	    c = nextc();
32290c8de5b0SBaptiste Daroussin 	    if (c == L_BRAC && !haveyyval)
32300c8de5b0SBaptiste Daroussin 	    {
32310c8de5b0SBaptiste Daroussin 		trialaction = 1;
32320c8de5b0SBaptiste Daroussin 		goto loop;
32330c8de5b0SBaptiste Daroussin 	    }
32340c8de5b0SBaptiste Daroussin 	    if (c == L_CURL && !haveyyval)
32350c8de5b0SBaptiste Daroussin 	    {
32360c8de5b0SBaptiste Daroussin 		fprintf(f, "  if (!yytrial)\n");
32378e022d3cSDag-Erling Smørgrav 		fprintf_lineno(f, lineno, input_file_name);
32380c8de5b0SBaptiste Daroussin 		goto loop;
32390c8de5b0SBaptiste Daroussin 	    }
32400c8de5b0SBaptiste Daroussin 	}
32410c8de5b0SBaptiste Daroussin #endif
32428e022d3cSDag-Erling Smørgrav 	end_case(f);
3243*822ca327SBaptiste Daroussin 	end_ainfo(a);
32440c8de5b0SBaptiste Daroussin 	if (maxoffset > 0)
32450c8de5b0SBaptiste Daroussin 	    FREE(offsets);
324698e903e7SBaptiste Daroussin 	return;
324798e903e7SBaptiste Daroussin 
324898e903e7SBaptiste Daroussin     case '\'':
324998e903e7SBaptiste Daroussin     case '"':
325098e903e7SBaptiste Daroussin 	{
32510c8de5b0SBaptiste Daroussin 	    char *s = copy_string(c);
32520c8de5b0SBaptiste Daroussin 	    fputs(s, f);
32530c8de5b0SBaptiste Daroussin 	    free(s);
32540c8de5b0SBaptiste Daroussin 	}
32550c8de5b0SBaptiste Daroussin 	goto loop;
325698e903e7SBaptiste Daroussin 
32570c8de5b0SBaptiste Daroussin     case '/':
32580c8de5b0SBaptiste Daroussin 	{
32590c8de5b0SBaptiste Daroussin 	    char *s = copy_comment();
32600c8de5b0SBaptiste Daroussin 	    fputs(s, f);
32610c8de5b0SBaptiste Daroussin 	    free(s);
32620c8de5b0SBaptiste Daroussin 	}
32630c8de5b0SBaptiste Daroussin 	goto loop;
32640c8de5b0SBaptiste Daroussin 
32650c8de5b0SBaptiste Daroussin     default:
32660c8de5b0SBaptiste Daroussin 	goto loop;
32670c8de5b0SBaptiste Daroussin     }
32680c8de5b0SBaptiste Daroussin }
32690c8de5b0SBaptiste Daroussin 
32700c8de5b0SBaptiste Daroussin #if defined(YYBTYACC)
32712aca18c7SJung-uk Kim static char *
get_code(struct ainfo * a,const char * loc)32722aca18c7SJung-uk Kim get_code(struct ainfo *a, const char *loc)
32730c8de5b0SBaptiste Daroussin {
32740c8de5b0SBaptiste Daroussin     int c;
32750c8de5b0SBaptiste Daroussin     int depth;
32760c8de5b0SBaptiste Daroussin     char *tag;
32772aca18c7SJung-uk Kim     struct mstring *code_mstr = msnew();
32780c8de5b0SBaptiste Daroussin 
32790c8de5b0SBaptiste Daroussin     if (!lflag)
32802aca18c7SJung-uk Kim 	msprintf(code_mstr, line_format, lineno, input_file_name);
32810c8de5b0SBaptiste Daroussin 
32820c8de5b0SBaptiste Daroussin     cptr = after_blanks(cptr);
32830c8de5b0SBaptiste Daroussin     if (*cptr == L_CURL)
32840c8de5b0SBaptiste Daroussin 	/* avoid putting curly-braces in first column, to ease editing */
32852aca18c7SJung-uk Kim 	mputc(code_mstr, '\t');
32860c8de5b0SBaptiste Daroussin     else
32870c8de5b0SBaptiste Daroussin 	syntax_error(lineno, line, cptr);
32880c8de5b0SBaptiste Daroussin 
3289*822ca327SBaptiste Daroussin     begin_ainfo((*a), 0);
32900c8de5b0SBaptiste Daroussin 
32910c8de5b0SBaptiste Daroussin     depth = 0;
32920c8de5b0SBaptiste Daroussin   loop:
32930c8de5b0SBaptiste Daroussin     c = *cptr;
32940c8de5b0SBaptiste Daroussin     if (c == '$')
32950c8de5b0SBaptiste Daroussin     {
32960c8de5b0SBaptiste Daroussin 	if (cptr[1] == '<')
32970c8de5b0SBaptiste Daroussin 	{
32980c8de5b0SBaptiste Daroussin 	    int d_lineno = lineno;
32990c8de5b0SBaptiste Daroussin 	    char *d_line = dup_line();
33000c8de5b0SBaptiste Daroussin 	    char *d_cptr = d_line + (cptr - line);
33010c8de5b0SBaptiste Daroussin 
33020c8de5b0SBaptiste Daroussin 	    ++cptr;
33030c8de5b0SBaptiste Daroussin 	    tag = get_tag();
33040c8de5b0SBaptiste Daroussin 	    c = *cptr;
33050c8de5b0SBaptiste Daroussin 	    if (c == '$')
33060c8de5b0SBaptiste Daroussin 	    {
33072aca18c7SJung-uk Kim 		msprintf(code_mstr, "(*val).%s", tag);
33080c8de5b0SBaptiste Daroussin 		++cptr;
33090c8de5b0SBaptiste Daroussin 		FREE(d_line);
33100c8de5b0SBaptiste Daroussin 		goto loop;
33110c8de5b0SBaptiste Daroussin 	    }
33120c8de5b0SBaptiste Daroussin 	    else
33130c8de5b0SBaptiste Daroussin 		dollar_error(d_lineno, d_line, d_cptr);
33140c8de5b0SBaptiste Daroussin 	}
33150c8de5b0SBaptiste Daroussin 	else if (cptr[1] == '$')
33160c8de5b0SBaptiste Daroussin 	{
33170c8de5b0SBaptiste Daroussin 	    /* process '$$' later; replacement is context dependent */
33182aca18c7SJung-uk Kim 	    msprintf(code_mstr, "$$");
33190c8de5b0SBaptiste Daroussin 	    cptr += 2;
33200c8de5b0SBaptiste Daroussin 	    goto loop;
33210c8de5b0SBaptiste Daroussin 	}
33220c8de5b0SBaptiste Daroussin     }
33230c8de5b0SBaptiste Daroussin     if (c == '@' && cptr[1] == '$')
33240c8de5b0SBaptiste Daroussin     {
33250c8de5b0SBaptiste Daroussin 	if (!locations)
33260c8de5b0SBaptiste Daroussin 	{
3327*822ca327SBaptiste Daroussin 	    dislocations_warning();
3328*822ca327SBaptiste Daroussin 	    locations = 1;
33290c8de5b0SBaptiste Daroussin 	}
33302aca18c7SJung-uk Kim 	msprintf(code_mstr, "%s", loc);
33310c8de5b0SBaptiste Daroussin 	cptr += 2;
33320c8de5b0SBaptiste Daroussin 	goto loop;
33330c8de5b0SBaptiste Daroussin     }
3334b53bb29fSJung-uk Kim     if (IS_NAME1(c))
33350c8de5b0SBaptiste Daroussin     {
33360c8de5b0SBaptiste Daroussin 	do
33370c8de5b0SBaptiste Daroussin 	{
33382aca18c7SJung-uk Kim 	    mputc(code_mstr, c);
33390c8de5b0SBaptiste Daroussin 	    c = *++cptr;
33400c8de5b0SBaptiste Daroussin 	}
3341b53bb29fSJung-uk Kim 	while (IS_NAME2(c));
33420c8de5b0SBaptiste Daroussin 	goto loop;
33430c8de5b0SBaptiste Daroussin     }
33440c8de5b0SBaptiste Daroussin     ++cptr;
33452aca18c7SJung-uk Kim     mputc(code_mstr, c);
33460c8de5b0SBaptiste Daroussin     switch (c)
33470c8de5b0SBaptiste Daroussin     {
33480c8de5b0SBaptiste Daroussin     case '\n':
33490c8de5b0SBaptiste Daroussin 	get_line();
33500c8de5b0SBaptiste Daroussin 	if (line)
33510c8de5b0SBaptiste Daroussin 	    goto loop;
33522aca18c7SJung-uk Kim 	unterminated_action(a);
33530c8de5b0SBaptiste Daroussin 
33540c8de5b0SBaptiste Daroussin     case L_CURL:
33550c8de5b0SBaptiste Daroussin 	++depth;
33560c8de5b0SBaptiste Daroussin 	goto loop;
33570c8de5b0SBaptiste Daroussin 
33580c8de5b0SBaptiste Daroussin     case R_CURL:
33590c8de5b0SBaptiste Daroussin 	if (--depth > 0)
33600c8de5b0SBaptiste Daroussin 	    goto loop;
33612aca18c7SJung-uk Kim 	goto out;
33620c8de5b0SBaptiste Daroussin 
33630c8de5b0SBaptiste Daroussin     case '\'':
33640c8de5b0SBaptiste Daroussin     case '"':
33650c8de5b0SBaptiste Daroussin 	{
33660c8de5b0SBaptiste Daroussin 	    char *s = copy_string(c);
33672aca18c7SJung-uk Kim 	    msprintf(code_mstr, "%s", s);
33680c8de5b0SBaptiste Daroussin 	    free(s);
33690c8de5b0SBaptiste Daroussin 	}
33700c8de5b0SBaptiste Daroussin 	goto loop;
33710c8de5b0SBaptiste Daroussin 
33720c8de5b0SBaptiste Daroussin     case '/':
33730c8de5b0SBaptiste Daroussin 	{
33740c8de5b0SBaptiste Daroussin 	    char *s = copy_comment();
33752aca18c7SJung-uk Kim 	    msprintf(code_mstr, "%s", s);
33760c8de5b0SBaptiste Daroussin 	    free(s);
33770c8de5b0SBaptiste Daroussin 	}
33780c8de5b0SBaptiste Daroussin 	goto loop;
33790c8de5b0SBaptiste Daroussin 
33800c8de5b0SBaptiste Daroussin     default:
33810c8de5b0SBaptiste Daroussin 	goto loop;
33820c8de5b0SBaptiste Daroussin     }
33832aca18c7SJung-uk Kim   out:
33842aca18c7SJung-uk Kim     return msdone(code_mstr);
33852aca18c7SJung-uk Kim }
33862aca18c7SJung-uk Kim 
33872aca18c7SJung-uk Kim static void
copy_initial_action(void)33882aca18c7SJung-uk Kim copy_initial_action(void)
33892aca18c7SJung-uk Kim {
33902aca18c7SJung-uk Kim     struct ainfo a;
33912aca18c7SJung-uk Kim 
33922aca18c7SJung-uk Kim     initial_action = get_code(&a, "yyloc");
3393*822ca327SBaptiste Daroussin     end_ainfo(a);
33942aca18c7SJung-uk Kim }
33952aca18c7SJung-uk Kim 
33962aca18c7SJung-uk Kim static void
copy_destructor(void)33972aca18c7SJung-uk Kim copy_destructor(void)
33982aca18c7SJung-uk Kim {
33992aca18c7SJung-uk Kim     char *code_text;
34002aca18c7SJung-uk Kim     struct ainfo a;
34012aca18c7SJung-uk Kim     bucket *bp;
34022aca18c7SJung-uk Kim 
34032aca18c7SJung-uk Kim     code_text = get_code(&a, "(*loc)");
34042aca18c7SJung-uk Kim 
34050c8de5b0SBaptiste Daroussin     for (;;)
34060c8de5b0SBaptiste Daroussin     {
34078e022d3cSDag-Erling Smørgrav 	int c = nextc();
34080c8de5b0SBaptiste Daroussin 	if (c == EOF)
34090c8de5b0SBaptiste Daroussin 	    unexpected_EOF();
34100c8de5b0SBaptiste Daroussin 	if (c == '<')
34110c8de5b0SBaptiste Daroussin 	{
34120c8de5b0SBaptiste Daroussin 	    if (cptr[1] == '>')
34130c8de5b0SBaptiste Daroussin 	    {			/* "no semantic type" default destructor */
34140c8de5b0SBaptiste Daroussin 		cptr += 2;
34150c8de5b0SBaptiste Daroussin 		if ((bp = default_destructor[UNTYPED_DEFAULT]) == NULL)
34160c8de5b0SBaptiste Daroussin 		{
34170c8de5b0SBaptiste Daroussin 		    static char untyped_default[] = "<>";
34180c8de5b0SBaptiste Daroussin 		    bp = make_bucket("untyped default");
34190c8de5b0SBaptiste Daroussin 		    bp->tag = untyped_default;
34200c8de5b0SBaptiste Daroussin 		    default_destructor[UNTYPED_DEFAULT] = bp;
34210c8de5b0SBaptiste Daroussin 		}
34220c8de5b0SBaptiste Daroussin 		if (bp->destructor != NULL)
34232aca18c7SJung-uk Kim 		    destructor_redeclared_warning(&a);
34240c8de5b0SBaptiste Daroussin 		else
34250c8de5b0SBaptiste Daroussin 		    /* replace "$$" with "(*val)" in destructor code */
34260c8de5b0SBaptiste Daroussin 		    bp->destructor = process_destructor_XX(code_text, NULL);
34270c8de5b0SBaptiste Daroussin 	    }
34280c8de5b0SBaptiste Daroussin 	    else if (cptr[1] == '*' && cptr[2] == '>')
34290c8de5b0SBaptiste Daroussin 	    {			/* "no per-symbol or per-type" default destructor */
34300c8de5b0SBaptiste Daroussin 		cptr += 3;
34310c8de5b0SBaptiste Daroussin 		if ((bp = default_destructor[TYPED_DEFAULT]) == NULL)
34320c8de5b0SBaptiste Daroussin 		{
34330c8de5b0SBaptiste Daroussin 		    static char typed_default[] = "<*>";
34340c8de5b0SBaptiste Daroussin 		    bp = make_bucket("typed default");
34350c8de5b0SBaptiste Daroussin 		    bp->tag = typed_default;
34360c8de5b0SBaptiste Daroussin 		    default_destructor[TYPED_DEFAULT] = bp;
34370c8de5b0SBaptiste Daroussin 		}
34380c8de5b0SBaptiste Daroussin 		if (bp->destructor != NULL)
34392aca18c7SJung-uk Kim 		    destructor_redeclared_warning(&a);
34400c8de5b0SBaptiste Daroussin 		else
34410c8de5b0SBaptiste Daroussin 		{
34420c8de5b0SBaptiste Daroussin 		    /* postpone re-processing destructor $$s until end of grammar spec */
34430c8de5b0SBaptiste Daroussin 		    bp->destructor = TMALLOC(char, strlen(code_text) + 1);
34440c8de5b0SBaptiste Daroussin 		    NO_SPACE(bp->destructor);
34450c8de5b0SBaptiste Daroussin 		    strcpy(bp->destructor, code_text);
34460c8de5b0SBaptiste Daroussin 		}
34470c8de5b0SBaptiste Daroussin 	    }
34480c8de5b0SBaptiste Daroussin 	    else
34490c8de5b0SBaptiste Daroussin 	    {			/* "semantic type" default destructor */
34502aca18c7SJung-uk Kim 		char *tag = get_tag();
34510c8de5b0SBaptiste Daroussin 		bp = lookup_type_destructor(tag);
34520c8de5b0SBaptiste Daroussin 		if (bp->destructor != NULL)
34532aca18c7SJung-uk Kim 		    destructor_redeclared_warning(&a);
34540c8de5b0SBaptiste Daroussin 		else
34550c8de5b0SBaptiste Daroussin 		    /* replace "$$" with "(*val).tag" in destructor code */
34560c8de5b0SBaptiste Daroussin 		    bp->destructor = process_destructor_XX(code_text, tag);
34570c8de5b0SBaptiste Daroussin 	    }
34580c8de5b0SBaptiste Daroussin 	}
3459b53bb29fSJung-uk Kim 	else if (isalpha(UCH(c)) || c == '_' || c == '.' || c == '$')
34600c8de5b0SBaptiste Daroussin 	{			/* "symbol" destructor */
34610c8de5b0SBaptiste Daroussin 	    bp = get_name();
34620c8de5b0SBaptiste Daroussin 	    if (bp->destructor != NULL)
34632aca18c7SJung-uk Kim 		destructor_redeclared_warning(&a);
34640c8de5b0SBaptiste Daroussin 	    else
34650c8de5b0SBaptiste Daroussin 	    {
34660c8de5b0SBaptiste Daroussin 		/* postpone re-processing destructor $$s until end of grammar spec */
34670c8de5b0SBaptiste Daroussin 		bp->destructor = TMALLOC(char, strlen(code_text) + 1);
34680c8de5b0SBaptiste Daroussin 		NO_SPACE(bp->destructor);
34690c8de5b0SBaptiste Daroussin 		strcpy(bp->destructor, code_text);
34700c8de5b0SBaptiste Daroussin 	    }
34710c8de5b0SBaptiste Daroussin 	}
34720c8de5b0SBaptiste Daroussin 	else
34730c8de5b0SBaptiste Daroussin 	    break;
34740c8de5b0SBaptiste Daroussin     }
3475*822ca327SBaptiste Daroussin     end_ainfo(a);
34760c8de5b0SBaptiste Daroussin     free(code_text);
34770c8de5b0SBaptiste Daroussin }
34780c8de5b0SBaptiste Daroussin 
34790c8de5b0SBaptiste Daroussin static char *
process_destructor_XX(char * code,char * tag)34800c8de5b0SBaptiste Daroussin process_destructor_XX(char *code, char *tag)
34810c8de5b0SBaptiste Daroussin {
34820c8de5b0SBaptiste Daroussin     int c;
34830c8de5b0SBaptiste Daroussin     int quote;
34840c8de5b0SBaptiste Daroussin     int depth;
34850c8de5b0SBaptiste Daroussin     struct mstring *new_code = msnew();
34860c8de5b0SBaptiste Daroussin     char *codeptr = code;
34870c8de5b0SBaptiste Daroussin 
34880c8de5b0SBaptiste Daroussin     depth = 0;
34890c8de5b0SBaptiste Daroussin   loop:			/* step thru code */
34900c8de5b0SBaptiste Daroussin     c = *codeptr;
34910c8de5b0SBaptiste Daroussin     if (c == '$' && codeptr[1] == '$')
34920c8de5b0SBaptiste Daroussin     {
34930c8de5b0SBaptiste Daroussin 	codeptr += 2;
34940c8de5b0SBaptiste Daroussin 	if (tag == NULL)
34950c8de5b0SBaptiste Daroussin 	    msprintf(new_code, "(*val)");
34960c8de5b0SBaptiste Daroussin 	else
34970c8de5b0SBaptiste Daroussin 	    msprintf(new_code, "(*val).%s", tag);
34980c8de5b0SBaptiste Daroussin 	goto loop;
34990c8de5b0SBaptiste Daroussin     }
3500b53bb29fSJung-uk Kim     if (IS_NAME1(c))
35010c8de5b0SBaptiste Daroussin     {
35020c8de5b0SBaptiste Daroussin 	do
35030c8de5b0SBaptiste Daroussin 	{
35040c8de5b0SBaptiste Daroussin 	    mputc(new_code, c);
35050c8de5b0SBaptiste Daroussin 	    c = *++codeptr;
35060c8de5b0SBaptiste Daroussin 	}
3507b53bb29fSJung-uk Kim 	while (IS_NAME2(c));
35080c8de5b0SBaptiste Daroussin 	goto loop;
35090c8de5b0SBaptiste Daroussin     }
35100c8de5b0SBaptiste Daroussin     ++codeptr;
35110c8de5b0SBaptiste Daroussin     mputc(new_code, c);
35120c8de5b0SBaptiste Daroussin     switch (c)
35130c8de5b0SBaptiste Daroussin     {
35140c8de5b0SBaptiste Daroussin     case L_CURL:
35150c8de5b0SBaptiste Daroussin 	++depth;
35160c8de5b0SBaptiste Daroussin 	goto loop;
35170c8de5b0SBaptiste Daroussin 
35180c8de5b0SBaptiste Daroussin     case R_CURL:
35190c8de5b0SBaptiste Daroussin 	if (--depth > 0)
35200c8de5b0SBaptiste Daroussin 	    goto loop;
35210c8de5b0SBaptiste Daroussin 	return msdone(new_code);
35220c8de5b0SBaptiste Daroussin 
35230c8de5b0SBaptiste Daroussin     case '\'':
35240c8de5b0SBaptiste Daroussin     case '"':
352598e903e7SBaptiste Daroussin 	quote = c;
352698e903e7SBaptiste Daroussin 	for (;;)
352798e903e7SBaptiste Daroussin 	{
35280c8de5b0SBaptiste Daroussin 	    c = *codeptr++;
35290c8de5b0SBaptiste Daroussin 	    mputc(new_code, c);
353098e903e7SBaptiste Daroussin 	    if (c == quote)
353198e903e7SBaptiste Daroussin 		goto loop;
353298e903e7SBaptiste Daroussin 	    if (c == '\\')
353398e903e7SBaptiste Daroussin 	    {
35340c8de5b0SBaptiste Daroussin 		c = *codeptr++;
35350c8de5b0SBaptiste Daroussin 		mputc(new_code, c);
353698e903e7SBaptiste Daroussin 	    }
353798e903e7SBaptiste Daroussin 	}
353898e903e7SBaptiste Daroussin 
353998e903e7SBaptiste Daroussin     case '/':
35400c8de5b0SBaptiste Daroussin 	c = *codeptr;
354198e903e7SBaptiste Daroussin 	if (c == '*')
354298e903e7SBaptiste Daroussin 	{
35430c8de5b0SBaptiste Daroussin 	    mputc(new_code, c);
35440c8de5b0SBaptiste Daroussin 	    ++codeptr;
354598e903e7SBaptiste Daroussin 	    for (;;)
354698e903e7SBaptiste Daroussin 	    {
35470c8de5b0SBaptiste Daroussin 		c = *codeptr++;
35480c8de5b0SBaptiste Daroussin 		mputc(new_code, c);
35490c8de5b0SBaptiste Daroussin 		if (c == '*' && *codeptr == '/')
355098e903e7SBaptiste Daroussin 		{
35510c8de5b0SBaptiste Daroussin 		    mputc(new_code, '/');
35520c8de5b0SBaptiste Daroussin 		    ++codeptr;
355398e903e7SBaptiste Daroussin 		    goto loop;
355498e903e7SBaptiste Daroussin 		}
355598e903e7SBaptiste Daroussin 	    }
355698e903e7SBaptiste Daroussin 	}
355798e903e7SBaptiste Daroussin 	goto loop;
355898e903e7SBaptiste Daroussin 
355998e903e7SBaptiste Daroussin     default:
356098e903e7SBaptiste Daroussin 	goto loop;
356198e903e7SBaptiste Daroussin     }
356298e903e7SBaptiste Daroussin }
35630c8de5b0SBaptiste Daroussin #endif /* defined(YYBTYACC) */
356498e903e7SBaptiste Daroussin 
356598e903e7SBaptiste Daroussin static int
mark_symbol(void)356698e903e7SBaptiste Daroussin mark_symbol(void)
356798e903e7SBaptiste Daroussin {
356898e903e7SBaptiste Daroussin     int c;
35693e066022SBaptiste Daroussin     bucket *bp = NULL;
357098e903e7SBaptiste Daroussin 
357198e903e7SBaptiste Daroussin     c = cptr[1];
357298e903e7SBaptiste Daroussin     if (c == '%' || c == '\\')
357398e903e7SBaptiste Daroussin     {
357498e903e7SBaptiste Daroussin 	cptr += 2;
357598e903e7SBaptiste Daroussin 	return (1);
357698e903e7SBaptiste Daroussin     }
357798e903e7SBaptiste Daroussin 
357898e903e7SBaptiste Daroussin     if (c == '=')
357998e903e7SBaptiste Daroussin 	cptr += 2;
358098e903e7SBaptiste Daroussin     else if ((c == 'p' || c == 'P') &&
358198e903e7SBaptiste Daroussin 	     ((c = cptr[2]) == 'r' || c == 'R') &&
358298e903e7SBaptiste Daroussin 	     ((c = cptr[3]) == 'e' || c == 'E') &&
358398e903e7SBaptiste Daroussin 	     ((c = cptr[4]) == 'c' || c == 'C') &&
358498e903e7SBaptiste Daroussin 	     ((c = cptr[5], !IS_IDENT(c))))
358598e903e7SBaptiste Daroussin 	cptr += 5;
35868e022d3cSDag-Erling Smørgrav     else if ((c == 'e' || c == 'E') &&
35878e022d3cSDag-Erling Smørgrav 	     ((c = cptr[2]) == 'm' || c == 'M') &&
35888e022d3cSDag-Erling Smørgrav 	     ((c = cptr[3]) == 'p' || c == 'P') &&
35898e022d3cSDag-Erling Smørgrav 	     ((c = cptr[4]) == 't' || c == 'T') &&
35908e022d3cSDag-Erling Smørgrav 	     ((c = cptr[5]) == 'y' || c == 'Y') &&
35918e022d3cSDag-Erling Smørgrav 	     ((c = cptr[6], !IS_IDENT(c))))
35928e022d3cSDag-Erling Smørgrav     {
35938e022d3cSDag-Erling Smørgrav 	cptr += 6;
35948e022d3cSDag-Erling Smørgrav 	return (1);
35958e022d3cSDag-Erling Smørgrav     }
359698e903e7SBaptiste Daroussin     else
359798e903e7SBaptiste Daroussin 	syntax_error(lineno, line, cptr);
359898e903e7SBaptiste Daroussin 
359998e903e7SBaptiste Daroussin     c = nextc();
3600b53bb29fSJung-uk Kim     if (isalpha(UCH(c)) || c == '_' || c == '.' || c == '$')
360198e903e7SBaptiste Daroussin 	bp = get_name();
360298e903e7SBaptiste Daroussin     else if (c == '\'' || c == '"')
360398e903e7SBaptiste Daroussin 	bp = get_literal();
360498e903e7SBaptiste Daroussin     else
360598e903e7SBaptiste Daroussin     {
360698e903e7SBaptiste Daroussin 	syntax_error(lineno, line, cptr);
3607c5b5d71aSJung-uk Kim 	/*NOTREACHED */
360898e903e7SBaptiste Daroussin     }
360998e903e7SBaptiste Daroussin 
361098e903e7SBaptiste Daroussin     if (rprec[nrules] != UNDEFINED && bp->prec != rprec[nrules])
361198e903e7SBaptiste Daroussin 	prec_redeclared();
361298e903e7SBaptiste Daroussin 
361398e903e7SBaptiste Daroussin     rprec[nrules] = bp->prec;
361498e903e7SBaptiste Daroussin     rassoc[nrules] = bp->assoc;
361598e903e7SBaptiste Daroussin     return (0);
361698e903e7SBaptiste Daroussin }
361798e903e7SBaptiste Daroussin 
361898e903e7SBaptiste Daroussin static void
read_grammar(void)361998e903e7SBaptiste Daroussin read_grammar(void)
362098e903e7SBaptiste Daroussin {
362198e903e7SBaptiste Daroussin     initialize_grammar();
362298e903e7SBaptiste Daroussin     advance_to_start();
362398e903e7SBaptiste Daroussin 
362498e903e7SBaptiste Daroussin     for (;;)
362598e903e7SBaptiste Daroussin     {
36268e022d3cSDag-Erling Smørgrav 	int c = nextc();
36278e022d3cSDag-Erling Smørgrav 
362898e903e7SBaptiste Daroussin 	if (c == EOF)
362998e903e7SBaptiste Daroussin 	    break;
3630b53bb29fSJung-uk Kim 	if (isalpha(UCH(c))
363198e903e7SBaptiste Daroussin 	    || c == '_'
363298e903e7SBaptiste Daroussin 	    || c == '.'
363398e903e7SBaptiste Daroussin 	    || c == '$'
363498e903e7SBaptiste Daroussin 	    || c == '\''
363598e903e7SBaptiste Daroussin 	    || c == '"')
36368e022d3cSDag-Erling Smørgrav 	{
363798e903e7SBaptiste Daroussin 	    add_symbol();
36388e022d3cSDag-Erling Smørgrav 	}
36398e022d3cSDag-Erling Smørgrav 	else if (c == L_CURL || c == '='
36400c8de5b0SBaptiste Daroussin #if defined(YYBTYACC)
36418e022d3cSDag-Erling Smørgrav 		 || (backtrack && c == L_BRAC)
36420c8de5b0SBaptiste Daroussin #endif
36438e022d3cSDag-Erling Smørgrav 	    )
36448e022d3cSDag-Erling Smørgrav 	{
364598e903e7SBaptiste Daroussin 	    copy_action();
36468e022d3cSDag-Erling Smørgrav 	}
364798e903e7SBaptiste Daroussin 	else if (c == '|')
364898e903e7SBaptiste Daroussin 	{
364998e903e7SBaptiste Daroussin 	    end_rule();
365098e903e7SBaptiste Daroussin 	    start_rule(plhs[nrules - 1], 0);
365198e903e7SBaptiste Daroussin 	    ++cptr;
365298e903e7SBaptiste Daroussin 	}
365398e903e7SBaptiste Daroussin 	else if (c == '%')
365498e903e7SBaptiste Daroussin 	{
365598e903e7SBaptiste Daroussin 	    if (mark_symbol())
365698e903e7SBaptiste Daroussin 		break;
365798e903e7SBaptiste Daroussin 	}
365898e903e7SBaptiste Daroussin 	else
365998e903e7SBaptiste Daroussin 	    syntax_error(lineno, line, cptr);
366098e903e7SBaptiste Daroussin     }
366198e903e7SBaptiste Daroussin     end_rule();
36620c8de5b0SBaptiste Daroussin #if defined(YYBTYACC)
36630c8de5b0SBaptiste Daroussin     if (goal->args > 0)
36640c8de5b0SBaptiste Daroussin 	start_requires_args(goal->name);
36650c8de5b0SBaptiste Daroussin #endif
366698e903e7SBaptiste Daroussin }
366798e903e7SBaptiste Daroussin 
366898e903e7SBaptiste Daroussin static void
free_tags(void)366998e903e7SBaptiste Daroussin free_tags(void)
367098e903e7SBaptiste Daroussin {
367198e903e7SBaptiste Daroussin     int i;
367298e903e7SBaptiste Daroussin 
367398e903e7SBaptiste Daroussin     if (tag_table == 0)
367498e903e7SBaptiste Daroussin 	return;
367598e903e7SBaptiste Daroussin 
367698e903e7SBaptiste Daroussin     for (i = 0; i < ntags; ++i)
367798e903e7SBaptiste Daroussin     {
367898e903e7SBaptiste Daroussin 	assert(tag_table[i]);
367998e903e7SBaptiste Daroussin 	FREE(tag_table[i]);
368098e903e7SBaptiste Daroussin     }
368198e903e7SBaptiste Daroussin     FREE(tag_table);
368298e903e7SBaptiste Daroussin }
368398e903e7SBaptiste Daroussin 
368498e903e7SBaptiste Daroussin static void
pack_names(void)368598e903e7SBaptiste Daroussin pack_names(void)
368698e903e7SBaptiste Daroussin {
368798e903e7SBaptiste Daroussin     bucket *bp;
36888e022d3cSDag-Erling Smørgrav     char *p;
36898e022d3cSDag-Erling Smørgrav     char *t;
369098e903e7SBaptiste Daroussin 
369198e903e7SBaptiste Daroussin     name_pool_size = 13;	/* 13 == sizeof("$end") + sizeof("$accept") */
369298e903e7SBaptiste Daroussin     for (bp = first_symbol; bp; bp = bp->next)
369398e903e7SBaptiste Daroussin 	name_pool_size += strlen(bp->name) + 1;
369498e903e7SBaptiste Daroussin 
36953e066022SBaptiste Daroussin     name_pool = TMALLOC(char, name_pool_size);
369698e903e7SBaptiste Daroussin     NO_SPACE(name_pool);
369798e903e7SBaptiste Daroussin 
369898e903e7SBaptiste Daroussin     strcpy(name_pool, "$accept");
369998e903e7SBaptiste Daroussin     strcpy(name_pool + 8, "$end");
370098e903e7SBaptiste Daroussin     t = name_pool + 13;
370198e903e7SBaptiste Daroussin     for (bp = first_symbol; bp; bp = bp->next)
370298e903e7SBaptiste Daroussin     {
37038e022d3cSDag-Erling Smørgrav 	char *s = bp->name;
37048e022d3cSDag-Erling Smørgrav 
370598e903e7SBaptiste Daroussin 	p = t;
370698e903e7SBaptiste Daroussin 	while ((*t++ = *s++) != 0)
370798e903e7SBaptiste Daroussin 	    continue;
370898e903e7SBaptiste Daroussin 	FREE(bp->name);
370998e903e7SBaptiste Daroussin 	bp->name = p;
371098e903e7SBaptiste Daroussin     }
371198e903e7SBaptiste Daroussin }
371298e903e7SBaptiste Daroussin 
371398e903e7SBaptiste Daroussin static void
check_symbols(void)371498e903e7SBaptiste Daroussin check_symbols(void)
371598e903e7SBaptiste Daroussin {
371698e903e7SBaptiste Daroussin     bucket *bp;
371798e903e7SBaptiste Daroussin 
371898e903e7SBaptiste Daroussin     if (goal->class == UNKNOWN)
371998e903e7SBaptiste Daroussin 	undefined_goal(goal->name);
372098e903e7SBaptiste Daroussin 
372198e903e7SBaptiste Daroussin     for (bp = first_symbol; bp; bp = bp->next)
372298e903e7SBaptiste Daroussin     {
372398e903e7SBaptiste Daroussin 	if (bp->class == UNKNOWN)
372498e903e7SBaptiste Daroussin 	{
372598e903e7SBaptiste Daroussin 	    undefined_symbol_warning(bp->name);
372698e903e7SBaptiste Daroussin 	    bp->class = TERM;
372798e903e7SBaptiste Daroussin 	}
372898e903e7SBaptiste Daroussin     }
372998e903e7SBaptiste Daroussin }
373098e903e7SBaptiste Daroussin 
373198e903e7SBaptiste Daroussin static void
protect_string(char * src,char ** des)373298e903e7SBaptiste Daroussin protect_string(char *src, char **des)
373398e903e7SBaptiste Daroussin {
373498e903e7SBaptiste Daroussin     *des = src;
373598e903e7SBaptiste Daroussin     if (src)
373698e903e7SBaptiste Daroussin     {
37378e022d3cSDag-Erling Smørgrav 	char *s;
37388e022d3cSDag-Erling Smørgrav 	char *d;
37398e022d3cSDag-Erling Smørgrav 
37408e022d3cSDag-Erling Smørgrav 	unsigned len = 1;
37418e022d3cSDag-Erling Smørgrav 
374298e903e7SBaptiste Daroussin 	s = src;
374398e903e7SBaptiste Daroussin 	while (*s)
374498e903e7SBaptiste Daroussin 	{
374598e903e7SBaptiste Daroussin 	    if ('\\' == *s || '"' == *s)
374698e903e7SBaptiste Daroussin 		len++;
374798e903e7SBaptiste Daroussin 	    s++;
374898e903e7SBaptiste Daroussin 	    len++;
374998e903e7SBaptiste Daroussin 	}
375098e903e7SBaptiste Daroussin 
37513e066022SBaptiste Daroussin 	*des = d = TMALLOC(char, len);
375298e903e7SBaptiste Daroussin 	NO_SPACE(d);
375398e903e7SBaptiste Daroussin 
375498e903e7SBaptiste Daroussin 	s = src;
375598e903e7SBaptiste Daroussin 	while (*s)
375698e903e7SBaptiste Daroussin 	{
375798e903e7SBaptiste Daroussin 	    if ('\\' == *s || '"' == *s)
375898e903e7SBaptiste Daroussin 		*d++ = '\\';
375998e903e7SBaptiste Daroussin 	    *d++ = *s++;
376098e903e7SBaptiste Daroussin 	}
376198e903e7SBaptiste Daroussin 	*d = '\0';
376298e903e7SBaptiste Daroussin     }
376398e903e7SBaptiste Daroussin }
376498e903e7SBaptiste Daroussin 
376598e903e7SBaptiste Daroussin static void
pack_symbols(void)376698e903e7SBaptiste Daroussin pack_symbols(void)
376798e903e7SBaptiste Daroussin {
376898e903e7SBaptiste Daroussin     bucket *bp;
376998e903e7SBaptiste Daroussin     bucket **v;
377098e903e7SBaptiste Daroussin     Value_t i, j, k, n;
37710c8de5b0SBaptiste Daroussin #if defined(YYBTYACC)
37720c8de5b0SBaptiste Daroussin     Value_t max_tok_pval;
37730c8de5b0SBaptiste Daroussin #endif
377498e903e7SBaptiste Daroussin 
377598e903e7SBaptiste Daroussin     nsyms = 2;
377698e903e7SBaptiste Daroussin     ntokens = 1;
377798e903e7SBaptiste Daroussin     for (bp = first_symbol; bp; bp = bp->next)
377898e903e7SBaptiste Daroussin     {
377998e903e7SBaptiste Daroussin 	++nsyms;
378098e903e7SBaptiste Daroussin 	if (bp->class == TERM)
378198e903e7SBaptiste Daroussin 	    ++ntokens;
378298e903e7SBaptiste Daroussin     }
378398e903e7SBaptiste Daroussin     start_symbol = (Value_t)ntokens;
37840c8de5b0SBaptiste Daroussin     nvars = (Value_t)(nsyms - ntokens);
378598e903e7SBaptiste Daroussin 
37863e066022SBaptiste Daroussin     symbol_name = TMALLOC(char *, nsyms);
378798e903e7SBaptiste Daroussin     NO_SPACE(symbol_name);
378898e903e7SBaptiste Daroussin 
37893e066022SBaptiste Daroussin     symbol_value = TMALLOC(Value_t, nsyms);
379098e903e7SBaptiste Daroussin     NO_SPACE(symbol_value);
379198e903e7SBaptiste Daroussin 
37920c8de5b0SBaptiste Daroussin     symbol_prec = TMALLOC(Value_t, nsyms);
379398e903e7SBaptiste Daroussin     NO_SPACE(symbol_prec);
379498e903e7SBaptiste Daroussin 
37953e066022SBaptiste Daroussin     symbol_assoc = TMALLOC(char, nsyms);
379698e903e7SBaptiste Daroussin     NO_SPACE(symbol_assoc);
379798e903e7SBaptiste Daroussin 
37980c8de5b0SBaptiste Daroussin #if defined(YYBTYACC)
37990c8de5b0SBaptiste Daroussin     symbol_pval = TMALLOC(Value_t, nsyms);
38000c8de5b0SBaptiste Daroussin     NO_SPACE(symbol_pval);
38010c8de5b0SBaptiste Daroussin 
38020c8de5b0SBaptiste Daroussin     if (destructor)
38030c8de5b0SBaptiste Daroussin     {
38040c8de5b0SBaptiste Daroussin 	symbol_destructor = CALLOC(sizeof(char *), nsyms);
38050c8de5b0SBaptiste Daroussin 	NO_SPACE(symbol_destructor);
38060c8de5b0SBaptiste Daroussin 
38070c8de5b0SBaptiste Daroussin 	symbol_type_tag = CALLOC(sizeof(char *), nsyms);
38080c8de5b0SBaptiste Daroussin 	NO_SPACE(symbol_type_tag);
38090c8de5b0SBaptiste Daroussin     }
38100c8de5b0SBaptiste Daroussin #endif
38110c8de5b0SBaptiste Daroussin 
38123e066022SBaptiste Daroussin     v = TMALLOC(bucket *, nsyms);
381398e903e7SBaptiste Daroussin     NO_SPACE(v);
381498e903e7SBaptiste Daroussin 
381598e903e7SBaptiste Daroussin     v[0] = 0;
381698e903e7SBaptiste Daroussin     v[start_symbol] = 0;
381798e903e7SBaptiste Daroussin 
381898e903e7SBaptiste Daroussin     i = 1;
381998e903e7SBaptiste Daroussin     j = (Value_t)(start_symbol + 1);
382098e903e7SBaptiste Daroussin     for (bp = first_symbol; bp; bp = bp->next)
382198e903e7SBaptiste Daroussin     {
382298e903e7SBaptiste Daroussin 	if (bp->class == TERM)
382398e903e7SBaptiste Daroussin 	    v[i++] = bp;
382498e903e7SBaptiste Daroussin 	else
382598e903e7SBaptiste Daroussin 	    v[j++] = bp;
382698e903e7SBaptiste Daroussin     }
382798e903e7SBaptiste Daroussin     assert(i == ntokens && j == nsyms);
382898e903e7SBaptiste Daroussin 
382998e903e7SBaptiste Daroussin     for (i = 1; i < ntokens; ++i)
383098e903e7SBaptiste Daroussin 	v[i]->index = i;
383198e903e7SBaptiste Daroussin 
383298e903e7SBaptiste Daroussin     goal->index = (Index_t)(start_symbol + 1);
383398e903e7SBaptiste Daroussin     k = (Value_t)(start_symbol + 2);
383498e903e7SBaptiste Daroussin     while (++i < nsyms)
383598e903e7SBaptiste Daroussin 	if (v[i] != goal)
383698e903e7SBaptiste Daroussin 	{
383798e903e7SBaptiste Daroussin 	    v[i]->index = k;
383898e903e7SBaptiste Daroussin 	    ++k;
383998e903e7SBaptiste Daroussin 	}
384098e903e7SBaptiste Daroussin 
384198e903e7SBaptiste Daroussin     goal->value = 0;
384298e903e7SBaptiste Daroussin     k = 1;
384398e903e7SBaptiste Daroussin     for (i = (Value_t)(start_symbol + 1); i < nsyms; ++i)
384498e903e7SBaptiste Daroussin     {
384598e903e7SBaptiste Daroussin 	if (v[i] != goal)
384698e903e7SBaptiste Daroussin 	{
384798e903e7SBaptiste Daroussin 	    v[i]->value = k;
384898e903e7SBaptiste Daroussin 	    ++k;
384998e903e7SBaptiste Daroussin 	}
385098e903e7SBaptiste Daroussin     }
385198e903e7SBaptiste Daroussin 
385298e903e7SBaptiste Daroussin     k = 0;
385398e903e7SBaptiste Daroussin     for (i = 1; i < ntokens; ++i)
385498e903e7SBaptiste Daroussin     {
385598e903e7SBaptiste Daroussin 	n = v[i]->value;
385698e903e7SBaptiste Daroussin 	if (n > 256)
385798e903e7SBaptiste Daroussin 	{
385898e903e7SBaptiste Daroussin 	    for (j = k++; j > 0 && symbol_value[j - 1] > n; --j)
385998e903e7SBaptiste Daroussin 		symbol_value[j] = symbol_value[j - 1];
386098e903e7SBaptiste Daroussin 	    symbol_value[j] = n;
386198e903e7SBaptiste Daroussin 	}
386298e903e7SBaptiste Daroussin     }
386398e903e7SBaptiste Daroussin 
386498e903e7SBaptiste Daroussin     assert(v[1] != 0);
386598e903e7SBaptiste Daroussin 
386698e903e7SBaptiste Daroussin     if (v[1]->value == UNDEFINED)
386798e903e7SBaptiste Daroussin 	v[1]->value = 256;
386898e903e7SBaptiste Daroussin 
386998e903e7SBaptiste Daroussin     j = 0;
387098e903e7SBaptiste Daroussin     n = 257;
387198e903e7SBaptiste Daroussin     for (i = 2; i < ntokens; ++i)
387298e903e7SBaptiste Daroussin     {
387398e903e7SBaptiste Daroussin 	if (v[i]->value == UNDEFINED)
387498e903e7SBaptiste Daroussin 	{
387598e903e7SBaptiste Daroussin 	    while (j < k && n == symbol_value[j])
387698e903e7SBaptiste Daroussin 	    {
387798e903e7SBaptiste Daroussin 		while (++j < k && n == symbol_value[j])
387898e903e7SBaptiste Daroussin 		    continue;
387998e903e7SBaptiste Daroussin 		++n;
388098e903e7SBaptiste Daroussin 	    }
388198e903e7SBaptiste Daroussin 	    v[i]->value = n;
388298e903e7SBaptiste Daroussin 	    ++n;
388398e903e7SBaptiste Daroussin 	}
388498e903e7SBaptiste Daroussin     }
388598e903e7SBaptiste Daroussin 
388698e903e7SBaptiste Daroussin     symbol_name[0] = name_pool + 8;
388798e903e7SBaptiste Daroussin     symbol_value[0] = 0;
388898e903e7SBaptiste Daroussin     symbol_prec[0] = 0;
388998e903e7SBaptiste Daroussin     symbol_assoc[0] = TOKEN;
38900c8de5b0SBaptiste Daroussin #if defined(YYBTYACC)
38910c8de5b0SBaptiste Daroussin     symbol_pval[0] = 0;
38920c8de5b0SBaptiste Daroussin     max_tok_pval = 0;
38930c8de5b0SBaptiste Daroussin #endif
389498e903e7SBaptiste Daroussin     for (i = 1; i < ntokens; ++i)
389598e903e7SBaptiste Daroussin     {
389698e903e7SBaptiste Daroussin 	symbol_name[i] = v[i]->name;
389798e903e7SBaptiste Daroussin 	symbol_value[i] = v[i]->value;
389898e903e7SBaptiste Daroussin 	symbol_prec[i] = v[i]->prec;
389998e903e7SBaptiste Daroussin 	symbol_assoc[i] = v[i]->assoc;
39000c8de5b0SBaptiste Daroussin #if defined(YYBTYACC)
39010c8de5b0SBaptiste Daroussin 	symbol_pval[i] = v[i]->value;
39020c8de5b0SBaptiste Daroussin 	if (symbol_pval[i] > max_tok_pval)
39030c8de5b0SBaptiste Daroussin 	    max_tok_pval = symbol_pval[i];
39040c8de5b0SBaptiste Daroussin 	if (destructor)
39050c8de5b0SBaptiste Daroussin 	{
39060c8de5b0SBaptiste Daroussin 	    symbol_destructor[i] = v[i]->destructor;
39070c8de5b0SBaptiste Daroussin 	    symbol_type_tag[i] = v[i]->tag;
39080c8de5b0SBaptiste Daroussin 	}
39090c8de5b0SBaptiste Daroussin #endif
391098e903e7SBaptiste Daroussin     }
391198e903e7SBaptiste Daroussin     symbol_name[start_symbol] = name_pool;
391298e903e7SBaptiste Daroussin     symbol_value[start_symbol] = -1;
391398e903e7SBaptiste Daroussin     symbol_prec[start_symbol] = 0;
391498e903e7SBaptiste Daroussin     symbol_assoc[start_symbol] = TOKEN;
39150c8de5b0SBaptiste Daroussin #if defined(YYBTYACC)
39160c8de5b0SBaptiste Daroussin     symbol_pval[start_symbol] = (Value_t)(max_tok_pval + 1);
39170c8de5b0SBaptiste Daroussin #endif
391898e903e7SBaptiste Daroussin     for (++i; i < nsyms; ++i)
391998e903e7SBaptiste Daroussin     {
392098e903e7SBaptiste Daroussin 	k = v[i]->index;
392198e903e7SBaptiste Daroussin 	symbol_name[k] = v[i]->name;
392298e903e7SBaptiste Daroussin 	symbol_value[k] = v[i]->value;
392398e903e7SBaptiste Daroussin 	symbol_prec[k] = v[i]->prec;
392498e903e7SBaptiste Daroussin 	symbol_assoc[k] = v[i]->assoc;
39250c8de5b0SBaptiste Daroussin #if defined(YYBTYACC)
39260c8de5b0SBaptiste Daroussin 	symbol_pval[k] = (Value_t)((max_tok_pval + 1) + v[i]->value + 1);
39270c8de5b0SBaptiste Daroussin 	if (destructor)
39280c8de5b0SBaptiste Daroussin 	{
39290c8de5b0SBaptiste Daroussin 	    symbol_destructor[k] = v[i]->destructor;
39300c8de5b0SBaptiste Daroussin 	    symbol_type_tag[k] = v[i]->tag;
39310c8de5b0SBaptiste Daroussin 	}
39320c8de5b0SBaptiste Daroussin #endif
393398e903e7SBaptiste Daroussin     }
393498e903e7SBaptiste Daroussin 
393598e903e7SBaptiste Daroussin     if (gflag)
393698e903e7SBaptiste Daroussin     {
39373e066022SBaptiste Daroussin 	symbol_pname = TMALLOC(char *, nsyms);
393898e903e7SBaptiste Daroussin 	NO_SPACE(symbol_pname);
393998e903e7SBaptiste Daroussin 
394098e903e7SBaptiste Daroussin 	for (i = 0; i < nsyms; ++i)
394198e903e7SBaptiste Daroussin 	    protect_string(symbol_name[i], &(symbol_pname[i]));
394298e903e7SBaptiste Daroussin     }
394398e903e7SBaptiste Daroussin 
394498e903e7SBaptiste Daroussin     FREE(v);
394598e903e7SBaptiste Daroussin }
394698e903e7SBaptiste Daroussin 
394798e903e7SBaptiste Daroussin static void
pack_grammar(void)394898e903e7SBaptiste Daroussin pack_grammar(void)
394998e903e7SBaptiste Daroussin {
395098e903e7SBaptiste Daroussin     int i;
395198e903e7SBaptiste Daroussin     Value_t j;
395298e903e7SBaptiste Daroussin 
39533e066022SBaptiste Daroussin     ritem = TMALLOC(Value_t, nitems);
395498e903e7SBaptiste Daroussin     NO_SPACE(ritem);
395598e903e7SBaptiste Daroussin 
39563e066022SBaptiste Daroussin     rlhs = TMALLOC(Value_t, nrules);
395798e903e7SBaptiste Daroussin     NO_SPACE(rlhs);
395898e903e7SBaptiste Daroussin 
39593e066022SBaptiste Daroussin     rrhs = TMALLOC(Value_t, nrules + 1);
396098e903e7SBaptiste Daroussin     NO_SPACE(rrhs);
396198e903e7SBaptiste Daroussin 
39623e066022SBaptiste Daroussin     rprec = TREALLOC(Value_t, rprec, nrules);
396398e903e7SBaptiste Daroussin     NO_SPACE(rprec);
396498e903e7SBaptiste Daroussin 
39653e066022SBaptiste Daroussin     rassoc = TREALLOC(Assoc_t, rassoc, nrules);
396698e903e7SBaptiste Daroussin     NO_SPACE(rassoc);
396798e903e7SBaptiste Daroussin 
396898e903e7SBaptiste Daroussin     ritem[0] = -1;
396998e903e7SBaptiste Daroussin     ritem[1] = goal->index;
397098e903e7SBaptiste Daroussin     ritem[2] = 0;
397198e903e7SBaptiste Daroussin     ritem[3] = -2;
397298e903e7SBaptiste Daroussin     rlhs[0] = 0;
397398e903e7SBaptiste Daroussin     rlhs[1] = 0;
397498e903e7SBaptiste Daroussin     rlhs[2] = start_symbol;
397598e903e7SBaptiste Daroussin     rrhs[0] = 0;
397698e903e7SBaptiste Daroussin     rrhs[1] = 0;
397798e903e7SBaptiste Daroussin     rrhs[2] = 1;
397898e903e7SBaptiste Daroussin 
397998e903e7SBaptiste Daroussin     j = 4;
398098e903e7SBaptiste Daroussin     for (i = 3; i < nrules; ++i)
398198e903e7SBaptiste Daroussin     {
39828e022d3cSDag-Erling Smørgrav 	Assoc_t assoc;
39838e022d3cSDag-Erling Smørgrav 	Value_t prec2;
39848e022d3cSDag-Erling Smørgrav 
39850c8de5b0SBaptiste Daroussin #if defined(YYBTYACC)
39860c8de5b0SBaptiste Daroussin 	if (plhs[i]->args > 0)
39870c8de5b0SBaptiste Daroussin 	{
39880c8de5b0SBaptiste Daroussin 	    if (plhs[i]->argnames)
39890c8de5b0SBaptiste Daroussin 	    {
39900c8de5b0SBaptiste Daroussin 		FREE(plhs[i]->argnames);
39910c8de5b0SBaptiste Daroussin 		plhs[i]->argnames = NULL;
39920c8de5b0SBaptiste Daroussin 	    }
39930c8de5b0SBaptiste Daroussin 	    if (plhs[i]->argtags)
39940c8de5b0SBaptiste Daroussin 	    {
39950c8de5b0SBaptiste Daroussin 		FREE(plhs[i]->argtags);
39960c8de5b0SBaptiste Daroussin 		plhs[i]->argtags = NULL;
39970c8de5b0SBaptiste Daroussin 	    }
39980c8de5b0SBaptiste Daroussin 	}
39990c8de5b0SBaptiste Daroussin #endif /* defined(YYBTYACC) */
400098e903e7SBaptiste Daroussin 	rlhs[i] = plhs[i]->index;
400198e903e7SBaptiste Daroussin 	rrhs[i] = j;
400298e903e7SBaptiste Daroussin 	assoc = TOKEN;
400398e903e7SBaptiste Daroussin 	prec2 = 0;
400498e903e7SBaptiste Daroussin 	while (pitem[j])
400598e903e7SBaptiste Daroussin 	{
400698e903e7SBaptiste Daroussin 	    ritem[j] = pitem[j]->index;
400798e903e7SBaptiste Daroussin 	    if (pitem[j]->class == TERM)
400898e903e7SBaptiste Daroussin 	    {
400998e903e7SBaptiste Daroussin 		prec2 = pitem[j]->prec;
401098e903e7SBaptiste Daroussin 		assoc = pitem[j]->assoc;
401198e903e7SBaptiste Daroussin 	    }
401298e903e7SBaptiste Daroussin 	    ++j;
401398e903e7SBaptiste Daroussin 	}
401498e903e7SBaptiste Daroussin 	ritem[j] = (Value_t)-i;
401598e903e7SBaptiste Daroussin 	++j;
401698e903e7SBaptiste Daroussin 	if (rprec[i] == UNDEFINED)
401798e903e7SBaptiste Daroussin 	{
401898e903e7SBaptiste Daroussin 	    rprec[i] = prec2;
401998e903e7SBaptiste Daroussin 	    rassoc[i] = assoc;
402098e903e7SBaptiste Daroussin 	}
402198e903e7SBaptiste Daroussin     }
402298e903e7SBaptiste Daroussin     rrhs[i] = j;
402398e903e7SBaptiste Daroussin 
402498e903e7SBaptiste Daroussin     FREE(plhs);
402598e903e7SBaptiste Daroussin     FREE(pitem);
40260c8de5b0SBaptiste Daroussin #if defined(YYBTYACC)
40270c8de5b0SBaptiste Daroussin     clean_arg_cache();
40280c8de5b0SBaptiste Daroussin #endif
402998e903e7SBaptiste Daroussin }
403098e903e7SBaptiste Daroussin 
403198e903e7SBaptiste Daroussin static void
print_grammar(void)403298e903e7SBaptiste Daroussin print_grammar(void)
403398e903e7SBaptiste Daroussin {
403498e903e7SBaptiste Daroussin     int i, k;
403598e903e7SBaptiste Daroussin     size_t j, spacing = 0;
403698e903e7SBaptiste Daroussin     FILE *f = verbose_file;
403798e903e7SBaptiste Daroussin 
403898e903e7SBaptiste Daroussin     if (!vflag)
403998e903e7SBaptiste Daroussin 	return;
404098e903e7SBaptiste Daroussin 
404198e903e7SBaptiste Daroussin     k = 1;
404298e903e7SBaptiste Daroussin     for (i = 2; i < nrules; ++i)
404398e903e7SBaptiste Daroussin     {
404498e903e7SBaptiste Daroussin 	if (rlhs[i] != rlhs[i - 1])
404598e903e7SBaptiste Daroussin 	{
404698e903e7SBaptiste Daroussin 	    if (i != 2)
404798e903e7SBaptiste Daroussin 		fprintf(f, "\n");
404898e903e7SBaptiste Daroussin 	    fprintf(f, "%4d  %s :", i - 2, symbol_name[rlhs[i]]);
404998e903e7SBaptiste Daroussin 	    spacing = strlen(symbol_name[rlhs[i]]) + 1;
405098e903e7SBaptiste Daroussin 	}
405198e903e7SBaptiste Daroussin 	else
405298e903e7SBaptiste Daroussin 	{
405398e903e7SBaptiste Daroussin 	    fprintf(f, "%4d  ", i - 2);
405498e903e7SBaptiste Daroussin 	    j = spacing;
405598e903e7SBaptiste Daroussin 	    while (j-- != 0)
405698e903e7SBaptiste Daroussin 		putc(' ', f);
405798e903e7SBaptiste Daroussin 	    putc('|', f);
405898e903e7SBaptiste Daroussin 	}
405998e903e7SBaptiste Daroussin 
406098e903e7SBaptiste Daroussin 	while (ritem[k] >= 0)
406198e903e7SBaptiste Daroussin 	{
406298e903e7SBaptiste Daroussin 	    fprintf(f, " %s", symbol_name[ritem[k]]);
406398e903e7SBaptiste Daroussin 	    ++k;
406498e903e7SBaptiste Daroussin 	}
406598e903e7SBaptiste Daroussin 	++k;
406698e903e7SBaptiste Daroussin 	putc('\n', f);
406798e903e7SBaptiste Daroussin     }
406898e903e7SBaptiste Daroussin }
406998e903e7SBaptiste Daroussin 
40700c8de5b0SBaptiste Daroussin #if defined(YYBTYACC)
40710c8de5b0SBaptiste Daroussin static void
finalize_destructors(void)40720c8de5b0SBaptiste Daroussin finalize_destructors(void)
40730c8de5b0SBaptiste Daroussin {
40740c8de5b0SBaptiste Daroussin     int i;
40750c8de5b0SBaptiste Daroussin     bucket *bp;
40760c8de5b0SBaptiste Daroussin 
40770c8de5b0SBaptiste Daroussin     for (i = 2; i < nsyms; ++i)
40780c8de5b0SBaptiste Daroussin     {
40798e022d3cSDag-Erling Smørgrav 	char *tag = symbol_type_tag[i];
40808e022d3cSDag-Erling Smørgrav 
40810c8de5b0SBaptiste Daroussin 	if (symbol_destructor[i] == NULL)
40820c8de5b0SBaptiste Daroussin 	{
40830c8de5b0SBaptiste Daroussin 	    if (tag == NULL)
40840c8de5b0SBaptiste Daroussin 	    {			/* use <> destructor, if there is one */
40850c8de5b0SBaptiste Daroussin 		if ((bp = default_destructor[UNTYPED_DEFAULT]) != NULL)
40860c8de5b0SBaptiste Daroussin 		{
40870c8de5b0SBaptiste Daroussin 		    symbol_destructor[i] = TMALLOC(char,
40880c8de5b0SBaptiste Daroussin 						   strlen(bp->destructor) + 1);
40890c8de5b0SBaptiste Daroussin 		    NO_SPACE(symbol_destructor[i]);
40900c8de5b0SBaptiste Daroussin 		    strcpy(symbol_destructor[i], bp->destructor);
40910c8de5b0SBaptiste Daroussin 		}
40920c8de5b0SBaptiste Daroussin 	    }
40930c8de5b0SBaptiste Daroussin 	    else
40940c8de5b0SBaptiste Daroussin 	    {			/* use type destructor for this tag, if there is one */
40950c8de5b0SBaptiste Daroussin 		bp = lookup_type_destructor(tag);
40960c8de5b0SBaptiste Daroussin 		if (bp->destructor != NULL)
40970c8de5b0SBaptiste Daroussin 		{
40980c8de5b0SBaptiste Daroussin 		    symbol_destructor[i] = TMALLOC(char,
40990c8de5b0SBaptiste Daroussin 						   strlen(bp->destructor) + 1);
41000c8de5b0SBaptiste Daroussin 		    NO_SPACE(symbol_destructor[i]);
41010c8de5b0SBaptiste Daroussin 		    strcpy(symbol_destructor[i], bp->destructor);
41020c8de5b0SBaptiste Daroussin 		}
41030c8de5b0SBaptiste Daroussin 		else
41040c8de5b0SBaptiste Daroussin 		{		/* use <*> destructor, if there is one */
41050c8de5b0SBaptiste Daroussin 		    if ((bp = default_destructor[TYPED_DEFAULT]) != NULL)
41060c8de5b0SBaptiste Daroussin 			/* replace "$$" with "(*val).tag" in destructor code */
41070c8de5b0SBaptiste Daroussin 			symbol_destructor[i]
41080c8de5b0SBaptiste Daroussin 			    = process_destructor_XX(bp->destructor, tag);
41090c8de5b0SBaptiste Daroussin 		}
41100c8de5b0SBaptiste Daroussin 	    }
41110c8de5b0SBaptiste Daroussin 	}
41120c8de5b0SBaptiste Daroussin 	else
41130c8de5b0SBaptiste Daroussin 	{			/* replace "$$" with "(*val)[.tag]" in destructor code */
41148e022d3cSDag-Erling Smørgrav 	    char *destructor_source = symbol_destructor[i];
41150c8de5b0SBaptiste Daroussin 	    symbol_destructor[i]
41168e022d3cSDag-Erling Smørgrav 		= process_destructor_XX(destructor_source, tag);
41178e022d3cSDag-Erling Smørgrav 	    FREE(destructor_source);
41180c8de5b0SBaptiste Daroussin 	}
41190c8de5b0SBaptiste Daroussin     }
41200c8de5b0SBaptiste Daroussin     /* 'symbol_type_tag[]' elements are freed by 'free_tags()' */
41210c8de5b0SBaptiste Daroussin     DO_FREE(symbol_type_tag);	/* no longer needed */
41220c8de5b0SBaptiste Daroussin     if ((bp = default_destructor[UNTYPED_DEFAULT]) != NULL)
41230c8de5b0SBaptiste Daroussin     {
41240c8de5b0SBaptiste Daroussin 	FREE(bp->name);
41250c8de5b0SBaptiste Daroussin 	/* 'bp->tag' is a static value, don't free */
41260c8de5b0SBaptiste Daroussin 	FREE(bp->destructor);
41270c8de5b0SBaptiste Daroussin 	FREE(bp);
41280c8de5b0SBaptiste Daroussin     }
41290c8de5b0SBaptiste Daroussin     if ((bp = default_destructor[TYPED_DEFAULT]) != NULL)
41300c8de5b0SBaptiste Daroussin     {
41310c8de5b0SBaptiste Daroussin 	FREE(bp->name);
41320c8de5b0SBaptiste Daroussin 	/* 'bp->tag' is a static value, don't free */
41330c8de5b0SBaptiste Daroussin 	FREE(bp->destructor);
41340c8de5b0SBaptiste Daroussin 	FREE(bp);
41350c8de5b0SBaptiste Daroussin     }
41360c8de5b0SBaptiste Daroussin     if ((bp = default_destructor[TYPE_SPECIFIED]) != NULL)
41370c8de5b0SBaptiste Daroussin     {
41380c8de5b0SBaptiste Daroussin 	bucket *p;
41390c8de5b0SBaptiste Daroussin 	for (; bp; bp = p)
41400c8de5b0SBaptiste Daroussin 	{
41410c8de5b0SBaptiste Daroussin 	    p = bp->link;
41420c8de5b0SBaptiste Daroussin 	    FREE(bp->name);
41430c8de5b0SBaptiste Daroussin 	    /* 'bp->tag' freed by 'free_tags()' */
41440c8de5b0SBaptiste Daroussin 	    FREE(bp->destructor);
41450c8de5b0SBaptiste Daroussin 	    FREE(bp);
41460c8de5b0SBaptiste Daroussin 	}
41470c8de5b0SBaptiste Daroussin     }
41480c8de5b0SBaptiste Daroussin }
41490c8de5b0SBaptiste Daroussin #endif /* defined(YYBTYACC) */
41500c8de5b0SBaptiste Daroussin 
415198e903e7SBaptiste Daroussin void
reader(void)415298e903e7SBaptiste Daroussin reader(void)
415398e903e7SBaptiste Daroussin {
415498e903e7SBaptiste Daroussin     write_section(code_file, banner);
415598e903e7SBaptiste Daroussin     create_symbol_table();
415698e903e7SBaptiste Daroussin     read_declarations();
415798e903e7SBaptiste Daroussin     read_grammar();
415898e903e7SBaptiste Daroussin     free_symbol_table();
415998e903e7SBaptiste Daroussin     pack_names();
416098e903e7SBaptiste Daroussin     check_symbols();
416198e903e7SBaptiste Daroussin     pack_symbols();
416298e903e7SBaptiste Daroussin     pack_grammar();
416398e903e7SBaptiste Daroussin     free_symbols();
416498e903e7SBaptiste Daroussin     print_grammar();
41650c8de5b0SBaptiste Daroussin #if defined(YYBTYACC)
41660c8de5b0SBaptiste Daroussin     if (destructor)
41670c8de5b0SBaptiste Daroussin 	finalize_destructors();
41680c8de5b0SBaptiste Daroussin #endif
41690c8de5b0SBaptiste Daroussin     free_tags();
417098e903e7SBaptiste Daroussin }
417198e903e7SBaptiste Daroussin 
417298e903e7SBaptiste Daroussin #ifdef NO_LEAKS
417398e903e7SBaptiste Daroussin static param *
free_declarations(param * list)417498e903e7SBaptiste Daroussin free_declarations(param *list)
417598e903e7SBaptiste Daroussin {
417698e903e7SBaptiste Daroussin     while (list != 0)
417798e903e7SBaptiste Daroussin     {
417898e903e7SBaptiste Daroussin 	param *next = list->next;
417998e903e7SBaptiste Daroussin 	free(list->type);
418098e903e7SBaptiste Daroussin 	free(list->name);
418198e903e7SBaptiste Daroussin 	free(list->type2);
418298e903e7SBaptiste Daroussin 	free(list);
418398e903e7SBaptiste Daroussin 	list = next;
418498e903e7SBaptiste Daroussin     }
418598e903e7SBaptiste Daroussin     return list;
418698e903e7SBaptiste Daroussin }
418798e903e7SBaptiste Daroussin 
418898e903e7SBaptiste Daroussin void
reader_leaks(void)418998e903e7SBaptiste Daroussin reader_leaks(void)
419098e903e7SBaptiste Daroussin {
419198e903e7SBaptiste Daroussin     lex_param = free_declarations(lex_param);
419298e903e7SBaptiste Daroussin     parse_param = free_declarations(parse_param);
419398e903e7SBaptiste Daroussin 
419498e903e7SBaptiste Daroussin     DO_FREE(line);
419598e903e7SBaptiste Daroussin     DO_FREE(rrhs);
419698e903e7SBaptiste Daroussin     DO_FREE(rlhs);
419798e903e7SBaptiste Daroussin     DO_FREE(rprec);
419898e903e7SBaptiste Daroussin     DO_FREE(ritem);
419998e903e7SBaptiste Daroussin     DO_FREE(rassoc);
420098e903e7SBaptiste Daroussin     DO_FREE(cache);
420198e903e7SBaptiste Daroussin     DO_FREE(name_pool);
420298e903e7SBaptiste Daroussin     DO_FREE(symbol_name);
420398e903e7SBaptiste Daroussin     DO_FREE(symbol_prec);
420498e903e7SBaptiste Daroussin     DO_FREE(symbol_assoc);
420598e903e7SBaptiste Daroussin     DO_FREE(symbol_value);
42060c8de5b0SBaptiste Daroussin #if defined(YYBTYACC)
42070c8de5b0SBaptiste Daroussin     DO_FREE(symbol_pval);
42080c8de5b0SBaptiste Daroussin     DO_FREE(symbol_destructor);
42090c8de5b0SBaptiste Daroussin     DO_FREE(symbol_type_tag);
42100c8de5b0SBaptiste Daroussin #endif
421198e903e7SBaptiste Daroussin }
421298e903e7SBaptiste Daroussin #endif
4213