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