1*e4b17023SJohn Marino /* Process source files and output type information.
2*e4b17023SJohn Marino    Copyright (C) 2006, 2007, 2010 Free Software Foundation, Inc.
3*e4b17023SJohn Marino 
4*e4b17023SJohn Marino    This file is part of GCC.
5*e4b17023SJohn Marino 
6*e4b17023SJohn Marino    GCC is free software; you can redistribute it and/or modify it under
7*e4b17023SJohn Marino    the terms of the GNU General Public License as published by the Free
8*e4b17023SJohn Marino    Software Foundation; either version 3, or (at your option) any later
9*e4b17023SJohn Marino    version.
10*e4b17023SJohn Marino 
11*e4b17023SJohn Marino    GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12*e4b17023SJohn Marino    WARRANTY; without even the implied warranty of MERCHANTABILITY or
13*e4b17023SJohn Marino    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14*e4b17023SJohn Marino    for more details.
15*e4b17023SJohn Marino 
16*e4b17023SJohn Marino    You should have received a copy of the GNU General Public License
17*e4b17023SJohn Marino    along with GCC; see the file COPYING3.  If not see
18*e4b17023SJohn Marino    <http://www.gnu.org/licenses/>.  */
19*e4b17023SJohn Marino 
20*e4b17023SJohn Marino #ifdef GENERATOR_FILE
21*e4b17023SJohn Marino #include "bconfig.h"
22*e4b17023SJohn Marino #else
23*e4b17023SJohn Marino #include "config.h"
24*e4b17023SJohn Marino #endif
25*e4b17023SJohn Marino #include "system.h"
26*e4b17023SJohn Marino #include "gengtype.h"
27*e4b17023SJohn Marino 
28*e4b17023SJohn Marino /* This is a simple recursive-descent parser which understands a subset of
29*e4b17023SJohn Marino    the C type grammar.
30*e4b17023SJohn Marino 
31*e4b17023SJohn Marino    Rule functions are suffixed _seq if they scan a sequence of items;
32*e4b17023SJohn Marino    _opt if they may consume zero tokens; _seqopt if both are true.  The
33*e4b17023SJohn Marino    "consume_" prefix indicates that a sequence of tokens is parsed for
34*e4b17023SJohn Marino    syntactic correctness and then thrown away.  */
35*e4b17023SJohn Marino 
36*e4b17023SJohn Marino /* Simple one-token lookahead mechanism.  */
37*e4b17023SJohn Marino 
38*e4b17023SJohn Marino struct token
39*e4b17023SJohn Marino {
40*e4b17023SJohn Marino   const char *value;
41*e4b17023SJohn Marino   int code;
42*e4b17023SJohn Marino   bool valid;
43*e4b17023SJohn Marino };
44*e4b17023SJohn Marino static struct token T;
45*e4b17023SJohn Marino 
46*e4b17023SJohn Marino /* Retrieve the code of the current token; if there is no current token,
47*e4b17023SJohn Marino    get the next one from the lexer.  */
48*e4b17023SJohn Marino static inline int
token(void)49*e4b17023SJohn Marino token (void)
50*e4b17023SJohn Marino {
51*e4b17023SJohn Marino   if (!T.valid)
52*e4b17023SJohn Marino     {
53*e4b17023SJohn Marino       T.code = yylex (&T.value);
54*e4b17023SJohn Marino       T.valid = true;
55*e4b17023SJohn Marino     }
56*e4b17023SJohn Marino   return T.code;
57*e4b17023SJohn Marino }
58*e4b17023SJohn Marino 
59*e4b17023SJohn Marino /* Retrieve the value of the current token (if any) and mark it consumed.
60*e4b17023SJohn Marino    The next call to token() will get another token from the lexer.  */
61*e4b17023SJohn Marino static inline const char *
advance(void)62*e4b17023SJohn Marino advance (void)
63*e4b17023SJohn Marino {
64*e4b17023SJohn Marino   T.valid = false;
65*e4b17023SJohn Marino   return T.value;
66*e4b17023SJohn Marino }
67*e4b17023SJohn Marino 
68*e4b17023SJohn Marino /* Diagnostics.  */
69*e4b17023SJohn Marino 
70*e4b17023SJohn Marino /* This array is indexed by the token code minus CHAR_TOKEN_OFFSET.  */
71*e4b17023SJohn Marino static const char *const token_names[] = {
72*e4b17023SJohn Marino   "GTY",
73*e4b17023SJohn Marino   "typedef",
74*e4b17023SJohn Marino   "extern",
75*e4b17023SJohn Marino   "static",
76*e4b17023SJohn Marino   "union",
77*e4b17023SJohn Marino   "struct",
78*e4b17023SJohn Marino   "enum",
79*e4b17023SJohn Marino   "VEC",
80*e4b17023SJohn Marino   "DEF_VEC_[OP]",
81*e4b17023SJohn Marino   "DEF_VEC_I",
82*e4b17023SJohn Marino   "DEF_VEC_ALLOC_[IOP]",
83*e4b17023SJohn Marino   "...",
84*e4b17023SJohn Marino   "ptr_alias",
85*e4b17023SJohn Marino   "nested_ptr",
86*e4b17023SJohn Marino   "a param<N>_is option",
87*e4b17023SJohn Marino   "a number",
88*e4b17023SJohn Marino   "a scalar type",
89*e4b17023SJohn Marino   "an identifier",
90*e4b17023SJohn Marino   "a string constant",
91*e4b17023SJohn Marino   "a character constant",
92*e4b17023SJohn Marino   "an array declarator",
93*e4b17023SJohn Marino };
94*e4b17023SJohn Marino 
95*e4b17023SJohn Marino /* This array is indexed by token code minus FIRST_TOKEN_WITH_VALUE.  */
96*e4b17023SJohn Marino static const char *const token_value_format[] = {
97*e4b17023SJohn Marino   "%s",
98*e4b17023SJohn Marino   "'%s'",
99*e4b17023SJohn Marino   "'%s'",
100*e4b17023SJohn Marino   "'%s'",
101*e4b17023SJohn Marino   "'\"%s\"'",
102*e4b17023SJohn Marino   "\"'%s'\"",
103*e4b17023SJohn Marino   "'[%s]'",
104*e4b17023SJohn Marino };
105*e4b17023SJohn Marino 
106*e4b17023SJohn Marino /* Produce a printable representation for a token defined by CODE and
107*e4b17023SJohn Marino    VALUE.  This sometimes returns pointers into malloc memory and
108*e4b17023SJohn Marino    sometimes not, therefore it is unsafe to free the pointer it
109*e4b17023SJohn Marino    returns, so that memory is leaked.  This does not matter, as this
110*e4b17023SJohn Marino    function is only used for diagnostics, and in a successful run of
111*e4b17023SJohn Marino    the program there will be none.  */
112*e4b17023SJohn Marino static const char *
print_token(int code,const char * value)113*e4b17023SJohn Marino print_token (int code, const char *value)
114*e4b17023SJohn Marino {
115*e4b17023SJohn Marino   if (code < CHAR_TOKEN_OFFSET)
116*e4b17023SJohn Marino     return xasprintf ("'%c'", code);
117*e4b17023SJohn Marino   else if (code < FIRST_TOKEN_WITH_VALUE)
118*e4b17023SJohn Marino     return xasprintf ("'%s'", token_names[code - CHAR_TOKEN_OFFSET]);
119*e4b17023SJohn Marino   else if (!value)
120*e4b17023SJohn Marino     return token_names[code - CHAR_TOKEN_OFFSET];	/* don't quote these */
121*e4b17023SJohn Marino   else
122*e4b17023SJohn Marino     return xasprintf (token_value_format[code - FIRST_TOKEN_WITH_VALUE],
123*e4b17023SJohn Marino 		      value);
124*e4b17023SJohn Marino }
125*e4b17023SJohn Marino 
126*e4b17023SJohn Marino /* Convenience wrapper around print_token which produces the printable
127*e4b17023SJohn Marino    representation of the current token.  */
128*e4b17023SJohn Marino static inline const char *
print_cur_token(void)129*e4b17023SJohn Marino print_cur_token (void)
130*e4b17023SJohn Marino {
131*e4b17023SJohn Marino   return print_token (T.code, T.value);
132*e4b17023SJohn Marino }
133*e4b17023SJohn Marino 
134*e4b17023SJohn Marino /* Report a parse error on the current line, with diagnostic MSG.
135*e4b17023SJohn Marino    Behaves as standard printf with respect to additional arguments and
136*e4b17023SJohn Marino    format escapes.  */
137*e4b17023SJohn Marino static void ATTRIBUTE_PRINTF_1
parse_error(const char * msg,...)138*e4b17023SJohn Marino parse_error (const char *msg, ...)
139*e4b17023SJohn Marino {
140*e4b17023SJohn Marino   va_list ap;
141*e4b17023SJohn Marino 
142*e4b17023SJohn Marino   fprintf (stderr, "%s:%d: parse error: ",
143*e4b17023SJohn Marino 	   get_input_file_name (lexer_line.file), lexer_line.line);
144*e4b17023SJohn Marino 
145*e4b17023SJohn Marino   va_start (ap, msg);
146*e4b17023SJohn Marino   vfprintf (stderr, msg, ap);
147*e4b17023SJohn Marino   va_end (ap);
148*e4b17023SJohn Marino 
149*e4b17023SJohn Marino   fputc ('\n', stderr);
150*e4b17023SJohn Marino 
151*e4b17023SJohn Marino   hit_error = true;
152*e4b17023SJohn Marino }
153*e4b17023SJohn Marino 
154*e4b17023SJohn Marino /* If the next token does not have code T, report a parse error; otherwise
155*e4b17023SJohn Marino    return the token's value.  */
156*e4b17023SJohn Marino static const char *
require(int t)157*e4b17023SJohn Marino require (int t)
158*e4b17023SJohn Marino {
159*e4b17023SJohn Marino   int u = token ();
160*e4b17023SJohn Marino   const char *v = advance ();
161*e4b17023SJohn Marino   if (u != t)
162*e4b17023SJohn Marino     {
163*e4b17023SJohn Marino       parse_error ("expected %s, have %s",
164*e4b17023SJohn Marino 		   print_token (t, 0), print_token (u, v));
165*e4b17023SJohn Marino       return 0;
166*e4b17023SJohn Marino     }
167*e4b17023SJohn Marino   return v;
168*e4b17023SJohn Marino }
169*e4b17023SJohn Marino 
170*e4b17023SJohn Marino /* If the next token does not have one of the codes T1 or T2, report a
171*e4b17023SJohn Marino    parse error; otherwise return the token's value.  */
172*e4b17023SJohn Marino static const char *
require2(int t1,int t2)173*e4b17023SJohn Marino require2 (int t1, int t2)
174*e4b17023SJohn Marino {
175*e4b17023SJohn Marino   int u = token ();
176*e4b17023SJohn Marino   const char *v = advance ();
177*e4b17023SJohn Marino   if (u != t1 && u != t2)
178*e4b17023SJohn Marino     {
179*e4b17023SJohn Marino       parse_error ("expected %s or %s, have %s",
180*e4b17023SJohn Marino 		   print_token (t1, 0), print_token (t2, 0),
181*e4b17023SJohn Marino 		   print_token (u, v));
182*e4b17023SJohn Marino       return 0;
183*e4b17023SJohn Marino     }
184*e4b17023SJohn Marino   return v;
185*e4b17023SJohn Marino }
186*e4b17023SJohn Marino 
187*e4b17023SJohn Marino /* Near-terminals.  */
188*e4b17023SJohn Marino 
189*e4b17023SJohn Marino /* C-style string constant concatenation: STRING+
190*e4b17023SJohn Marino    Bare STRING should appear nowhere else in this file.  */
191*e4b17023SJohn Marino static const char *
string_seq(void)192*e4b17023SJohn Marino string_seq (void)
193*e4b17023SJohn Marino {
194*e4b17023SJohn Marino   const char *s1, *s2;
195*e4b17023SJohn Marino   size_t l1, l2;
196*e4b17023SJohn Marino   char *buf;
197*e4b17023SJohn Marino 
198*e4b17023SJohn Marino   s1 = require (STRING);
199*e4b17023SJohn Marino   if (s1 == 0)
200*e4b17023SJohn Marino     return "";
201*e4b17023SJohn Marino   while (token () == STRING)
202*e4b17023SJohn Marino     {
203*e4b17023SJohn Marino       s2 = advance ();
204*e4b17023SJohn Marino 
205*e4b17023SJohn Marino       l1 = strlen (s1);
206*e4b17023SJohn Marino       l2 = strlen (s2);
207*e4b17023SJohn Marino       buf = XRESIZEVEC (char, CONST_CAST (char *, s1), l1 + l2 + 1);
208*e4b17023SJohn Marino       memcpy (buf + l1, s2, l2 + 1);
209*e4b17023SJohn Marino       XDELETE (CONST_CAST (char *, s2));
210*e4b17023SJohn Marino       s1 = buf;
211*e4b17023SJohn Marino     }
212*e4b17023SJohn Marino   return s1;
213*e4b17023SJohn Marino }
214*e4b17023SJohn Marino 
215*e4b17023SJohn Marino /* typedef_name: either an ID, or VEC(x,y) which is translated to VEC_x_y.
216*e4b17023SJohn Marino    Use only where VEC(x,y) is legitimate, i.e. in positions where a
217*e4b17023SJohn Marino    typedef name may appear.  */
218*e4b17023SJohn Marino static const char *
typedef_name(void)219*e4b17023SJohn Marino typedef_name (void)
220*e4b17023SJohn Marino {
221*e4b17023SJohn Marino   if (token () == VEC_TOKEN)
222*e4b17023SJohn Marino     {
223*e4b17023SJohn Marino       const char *c1, *c2, *r;
224*e4b17023SJohn Marino       advance ();
225*e4b17023SJohn Marino       require ('(');
226*e4b17023SJohn Marino       c1 = require2 (ID, SCALAR);
227*e4b17023SJohn Marino       require (',');
228*e4b17023SJohn Marino       c2 = require (ID);
229*e4b17023SJohn Marino       require (')');
230*e4b17023SJohn Marino       r = concat ("VEC_", c1, "_", c2, (char *) 0);
231*e4b17023SJohn Marino       free (CONST_CAST (char *, c1));
232*e4b17023SJohn Marino       free (CONST_CAST (char *, c2));
233*e4b17023SJohn Marino       return r;
234*e4b17023SJohn Marino     }
235*e4b17023SJohn Marino   else
236*e4b17023SJohn Marino     return require (ID);
237*e4b17023SJohn Marino }
238*e4b17023SJohn Marino 
239*e4b17023SJohn Marino /* Absorb a sequence of tokens delimited by balanced ()[]{}.  */
240*e4b17023SJohn Marino static void
consume_balanced(int opener,int closer)241*e4b17023SJohn Marino consume_balanced (int opener, int closer)
242*e4b17023SJohn Marino {
243*e4b17023SJohn Marino   require (opener);
244*e4b17023SJohn Marino   for (;;)
245*e4b17023SJohn Marino     switch (token ())
246*e4b17023SJohn Marino       {
247*e4b17023SJohn Marino       default:
248*e4b17023SJohn Marino 	advance ();
249*e4b17023SJohn Marino 	break;
250*e4b17023SJohn Marino       case '(':
251*e4b17023SJohn Marino 	consume_balanced ('(', ')');
252*e4b17023SJohn Marino 	break;
253*e4b17023SJohn Marino       case '[':
254*e4b17023SJohn Marino 	consume_balanced ('[', ']');
255*e4b17023SJohn Marino 	break;
256*e4b17023SJohn Marino       case '{':
257*e4b17023SJohn Marino 	consume_balanced ('{', '}');
258*e4b17023SJohn Marino 	break;
259*e4b17023SJohn Marino 
260*e4b17023SJohn Marino       case '}':
261*e4b17023SJohn Marino       case ']':
262*e4b17023SJohn Marino       case ')':
263*e4b17023SJohn Marino 	if (token () != closer)
264*e4b17023SJohn Marino 	  parse_error ("unbalanced delimiters - expected '%c', have '%c'",
265*e4b17023SJohn Marino 		       closer, token ());
266*e4b17023SJohn Marino       advance ();
267*e4b17023SJohn Marino       return;
268*e4b17023SJohn Marino 
269*e4b17023SJohn Marino       case EOF_TOKEN:
270*e4b17023SJohn Marino 	parse_error ("unexpected end of file within %c%c-delimited construct",
271*e4b17023SJohn Marino 		     opener, closer);
272*e4b17023SJohn Marino 	return;
273*e4b17023SJohn Marino       }
274*e4b17023SJohn Marino }
275*e4b17023SJohn Marino 
276*e4b17023SJohn Marino /* Absorb a sequence of tokens, possibly including ()[]{}-delimited
277*e4b17023SJohn Marino    expressions, until we encounter a semicolon outside any such
278*e4b17023SJohn Marino    delimiters; absorb that too.  If IMMEDIATE is true, it is an error
279*e4b17023SJohn Marino    if the semicolon is not the first token encountered.  */
280*e4b17023SJohn Marino static void
consume_until_semi(bool immediate)281*e4b17023SJohn Marino consume_until_semi (bool immediate)
282*e4b17023SJohn Marino {
283*e4b17023SJohn Marino   if (immediate && token () != ';')
284*e4b17023SJohn Marino     require (';');
285*e4b17023SJohn Marino   for (;;)
286*e4b17023SJohn Marino     switch (token ())
287*e4b17023SJohn Marino       {
288*e4b17023SJohn Marino       case ';':
289*e4b17023SJohn Marino 	advance ();
290*e4b17023SJohn Marino 	return;
291*e4b17023SJohn Marino       default:
292*e4b17023SJohn Marino 	advance ();
293*e4b17023SJohn Marino 	break;
294*e4b17023SJohn Marino 
295*e4b17023SJohn Marino       case '(':
296*e4b17023SJohn Marino 	consume_balanced ('(', ')');
297*e4b17023SJohn Marino 	break;
298*e4b17023SJohn Marino       case '[':
299*e4b17023SJohn Marino 	consume_balanced ('[', ']');
300*e4b17023SJohn Marino 	break;
301*e4b17023SJohn Marino       case '{':
302*e4b17023SJohn Marino 	consume_balanced ('{', '}');
303*e4b17023SJohn Marino 	break;
304*e4b17023SJohn Marino 
305*e4b17023SJohn Marino       case '}':
306*e4b17023SJohn Marino       case ']':
307*e4b17023SJohn Marino       case ')':
308*e4b17023SJohn Marino 	parse_error ("unmatched '%c' while scanning for ';'", token ());
309*e4b17023SJohn Marino       return;
310*e4b17023SJohn Marino 
311*e4b17023SJohn Marino       case EOF_TOKEN:
312*e4b17023SJohn Marino 	parse_error ("unexpected end of file while scanning for ';'");
313*e4b17023SJohn Marino 	return;
314*e4b17023SJohn Marino       }
315*e4b17023SJohn Marino }
316*e4b17023SJohn Marino 
317*e4b17023SJohn Marino /* Absorb a sequence of tokens, possibly including ()[]{}-delimited
318*e4b17023SJohn Marino    expressions, until we encounter a comma or semicolon outside any
319*e4b17023SJohn Marino    such delimiters; absorb that too.  If IMMEDIATE is true, it is an
320*e4b17023SJohn Marino    error if the comma or semicolon is not the first token encountered.
321*e4b17023SJohn Marino    Returns true if the loop ended with a comma.  */
322*e4b17023SJohn Marino static bool
consume_until_comma_or_semi(bool immediate)323*e4b17023SJohn Marino consume_until_comma_or_semi (bool immediate)
324*e4b17023SJohn Marino {
325*e4b17023SJohn Marino   if (immediate && token () != ',' && token () != ';')
326*e4b17023SJohn Marino     require2 (',', ';');
327*e4b17023SJohn Marino   for (;;)
328*e4b17023SJohn Marino     switch (token ())
329*e4b17023SJohn Marino       {
330*e4b17023SJohn Marino       case ',':
331*e4b17023SJohn Marino 	advance ();
332*e4b17023SJohn Marino 	return true;
333*e4b17023SJohn Marino       case ';':
334*e4b17023SJohn Marino 	advance ();
335*e4b17023SJohn Marino 	return false;
336*e4b17023SJohn Marino       default:
337*e4b17023SJohn Marino 	advance ();
338*e4b17023SJohn Marino 	break;
339*e4b17023SJohn Marino 
340*e4b17023SJohn Marino       case '(':
341*e4b17023SJohn Marino 	consume_balanced ('(', ')');
342*e4b17023SJohn Marino 	break;
343*e4b17023SJohn Marino       case '[':
344*e4b17023SJohn Marino 	consume_balanced ('[', ']');
345*e4b17023SJohn Marino 	break;
346*e4b17023SJohn Marino       case '{':
347*e4b17023SJohn Marino 	consume_balanced ('{', '}');
348*e4b17023SJohn Marino 	break;
349*e4b17023SJohn Marino 
350*e4b17023SJohn Marino       case '}':
351*e4b17023SJohn Marino       case ']':
352*e4b17023SJohn Marino       case ')':
353*e4b17023SJohn Marino 	parse_error ("unmatched '%s' while scanning for ',' or ';'",
354*e4b17023SJohn Marino 		     print_cur_token ());
355*e4b17023SJohn Marino       return false;
356*e4b17023SJohn Marino 
357*e4b17023SJohn Marino       case EOF_TOKEN:
358*e4b17023SJohn Marino 	parse_error ("unexpected end of file while scanning for ',' or ';'");
359*e4b17023SJohn Marino 	return false;
360*e4b17023SJohn Marino       }
361*e4b17023SJohn Marino }
362*e4b17023SJohn Marino 
363*e4b17023SJohn Marino 
364*e4b17023SJohn Marino /* GTY(()) option handling.  */
365*e4b17023SJohn Marino static type_p type (options_p *optsp, bool nested);
366*e4b17023SJohn Marino 
367*e4b17023SJohn Marino /* Optional parenthesized string: ('(' string_seq ')')? */
368*e4b17023SJohn Marino static options_p
str_optvalue_opt(options_p prev)369*e4b17023SJohn Marino str_optvalue_opt (options_p prev)
370*e4b17023SJohn Marino {
371*e4b17023SJohn Marino   const char *name = advance ();
372*e4b17023SJohn Marino   const char *value = "";
373*e4b17023SJohn Marino   if (token () == '(')
374*e4b17023SJohn Marino     {
375*e4b17023SJohn Marino       advance ();
376*e4b17023SJohn Marino       value = string_seq ();
377*e4b17023SJohn Marino       require (')');
378*e4b17023SJohn Marino     }
379*e4b17023SJohn Marino   return create_string_option (prev, name, value);
380*e4b17023SJohn Marino }
381*e4b17023SJohn Marino 
382*e4b17023SJohn Marino /* absdecl: type '*'*
383*e4b17023SJohn Marino    -- a vague approximation to what the C standard calls an abstract
384*e4b17023SJohn Marino    declarator.  The only kinds that are actually used are those that
385*e4b17023SJohn Marino    are just a bare type and those that have trailing pointer-stars.
386*e4b17023SJohn Marino    Further kinds should be implemented if and when they become
387*e4b17023SJohn Marino    necessary.  Used only within GTY(()) option values, therefore
388*e4b17023SJohn Marino    further GTY(()) tags within the type are invalid.  Note that the
389*e4b17023SJohn Marino    return value has already been run through adjust_field_type.  */
390*e4b17023SJohn Marino static type_p
absdecl(void)391*e4b17023SJohn Marino absdecl (void)
392*e4b17023SJohn Marino {
393*e4b17023SJohn Marino   type_p ty;
394*e4b17023SJohn Marino   options_p opts;
395*e4b17023SJohn Marino 
396*e4b17023SJohn Marino   ty = type (&opts, true);
397*e4b17023SJohn Marino   while (token () == '*')
398*e4b17023SJohn Marino     {
399*e4b17023SJohn Marino       ty = create_pointer (ty);
400*e4b17023SJohn Marino       advance ();
401*e4b17023SJohn Marino     }
402*e4b17023SJohn Marino 
403*e4b17023SJohn Marino   if (opts)
404*e4b17023SJohn Marino     parse_error ("nested GTY(()) options are invalid");
405*e4b17023SJohn Marino 
406*e4b17023SJohn Marino   return adjust_field_type (ty, 0);
407*e4b17023SJohn Marino }
408*e4b17023SJohn Marino 
409*e4b17023SJohn Marino /* Type-option: '(' absdecl ')' */
410*e4b17023SJohn Marino static options_p
type_optvalue(options_p prev,const char * name)411*e4b17023SJohn Marino type_optvalue (options_p prev, const char *name)
412*e4b17023SJohn Marino {
413*e4b17023SJohn Marino   type_p ty;
414*e4b17023SJohn Marino   require ('(');
415*e4b17023SJohn Marino   ty = absdecl ();
416*e4b17023SJohn Marino   require (')');
417*e4b17023SJohn Marino   return create_type_option (prev, name, ty);
418*e4b17023SJohn Marino }
419*e4b17023SJohn Marino 
420*e4b17023SJohn Marino /* Nested pointer data: '(' type '*'* ',' string_seq ',' string_seq ')' */
421*e4b17023SJohn Marino static options_p
nestedptr_optvalue(options_p prev)422*e4b17023SJohn Marino nestedptr_optvalue (options_p prev)
423*e4b17023SJohn Marino {
424*e4b17023SJohn Marino   type_p ty;
425*e4b17023SJohn Marino   const char *from, *to;
426*e4b17023SJohn Marino 
427*e4b17023SJohn Marino   require ('(');
428*e4b17023SJohn Marino   ty = absdecl ();
429*e4b17023SJohn Marino   require (',');
430*e4b17023SJohn Marino   to = string_seq ();
431*e4b17023SJohn Marino   require (',');
432*e4b17023SJohn Marino   from = string_seq ();
433*e4b17023SJohn Marino   require (')');
434*e4b17023SJohn Marino 
435*e4b17023SJohn Marino   return create_nested_ptr_option (prev, ty, to, from);
436*e4b17023SJohn Marino }
437*e4b17023SJohn Marino 
438*e4b17023SJohn Marino /* One GTY(()) option:
439*e4b17023SJohn Marino    ID str_optvalue_opt
440*e4b17023SJohn Marino    | PTR_ALIAS type_optvalue
441*e4b17023SJohn Marino    | PARAM_IS type_optvalue
442*e4b17023SJohn Marino    | NESTED_PTR nestedptr_optvalue
443*e4b17023SJohn Marino */
444*e4b17023SJohn Marino static options_p
option(options_p prev)445*e4b17023SJohn Marino option (options_p prev)
446*e4b17023SJohn Marino {
447*e4b17023SJohn Marino   switch (token ())
448*e4b17023SJohn Marino     {
449*e4b17023SJohn Marino     case ID:
450*e4b17023SJohn Marino       return str_optvalue_opt (prev);
451*e4b17023SJohn Marino 
452*e4b17023SJohn Marino     case PTR_ALIAS:
453*e4b17023SJohn Marino       advance ();
454*e4b17023SJohn Marino       return type_optvalue (prev, "ptr_alias");
455*e4b17023SJohn Marino 
456*e4b17023SJohn Marino     case PARAM_IS:
457*e4b17023SJohn Marino       return type_optvalue (prev, advance ());
458*e4b17023SJohn Marino 
459*e4b17023SJohn Marino     case NESTED_PTR:
460*e4b17023SJohn Marino       advance ();
461*e4b17023SJohn Marino       return nestedptr_optvalue (prev);
462*e4b17023SJohn Marino 
463*e4b17023SJohn Marino     default:
464*e4b17023SJohn Marino       parse_error ("expected an option keyword, have %s", print_cur_token ());
465*e4b17023SJohn Marino       advance ();
466*e4b17023SJohn Marino       return create_string_option (prev, "", "");
467*e4b17023SJohn Marino     }
468*e4b17023SJohn Marino }
469*e4b17023SJohn Marino 
470*e4b17023SJohn Marino /* One comma-separated list of options.  */
471*e4b17023SJohn Marino static options_p
option_seq(void)472*e4b17023SJohn Marino option_seq (void)
473*e4b17023SJohn Marino {
474*e4b17023SJohn Marino   options_p o;
475*e4b17023SJohn Marino 
476*e4b17023SJohn Marino   o = option (0);
477*e4b17023SJohn Marino   while (token () == ',')
478*e4b17023SJohn Marino     {
479*e4b17023SJohn Marino       advance ();
480*e4b17023SJohn Marino       o = option (o);
481*e4b17023SJohn Marino     }
482*e4b17023SJohn Marino   return o;
483*e4b17023SJohn Marino }
484*e4b17023SJohn Marino 
485*e4b17023SJohn Marino /* GTY marker: 'GTY' '(' '(' option_seq? ')' ')' */
486*e4b17023SJohn Marino static options_p
gtymarker(void)487*e4b17023SJohn Marino gtymarker (void)
488*e4b17023SJohn Marino {
489*e4b17023SJohn Marino   options_p result = 0;
490*e4b17023SJohn Marino   require (GTY_TOKEN);
491*e4b17023SJohn Marino   require ('(');
492*e4b17023SJohn Marino   require ('(');
493*e4b17023SJohn Marino   if (token () != ')')
494*e4b17023SJohn Marino     result = option_seq ();
495*e4b17023SJohn Marino   require (')');
496*e4b17023SJohn Marino   require (')');
497*e4b17023SJohn Marino   return result;
498*e4b17023SJohn Marino }
499*e4b17023SJohn Marino 
500*e4b17023SJohn Marino /* Optional GTY marker.  */
501*e4b17023SJohn Marino static options_p
gtymarker_opt(void)502*e4b17023SJohn Marino gtymarker_opt (void)
503*e4b17023SJohn Marino {
504*e4b17023SJohn Marino   if (token () != GTY_TOKEN)
505*e4b17023SJohn Marino     return 0;
506*e4b17023SJohn Marino   return gtymarker ();
507*e4b17023SJohn Marino }
508*e4b17023SJohn Marino 
509*e4b17023SJohn Marino /* Declarators. The logic here is largely lifted from c-parser.c.
510*e4b17023SJohn Marino    Note that we do not have to process abstract declarators, which can
511*e4b17023SJohn Marino    appear only in parameter type lists or casts (but see absdecl,
512*e4b17023SJohn Marino    above).  Also, type qualifiers are thrown out in gengtype-lex.l so
513*e4b17023SJohn Marino    we don't have to do it.  */
514*e4b17023SJohn Marino 
515*e4b17023SJohn Marino /* array_and_function_declarators_opt:
516*e4b17023SJohn Marino    \epsilon
517*e4b17023SJohn Marino    array_and_function_declarators_opt ARRAY
518*e4b17023SJohn Marino    array_and_function_declarators_opt '(' ... ')'
519*e4b17023SJohn Marino 
520*e4b17023SJohn Marino    where '...' indicates stuff we ignore except insofar as grouping
521*e4b17023SJohn Marino    symbols ()[]{} must balance.
522*e4b17023SJohn Marino 
523*e4b17023SJohn Marino    Subroutine of direct_declarator - do not use elsewhere. */
524*e4b17023SJohn Marino 
525*e4b17023SJohn Marino static type_p
array_and_function_declarators_opt(type_p ty)526*e4b17023SJohn Marino array_and_function_declarators_opt (type_p ty)
527*e4b17023SJohn Marino {
528*e4b17023SJohn Marino   if (token () == ARRAY)
529*e4b17023SJohn Marino     {
530*e4b17023SJohn Marino       const char *array = advance ();
531*e4b17023SJohn Marino       return create_array (array_and_function_declarators_opt (ty), array);
532*e4b17023SJohn Marino     }
533*e4b17023SJohn Marino   else if (token () == '(')
534*e4b17023SJohn Marino     {
535*e4b17023SJohn Marino       /* We don't need exact types for functions.  */
536*e4b17023SJohn Marino       consume_balanced ('(', ')');
537*e4b17023SJohn Marino       array_and_function_declarators_opt (ty);
538*e4b17023SJohn Marino       return create_scalar_type ("function type");
539*e4b17023SJohn Marino     }
540*e4b17023SJohn Marino   else
541*e4b17023SJohn Marino     return ty;
542*e4b17023SJohn Marino }
543*e4b17023SJohn Marino 
544*e4b17023SJohn Marino static type_p inner_declarator (type_p, const char **, options_p *);
545*e4b17023SJohn Marino 
546*e4b17023SJohn Marino /* direct_declarator:
547*e4b17023SJohn Marino    '(' inner_declarator ')'
548*e4b17023SJohn Marino    gtymarker_opt ID array_and_function_declarators_opt
549*e4b17023SJohn Marino 
550*e4b17023SJohn Marino    Subroutine of declarator, mutually recursive with inner_declarator;
551*e4b17023SJohn Marino    do not use elsewhere.  */
552*e4b17023SJohn Marino static type_p
direct_declarator(type_p ty,const char ** namep,options_p * optsp)553*e4b17023SJohn Marino direct_declarator (type_p ty, const char **namep, options_p *optsp)
554*e4b17023SJohn Marino {
555*e4b17023SJohn Marino   /* The first token in a direct-declarator must be an ID, a
556*e4b17023SJohn Marino      GTY marker, or an open parenthesis.  */
557*e4b17023SJohn Marino   switch (token ())
558*e4b17023SJohn Marino     {
559*e4b17023SJohn Marino     case GTY_TOKEN:
560*e4b17023SJohn Marino       *optsp = gtymarker ();
561*e4b17023SJohn Marino       /* fall through */
562*e4b17023SJohn Marino     case ID:
563*e4b17023SJohn Marino       *namep = require (ID);
564*e4b17023SJohn Marino       break;
565*e4b17023SJohn Marino 
566*e4b17023SJohn Marino     case '(':
567*e4b17023SJohn Marino       advance ();
568*e4b17023SJohn Marino       ty = inner_declarator (ty, namep, optsp);
569*e4b17023SJohn Marino       require (')');
570*e4b17023SJohn Marino       break;
571*e4b17023SJohn Marino 
572*e4b17023SJohn Marino     default:
573*e4b17023SJohn Marino       parse_error ("expected '(', 'GTY', or an identifier, have %s",
574*e4b17023SJohn Marino 		   print_cur_token ());
575*e4b17023SJohn Marino       /* Do _not_ advance if what we have is a close squiggle brace, as
576*e4b17023SJohn Marino 	 we will get much better error recovery that way.  */
577*e4b17023SJohn Marino       if (token () != '}')
578*e4b17023SJohn Marino 	advance ();
579*e4b17023SJohn Marino       return 0;
580*e4b17023SJohn Marino     }
581*e4b17023SJohn Marino   return array_and_function_declarators_opt (ty);
582*e4b17023SJohn Marino }
583*e4b17023SJohn Marino 
584*e4b17023SJohn Marino /* The difference between inner_declarator and declarator is in the
585*e4b17023SJohn Marino    handling of stars.  Consider this declaration:
586*e4b17023SJohn Marino 
587*e4b17023SJohn Marino    char * (*pfc) (void)
588*e4b17023SJohn Marino 
589*e4b17023SJohn Marino    It declares a pointer to a function that takes no arguments and
590*e4b17023SJohn Marino    returns a char*.  To construct the correct type for this
591*e4b17023SJohn Marino    declaration, the star outside the parentheses must be processed
592*e4b17023SJohn Marino    _before_ the function type, the star inside the parentheses must
593*e4b17023SJohn Marino    be processed _after_ the function type.  To accomplish this,
594*e4b17023SJohn Marino    declarator() creates pointers before recursing (it is actually
595*e4b17023SJohn Marino    coded as a while loop), whereas inner_declarator() recurses before
596*e4b17023SJohn Marino    creating pointers.  */
597*e4b17023SJohn Marino 
598*e4b17023SJohn Marino /* inner_declarator:
599*e4b17023SJohn Marino    '*' inner_declarator
600*e4b17023SJohn Marino    direct_declarator
601*e4b17023SJohn Marino 
602*e4b17023SJohn Marino    Mutually recursive subroutine of direct_declarator; do not use
603*e4b17023SJohn Marino    elsewhere.  */
604*e4b17023SJohn Marino 
605*e4b17023SJohn Marino static type_p
inner_declarator(type_p ty,const char ** namep,options_p * optsp)606*e4b17023SJohn Marino inner_declarator (type_p ty, const char **namep, options_p *optsp)
607*e4b17023SJohn Marino {
608*e4b17023SJohn Marino   if (token () == '*')
609*e4b17023SJohn Marino     {
610*e4b17023SJohn Marino       type_p inner;
611*e4b17023SJohn Marino       advance ();
612*e4b17023SJohn Marino       inner = inner_declarator (ty, namep, optsp);
613*e4b17023SJohn Marino       if (inner == 0)
614*e4b17023SJohn Marino 	return 0;
615*e4b17023SJohn Marino       else
616*e4b17023SJohn Marino 	return create_pointer (ty);
617*e4b17023SJohn Marino     }
618*e4b17023SJohn Marino   else
619*e4b17023SJohn Marino     return direct_declarator (ty, namep, optsp);
620*e4b17023SJohn Marino }
621*e4b17023SJohn Marino 
622*e4b17023SJohn Marino /* declarator: '*'+ direct_declarator
623*e4b17023SJohn Marino 
624*e4b17023SJohn Marino    This is the sole public interface to this part of the grammar.
625*e4b17023SJohn Marino    Arguments are the type known so far, a pointer to where the name
626*e4b17023SJohn Marino    may be stored, and a pointer to where GTY options may be stored.
627*e4b17023SJohn Marino    Returns the final type. */
628*e4b17023SJohn Marino 
629*e4b17023SJohn Marino static type_p
declarator(type_p ty,const char ** namep,options_p * optsp)630*e4b17023SJohn Marino declarator (type_p ty, const char **namep, options_p *optsp)
631*e4b17023SJohn Marino {
632*e4b17023SJohn Marino   *namep = 0;
633*e4b17023SJohn Marino   *optsp = 0;
634*e4b17023SJohn Marino   while (token () == '*')
635*e4b17023SJohn Marino     {
636*e4b17023SJohn Marino       advance ();
637*e4b17023SJohn Marino       ty = create_pointer (ty);
638*e4b17023SJohn Marino     }
639*e4b17023SJohn Marino   return direct_declarator (ty, namep, optsp);
640*e4b17023SJohn Marino }
641*e4b17023SJohn Marino 
642*e4b17023SJohn Marino /* Types and declarations.  */
643*e4b17023SJohn Marino 
644*e4b17023SJohn Marino /* Structure field(s) declaration:
645*e4b17023SJohn Marino    (
646*e4b17023SJohn Marino    type bitfield ';'
647*e4b17023SJohn Marino    | type declarator bitfield? ( ',' declarator bitfield? )+ ';'
648*e4b17023SJohn Marino    )+
649*e4b17023SJohn Marino 
650*e4b17023SJohn Marino    Knows that such declarations must end with a close brace (or,
651*e4b17023SJohn Marino    erroneously, at EOF).
652*e4b17023SJohn Marino */
653*e4b17023SJohn Marino static pair_p
struct_field_seq(void)654*e4b17023SJohn Marino struct_field_seq (void)
655*e4b17023SJohn Marino {
656*e4b17023SJohn Marino   pair_p f = 0;
657*e4b17023SJohn Marino   type_p ty, dty;
658*e4b17023SJohn Marino   options_p opts, dopts;
659*e4b17023SJohn Marino   const char *name;
660*e4b17023SJohn Marino   bool another;
661*e4b17023SJohn Marino 
662*e4b17023SJohn Marino   do
663*e4b17023SJohn Marino     {
664*e4b17023SJohn Marino       ty = type (&opts, true);
665*e4b17023SJohn Marino       /* Another piece of the IFCVT_EXTRA_FIELDS special case, see type().  */
666*e4b17023SJohn Marino       if (!ty && token () == '}')
667*e4b17023SJohn Marino 	break;
668*e4b17023SJohn Marino 
669*e4b17023SJohn Marino       if (!ty || token () == ':')
670*e4b17023SJohn Marino 	{
671*e4b17023SJohn Marino 	  consume_until_semi (false);
672*e4b17023SJohn Marino 	  continue;
673*e4b17023SJohn Marino 	}
674*e4b17023SJohn Marino 
675*e4b17023SJohn Marino       do
676*e4b17023SJohn Marino 	{
677*e4b17023SJohn Marino 	  dty = declarator (ty, &name, &dopts);
678*e4b17023SJohn Marino 	  /* There could be any number of weird things after the declarator,
679*e4b17023SJohn Marino 	     notably bitfield declarations and __attribute__s.  If this
680*e4b17023SJohn Marino 	     function returns true, the last thing was a comma, so we have
681*e4b17023SJohn Marino 	     more than one declarator paired with the current type.  */
682*e4b17023SJohn Marino 	  another = consume_until_comma_or_semi (false);
683*e4b17023SJohn Marino 
684*e4b17023SJohn Marino 	  if (!dty)
685*e4b17023SJohn Marino 	    continue;
686*e4b17023SJohn Marino 
687*e4b17023SJohn Marino 	  if (opts && dopts)
688*e4b17023SJohn Marino 	    parse_error ("two GTY(()) options for field %s", name);
689*e4b17023SJohn Marino 	  if (opts && !dopts)
690*e4b17023SJohn Marino 	    dopts = opts;
691*e4b17023SJohn Marino 
692*e4b17023SJohn Marino 	  f = create_field_at (f, dty, name, dopts, &lexer_line);
693*e4b17023SJohn Marino 	}
694*e4b17023SJohn Marino       while (another);
695*e4b17023SJohn Marino     }
696*e4b17023SJohn Marino   while (token () != '}' && token () != EOF_TOKEN);
697*e4b17023SJohn Marino   return nreverse_pairs (f);
698*e4b17023SJohn Marino }
699*e4b17023SJohn Marino 
700*e4b17023SJohn Marino /* This is called type(), but what it parses (sort of) is what C calls
701*e4b17023SJohn Marino    declaration-specifiers and specifier-qualifier-list:
702*e4b17023SJohn Marino 
703*e4b17023SJohn Marino    SCALAR
704*e4b17023SJohn Marino    | ID     // typedef
705*e4b17023SJohn Marino    | (STRUCT|UNION) ID? gtymarker? ( '{' gtymarker? struct_field_seq '}' )?
706*e4b17023SJohn Marino    | ENUM ID ( '{' ... '}' )?
707*e4b17023SJohn Marino 
708*e4b17023SJohn Marino    Returns a partial type; under some conditions (notably
709*e4b17023SJohn Marino    "struct foo GTY((...)) thing;") it may write an options
710*e4b17023SJohn Marino    structure to *OPTSP.
711*e4b17023SJohn Marino */
712*e4b17023SJohn Marino static type_p
type(options_p * optsp,bool nested)713*e4b17023SJohn Marino type (options_p *optsp, bool nested)
714*e4b17023SJohn Marino {
715*e4b17023SJohn Marino   const char *s;
716*e4b17023SJohn Marino   *optsp = 0;
717*e4b17023SJohn Marino   switch (token ())
718*e4b17023SJohn Marino     {
719*e4b17023SJohn Marino     case SCALAR:
720*e4b17023SJohn Marino       s = advance ();
721*e4b17023SJohn Marino       return create_scalar_type (s);
722*e4b17023SJohn Marino 
723*e4b17023SJohn Marino     case ID:
724*e4b17023SJohn Marino     case VEC_TOKEN:
725*e4b17023SJohn Marino       s = typedef_name ();
726*e4b17023SJohn Marino       return resolve_typedef (s, &lexer_line);
727*e4b17023SJohn Marino 
728*e4b17023SJohn Marino     case STRUCT:
729*e4b17023SJohn Marino     case UNION:
730*e4b17023SJohn Marino       {
731*e4b17023SJohn Marino 	options_p opts = 0;
732*e4b17023SJohn Marino 	/* GTY annotations follow attribute syntax
733*e4b17023SJohn Marino 	   GTY_BEFORE_ID is for union/struct declarations
734*e4b17023SJohn Marino 	   GTY_AFTER_ID is for variable declarations.  */
735*e4b17023SJohn Marino 	enum
736*e4b17023SJohn Marino 	{
737*e4b17023SJohn Marino 	  NO_GTY,
738*e4b17023SJohn Marino 	  GTY_BEFORE_ID,
739*e4b17023SJohn Marino 	  GTY_AFTER_ID
740*e4b17023SJohn Marino 	} is_gty = NO_GTY;
741*e4b17023SJohn Marino 	bool is_union = (token () == UNION);
742*e4b17023SJohn Marino 	advance ();
743*e4b17023SJohn Marino 
744*e4b17023SJohn Marino 	/* Top-level structures that are not explicitly tagged GTY(())
745*e4b17023SJohn Marino 	   are treated as mere forward declarations.  This is because
746*e4b17023SJohn Marino 	   there are a lot of structures that we don't need to know
747*e4b17023SJohn Marino 	   about, and some of those have weird macro stuff in them
748*e4b17023SJohn Marino 	   that we can't handle.  */
749*e4b17023SJohn Marino 	if (nested || token () == GTY_TOKEN)
750*e4b17023SJohn Marino 	  {
751*e4b17023SJohn Marino 	    is_gty = GTY_BEFORE_ID;
752*e4b17023SJohn Marino 	    opts = gtymarker_opt ();
753*e4b17023SJohn Marino 	  }
754*e4b17023SJohn Marino 
755*e4b17023SJohn Marino 	if (token () == ID)
756*e4b17023SJohn Marino 	  s = advance ();
757*e4b17023SJohn Marino 	else
758*e4b17023SJohn Marino 	  s = xasprintf ("anonymous:%s:%d",
759*e4b17023SJohn Marino 			 get_input_file_name (lexer_line.file),
760*e4b17023SJohn Marino 			 lexer_line.line);
761*e4b17023SJohn Marino 
762*e4b17023SJohn Marino 	/* Unfortunately above GTY_TOKEN check does not capture the
763*e4b17023SJohn Marino 	   typedef struct_type GTY case.  */
764*e4b17023SJohn Marino 	if (token () == GTY_TOKEN)
765*e4b17023SJohn Marino 	  {
766*e4b17023SJohn Marino 	    is_gty = GTY_AFTER_ID;
767*e4b17023SJohn Marino 	    opts = gtymarker_opt ();
768*e4b17023SJohn Marino 	  }
769*e4b17023SJohn Marino 
770*e4b17023SJohn Marino 	if (is_gty)
771*e4b17023SJohn Marino 	  {
772*e4b17023SJohn Marino 	    if (token () == '{')
773*e4b17023SJohn Marino 	      {
774*e4b17023SJohn Marino 		pair_p fields;
775*e4b17023SJohn Marino 
776*e4b17023SJohn Marino 		if (is_gty == GTY_AFTER_ID)
777*e4b17023SJohn Marino 		  parse_error ("GTY must be specified before identifier");
778*e4b17023SJohn Marino 
779*e4b17023SJohn Marino 		advance ();
780*e4b17023SJohn Marino 		fields = struct_field_seq ();
781*e4b17023SJohn Marino 		require ('}');
782*e4b17023SJohn Marino 		return new_structure (s, is_union, &lexer_line, fields, opts);
783*e4b17023SJohn Marino 	      }
784*e4b17023SJohn Marino 	  }
785*e4b17023SJohn Marino 	else if (token () == '{')
786*e4b17023SJohn Marino 	  consume_balanced ('{', '}');
787*e4b17023SJohn Marino 	if (opts)
788*e4b17023SJohn Marino 	  *optsp = opts;
789*e4b17023SJohn Marino 	return find_structure (s, is_union);
790*e4b17023SJohn Marino       }
791*e4b17023SJohn Marino 
792*e4b17023SJohn Marino     case ENUM:
793*e4b17023SJohn Marino       advance ();
794*e4b17023SJohn Marino       if (token () == ID)
795*e4b17023SJohn Marino 	s = advance ();
796*e4b17023SJohn Marino       else
797*e4b17023SJohn Marino 	s = xasprintf ("anonymous:%s:%d",
798*e4b17023SJohn Marino 		       get_input_file_name (lexer_line.file),
799*e4b17023SJohn Marino 		       lexer_line.line);
800*e4b17023SJohn Marino 
801*e4b17023SJohn Marino       if (token () == '{')
802*e4b17023SJohn Marino 	consume_balanced ('{', '}');
803*e4b17023SJohn Marino       return create_scalar_type (s);
804*e4b17023SJohn Marino 
805*e4b17023SJohn Marino     default:
806*e4b17023SJohn Marino       parse_error ("expected a type specifier, have %s", print_cur_token ());
807*e4b17023SJohn Marino       advance ();
808*e4b17023SJohn Marino       return create_scalar_type ("erroneous type");
809*e4b17023SJohn Marino     }
810*e4b17023SJohn Marino }
811*e4b17023SJohn Marino 
812*e4b17023SJohn Marino /* Top level constructs.  */
813*e4b17023SJohn Marino 
814*e4b17023SJohn Marino /* Dispatch declarations beginning with 'typedef'.  */
815*e4b17023SJohn Marino 
816*e4b17023SJohn Marino static void
typedef_decl(void)817*e4b17023SJohn Marino typedef_decl (void)
818*e4b17023SJohn Marino {
819*e4b17023SJohn Marino   type_p ty, dty;
820*e4b17023SJohn Marino   const char *name;
821*e4b17023SJohn Marino   options_p opts;
822*e4b17023SJohn Marino   bool another;
823*e4b17023SJohn Marino 
824*e4b17023SJohn Marino   gcc_assert (token () == TYPEDEF);
825*e4b17023SJohn Marino   advance ();
826*e4b17023SJohn Marino 
827*e4b17023SJohn Marino   ty = type (&opts, false);
828*e4b17023SJohn Marino   if (!ty)
829*e4b17023SJohn Marino     return;
830*e4b17023SJohn Marino   if (opts)
831*e4b17023SJohn Marino     parse_error ("GTY((...)) cannot be applied to a typedef");
832*e4b17023SJohn Marino   do
833*e4b17023SJohn Marino     {
834*e4b17023SJohn Marino       dty = declarator (ty, &name, &opts);
835*e4b17023SJohn Marino       if (opts)
836*e4b17023SJohn Marino 	parse_error ("GTY((...)) cannot be applied to a typedef");
837*e4b17023SJohn Marino 
838*e4b17023SJohn Marino       /* Yet another place where we could have junk (notably attributes)
839*e4b17023SJohn Marino 	 after the declarator.  */
840*e4b17023SJohn Marino       another = consume_until_comma_or_semi (false);
841*e4b17023SJohn Marino       if (dty)
842*e4b17023SJohn Marino 	do_typedef (name, dty, &lexer_line);
843*e4b17023SJohn Marino     }
844*e4b17023SJohn Marino   while (another);
845*e4b17023SJohn Marino }
846*e4b17023SJohn Marino 
847*e4b17023SJohn Marino /* Structure definition: type() does all the work.  */
848*e4b17023SJohn Marino 
849*e4b17023SJohn Marino static void
struct_or_union(void)850*e4b17023SJohn Marino struct_or_union (void)
851*e4b17023SJohn Marino {
852*e4b17023SJohn Marino   options_p dummy;
853*e4b17023SJohn Marino   type (&dummy, false);
854*e4b17023SJohn Marino   /* There may be junk after the type: notably, we cannot currently
855*e4b17023SJohn Marino      distinguish 'struct foo *function(prototype);' from 'struct foo;'
856*e4b17023SJohn Marino      ...  we could call declarator(), but it's a waste of time at
857*e4b17023SJohn Marino      present.  Instead, just eat whatever token is currently lookahead
858*e4b17023SJohn Marino      and go back to lexical skipping mode. */
859*e4b17023SJohn Marino   advance ();
860*e4b17023SJohn Marino }
861*e4b17023SJohn Marino 
862*e4b17023SJohn Marino /* GC root declaration:
863*e4b17023SJohn Marino    (extern|static) gtymarker? type ID array_declarators_opt (';'|'=')
864*e4b17023SJohn Marino    If the gtymarker is not present, we ignore the rest of the declaration.  */
865*e4b17023SJohn Marino static void
extern_or_static(void)866*e4b17023SJohn Marino extern_or_static (void)
867*e4b17023SJohn Marino {
868*e4b17023SJohn Marino   options_p opts, opts2, dopts;
869*e4b17023SJohn Marino   type_p ty, dty;
870*e4b17023SJohn Marino   const char *name;
871*e4b17023SJohn Marino   require2 (EXTERN, STATIC);
872*e4b17023SJohn Marino 
873*e4b17023SJohn Marino   if (token () != GTY_TOKEN)
874*e4b17023SJohn Marino     {
875*e4b17023SJohn Marino       advance ();
876*e4b17023SJohn Marino       return;
877*e4b17023SJohn Marino     }
878*e4b17023SJohn Marino 
879*e4b17023SJohn Marino   opts = gtymarker ();
880*e4b17023SJohn Marino   ty = type (&opts2, true);	/* if we get here, it's got a GTY(()) */
881*e4b17023SJohn Marino   dty = declarator (ty, &name, &dopts);
882*e4b17023SJohn Marino 
883*e4b17023SJohn Marino   if ((opts && dopts) || (opts && opts2) || (opts2 && dopts))
884*e4b17023SJohn Marino     parse_error ("GTY((...)) specified more than once for %s", name);
885*e4b17023SJohn Marino   else if (opts2)
886*e4b17023SJohn Marino     opts = opts2;
887*e4b17023SJohn Marino   else if (dopts)
888*e4b17023SJohn Marino     opts = dopts;
889*e4b17023SJohn Marino 
890*e4b17023SJohn Marino   if (dty)
891*e4b17023SJohn Marino     {
892*e4b17023SJohn Marino       note_variable (name, adjust_field_type (dty, opts), opts, &lexer_line);
893*e4b17023SJohn Marino       require2 (';', '=');
894*e4b17023SJohn Marino     }
895*e4b17023SJohn Marino }
896*e4b17023SJohn Marino 
897*e4b17023SJohn Marino /* Definition of a generic VEC structure:
898*e4b17023SJohn Marino 
899*e4b17023SJohn Marino    'DEF_VEC_[IPO]' '(' id ')' ';'
900*e4b17023SJohn Marino 
901*e4b17023SJohn Marino    Scalar VECs require slightly different treatment than otherwise -
902*e4b17023SJohn Marino    that's handled in note_def_vec, we just pass it along.*/
903*e4b17023SJohn Marino static void
def_vec(void)904*e4b17023SJohn Marino def_vec (void)
905*e4b17023SJohn Marino {
906*e4b17023SJohn Marino   bool is_scalar = (token () == DEFVEC_I);
907*e4b17023SJohn Marino   const char *type;
908*e4b17023SJohn Marino 
909*e4b17023SJohn Marino   require2 (DEFVEC_OP, DEFVEC_I);
910*e4b17023SJohn Marino   require ('(');
911*e4b17023SJohn Marino   type = require2 (ID, SCALAR);
912*e4b17023SJohn Marino   require (')');
913*e4b17023SJohn Marino   require (';');
914*e4b17023SJohn Marino 
915*e4b17023SJohn Marino   if (!type)
916*e4b17023SJohn Marino     return;
917*e4b17023SJohn Marino 
918*e4b17023SJohn Marino   note_def_vec (type, is_scalar, &lexer_line);
919*e4b17023SJohn Marino   note_def_vec_alloc (type, "none", &lexer_line);
920*e4b17023SJohn Marino }
921*e4b17023SJohn Marino 
922*e4b17023SJohn Marino /* Definition of an allocation strategy for a VEC structure:
923*e4b17023SJohn Marino 
924*e4b17023SJohn Marino    'DEF_VEC_ALLOC_[IPO]' '(' id ',' id ')' ';'
925*e4b17023SJohn Marino 
926*e4b17023SJohn Marino    For purposes of gengtype, this just declares a wrapper structure.  */
927*e4b17023SJohn Marino static void
def_vec_alloc(void)928*e4b17023SJohn Marino def_vec_alloc (void)
929*e4b17023SJohn Marino {
930*e4b17023SJohn Marino   const char *type, *astrat;
931*e4b17023SJohn Marino 
932*e4b17023SJohn Marino   require (DEFVEC_ALLOC);
933*e4b17023SJohn Marino   require ('(');
934*e4b17023SJohn Marino   type = require2 (ID, SCALAR);
935*e4b17023SJohn Marino   require (',');
936*e4b17023SJohn Marino   astrat = require (ID);
937*e4b17023SJohn Marino   require (')');
938*e4b17023SJohn Marino   require (';');
939*e4b17023SJohn Marino 
940*e4b17023SJohn Marino   if (!type || !astrat)
941*e4b17023SJohn Marino     return;
942*e4b17023SJohn Marino 
943*e4b17023SJohn Marino   note_def_vec_alloc (type, astrat, &lexer_line);
944*e4b17023SJohn Marino }
945*e4b17023SJohn Marino 
946*e4b17023SJohn Marino /* Parse the file FNAME for GC-relevant declarations and definitions.
947*e4b17023SJohn Marino    This is the only entry point to this file.  */
948*e4b17023SJohn Marino void
parse_file(const char * fname)949*e4b17023SJohn Marino parse_file (const char *fname)
950*e4b17023SJohn Marino {
951*e4b17023SJohn Marino   yybegin (fname);
952*e4b17023SJohn Marino   for (;;)
953*e4b17023SJohn Marino     {
954*e4b17023SJohn Marino       switch (token ())
955*e4b17023SJohn Marino 	{
956*e4b17023SJohn Marino 	case EXTERN:
957*e4b17023SJohn Marino 	case STATIC:
958*e4b17023SJohn Marino 	  extern_or_static ();
959*e4b17023SJohn Marino 	  break;
960*e4b17023SJohn Marino 
961*e4b17023SJohn Marino 	case STRUCT:
962*e4b17023SJohn Marino 	case UNION:
963*e4b17023SJohn Marino 	  struct_or_union ();
964*e4b17023SJohn Marino 	  break;
965*e4b17023SJohn Marino 
966*e4b17023SJohn Marino 	case TYPEDEF:
967*e4b17023SJohn Marino 	  typedef_decl ();
968*e4b17023SJohn Marino 	  break;
969*e4b17023SJohn Marino 
970*e4b17023SJohn Marino 	case DEFVEC_OP:
971*e4b17023SJohn Marino 	case DEFVEC_I:
972*e4b17023SJohn Marino 	  def_vec ();
973*e4b17023SJohn Marino 	  break;
974*e4b17023SJohn Marino 
975*e4b17023SJohn Marino 	case DEFVEC_ALLOC:
976*e4b17023SJohn Marino 	  def_vec_alloc ();
977*e4b17023SJohn Marino 	  break;
978*e4b17023SJohn Marino 
979*e4b17023SJohn Marino 	case EOF_TOKEN:
980*e4b17023SJohn Marino 	  goto eof;
981*e4b17023SJohn Marino 
982*e4b17023SJohn Marino 	default:
983*e4b17023SJohn Marino 	  parse_error ("unexpected top level token, %s", print_cur_token ());
984*e4b17023SJohn Marino 	  goto eof;
985*e4b17023SJohn Marino 	}
986*e4b17023SJohn Marino       lexer_toplevel_done = 1;
987*e4b17023SJohn Marino     }
988*e4b17023SJohn Marino 
989*e4b17023SJohn Marino  eof:
990*e4b17023SJohn Marino   advance ();
991*e4b17023SJohn Marino   yyend ();
992*e4b17023SJohn Marino }
993