1*4882a593Smuzhiyun /* SPDX-License-Identifier: GPL-2.0-or-later */
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * C global declaration parser for genksyms.
4*4882a593Smuzhiyun * Copyright 1996, 1997 Linux International.
5*4882a593Smuzhiyun *
6*4882a593Smuzhiyun * New implementation contributed by Richard Henderson <rth@tamu.edu>
7*4882a593Smuzhiyun * Based on original work by Bjorn Ekwall <bj0rn@blox.se>
8*4882a593Smuzhiyun *
9*4882a593Smuzhiyun * This file is part of the Linux modutils.
10*4882a593Smuzhiyun */
11*4882a593Smuzhiyun
12*4882a593Smuzhiyun %{
13*4882a593Smuzhiyun
14*4882a593Smuzhiyun #include <assert.h>
15*4882a593Smuzhiyun #include <stdlib.h>
16*4882a593Smuzhiyun #include <string.h>
17*4882a593Smuzhiyun #include "genksyms.h"
18*4882a593Smuzhiyun
19*4882a593Smuzhiyun static int is_typedef;
20*4882a593Smuzhiyun static int is_extern;
21*4882a593Smuzhiyun static char *current_name;
22*4882a593Smuzhiyun static struct string_list *decl_spec;
23*4882a593Smuzhiyun
24*4882a593Smuzhiyun static void yyerror(const char *);
25*4882a593Smuzhiyun
26*4882a593Smuzhiyun static inline void
remove_node(struct string_list ** p)27*4882a593Smuzhiyun remove_node(struct string_list **p)
28*4882a593Smuzhiyun {
29*4882a593Smuzhiyun struct string_list *node = *p;
30*4882a593Smuzhiyun *p = node->next;
31*4882a593Smuzhiyun free_node(node);
32*4882a593Smuzhiyun }
33*4882a593Smuzhiyun
34*4882a593Smuzhiyun static inline void
remove_list(struct string_list ** pb,struct string_list ** pe)35*4882a593Smuzhiyun remove_list(struct string_list **pb, struct string_list **pe)
36*4882a593Smuzhiyun {
37*4882a593Smuzhiyun struct string_list *b = *pb, *e = *pe;
38*4882a593Smuzhiyun *pb = e;
39*4882a593Smuzhiyun free_list(b, e);
40*4882a593Smuzhiyun }
41*4882a593Smuzhiyun
42*4882a593Smuzhiyun /* Record definition of a struct/union/enum */
record_compound(struct string_list ** keyw,struct string_list ** ident,struct string_list ** body,enum symbol_type type)43*4882a593Smuzhiyun static void record_compound(struct string_list **keyw,
44*4882a593Smuzhiyun struct string_list **ident,
45*4882a593Smuzhiyun struct string_list **body,
46*4882a593Smuzhiyun enum symbol_type type)
47*4882a593Smuzhiyun {
48*4882a593Smuzhiyun struct string_list *b = *body, *i = *ident, *r;
49*4882a593Smuzhiyun
50*4882a593Smuzhiyun if (i->in_source_file) {
51*4882a593Smuzhiyun remove_node(keyw);
52*4882a593Smuzhiyun (*ident)->tag = type;
53*4882a593Smuzhiyun remove_list(body, ident);
54*4882a593Smuzhiyun return;
55*4882a593Smuzhiyun }
56*4882a593Smuzhiyun r = copy_node(i); r->tag = type;
57*4882a593Smuzhiyun r->next = (*keyw)->next; *body = r; (*keyw)->next = NULL;
58*4882a593Smuzhiyun add_symbol(i->string, type, b, is_extern);
59*4882a593Smuzhiyun }
60*4882a593Smuzhiyun
61*4882a593Smuzhiyun %}
62*4882a593Smuzhiyun
63*4882a593Smuzhiyun %token ASM_KEYW
64*4882a593Smuzhiyun %token ATTRIBUTE_KEYW
65*4882a593Smuzhiyun %token AUTO_KEYW
66*4882a593Smuzhiyun %token BOOL_KEYW
67*4882a593Smuzhiyun %token BUILTIN_INT_KEYW
68*4882a593Smuzhiyun %token CHAR_KEYW
69*4882a593Smuzhiyun %token CONST_KEYW
70*4882a593Smuzhiyun %token DOUBLE_KEYW
71*4882a593Smuzhiyun %token ENUM_KEYW
72*4882a593Smuzhiyun %token EXTERN_KEYW
73*4882a593Smuzhiyun %token EXTENSION_KEYW
74*4882a593Smuzhiyun %token FLOAT_KEYW
75*4882a593Smuzhiyun %token INLINE_KEYW
76*4882a593Smuzhiyun %token INT_KEYW
77*4882a593Smuzhiyun %token LONG_KEYW
78*4882a593Smuzhiyun %token REGISTER_KEYW
79*4882a593Smuzhiyun %token RESTRICT_KEYW
80*4882a593Smuzhiyun %token SHORT_KEYW
81*4882a593Smuzhiyun %token SIGNED_KEYW
82*4882a593Smuzhiyun %token STATIC_KEYW
83*4882a593Smuzhiyun %token STRUCT_KEYW
84*4882a593Smuzhiyun %token TYPEDEF_KEYW
85*4882a593Smuzhiyun %token UNION_KEYW
86*4882a593Smuzhiyun %token UNSIGNED_KEYW
87*4882a593Smuzhiyun %token VOID_KEYW
88*4882a593Smuzhiyun %token VOLATILE_KEYW
89*4882a593Smuzhiyun %token TYPEOF_KEYW
90*4882a593Smuzhiyun %token VA_LIST_KEYW
91*4882a593Smuzhiyun
92*4882a593Smuzhiyun %token EXPORT_SYMBOL_KEYW
93*4882a593Smuzhiyun
94*4882a593Smuzhiyun %token ASM_PHRASE
95*4882a593Smuzhiyun %token ATTRIBUTE_PHRASE
96*4882a593Smuzhiyun %token TYPEOF_PHRASE
97*4882a593Smuzhiyun %token BRACE_PHRASE
98*4882a593Smuzhiyun %token BRACKET_PHRASE
99*4882a593Smuzhiyun %token EXPRESSION_PHRASE
100*4882a593Smuzhiyun
101*4882a593Smuzhiyun %token CHAR
102*4882a593Smuzhiyun %token DOTS
103*4882a593Smuzhiyun %token IDENT
104*4882a593Smuzhiyun %token INT
105*4882a593Smuzhiyun %token REAL
106*4882a593Smuzhiyun %token STRING
107*4882a593Smuzhiyun %token TYPE
108*4882a593Smuzhiyun %token OTHER
109*4882a593Smuzhiyun %token FILENAME
110*4882a593Smuzhiyun
111*4882a593Smuzhiyun %%
112*4882a593Smuzhiyun
113*4882a593Smuzhiyun declaration_seq:
114*4882a593Smuzhiyun declaration
115*4882a593Smuzhiyun | declaration_seq declaration
116*4882a593Smuzhiyun ;
117*4882a593Smuzhiyun
118*4882a593Smuzhiyun declaration:
119*4882a593Smuzhiyun { is_typedef = 0; is_extern = 0; current_name = NULL; decl_spec = NULL; }
120*4882a593Smuzhiyun declaration1
121*4882a593Smuzhiyun { free_list(*$2, NULL); *$2 = NULL; }
122*4882a593Smuzhiyun ;
123*4882a593Smuzhiyun
124*4882a593Smuzhiyun declaration1:
125*4882a593Smuzhiyun EXTENSION_KEYW TYPEDEF_KEYW { is_typedef = 1; } simple_declaration
126*4882a593Smuzhiyun { $$ = $4; }
127*4882a593Smuzhiyun | TYPEDEF_KEYW { is_typedef = 1; } simple_declaration
128*4882a593Smuzhiyun { $$ = $3; }
129*4882a593Smuzhiyun | simple_declaration
130*4882a593Smuzhiyun | function_definition
131*4882a593Smuzhiyun | asm_definition
132*4882a593Smuzhiyun | export_definition
133*4882a593Smuzhiyun | error ';' { $$ = $2; }
134*4882a593Smuzhiyun | error '}' { $$ = $2; }
135*4882a593Smuzhiyun ;
136*4882a593Smuzhiyun
137*4882a593Smuzhiyun simple_declaration:
138*4882a593Smuzhiyun decl_specifier_seq_opt init_declarator_list_opt ';'
139*4882a593Smuzhiyun { if (current_name) {
140*4882a593Smuzhiyun struct string_list *decl = (*$3)->next;
141*4882a593Smuzhiyun (*$3)->next = NULL;
142*4882a593Smuzhiyun add_symbol(current_name,
143*4882a593Smuzhiyun is_typedef ? SYM_TYPEDEF : SYM_NORMAL,
144*4882a593Smuzhiyun decl, is_extern);
145*4882a593Smuzhiyun current_name = NULL;
146*4882a593Smuzhiyun }
147*4882a593Smuzhiyun $$ = $3;
148*4882a593Smuzhiyun }
149*4882a593Smuzhiyun ;
150*4882a593Smuzhiyun
151*4882a593Smuzhiyun init_declarator_list_opt:
152*4882a593Smuzhiyun /* empty */ { $$ = NULL; }
153*4882a593Smuzhiyun | init_declarator_list
154*4882a593Smuzhiyun ;
155*4882a593Smuzhiyun
156*4882a593Smuzhiyun init_declarator_list:
157*4882a593Smuzhiyun init_declarator
158*4882a593Smuzhiyun { struct string_list *decl = *$1;
159*4882a593Smuzhiyun *$1 = NULL;
160*4882a593Smuzhiyun add_symbol(current_name,
161*4882a593Smuzhiyun is_typedef ? SYM_TYPEDEF : SYM_NORMAL, decl, is_extern);
162*4882a593Smuzhiyun current_name = NULL;
163*4882a593Smuzhiyun $$ = $1;
164*4882a593Smuzhiyun }
165*4882a593Smuzhiyun | init_declarator_list ',' init_declarator
166*4882a593Smuzhiyun { struct string_list *decl = *$3;
167*4882a593Smuzhiyun *$3 = NULL;
168*4882a593Smuzhiyun free_list(*$2, NULL);
169*4882a593Smuzhiyun *$2 = decl_spec;
170*4882a593Smuzhiyun add_symbol(current_name,
171*4882a593Smuzhiyun is_typedef ? SYM_TYPEDEF : SYM_NORMAL, decl, is_extern);
172*4882a593Smuzhiyun current_name = NULL;
173*4882a593Smuzhiyun $$ = $3;
174*4882a593Smuzhiyun }
175*4882a593Smuzhiyun ;
176*4882a593Smuzhiyun
177*4882a593Smuzhiyun init_declarator:
178*4882a593Smuzhiyun declarator asm_phrase_opt attribute_opt initializer_opt
179*4882a593Smuzhiyun { $$ = $4 ? $4 : $3 ? $3 : $2 ? $2 : $1; }
180*4882a593Smuzhiyun ;
181*4882a593Smuzhiyun
182*4882a593Smuzhiyun /* Hang on to the specifiers so that we can reuse them. */
183*4882a593Smuzhiyun decl_specifier_seq_opt:
184*4882a593Smuzhiyun /* empty */ { decl_spec = NULL; }
185*4882a593Smuzhiyun | decl_specifier_seq
186*4882a593Smuzhiyun ;
187*4882a593Smuzhiyun
188*4882a593Smuzhiyun decl_specifier_seq:
189*4882a593Smuzhiyun decl_specifier { decl_spec = *$1; }
190*4882a593Smuzhiyun | decl_specifier_seq decl_specifier { decl_spec = *$2; }
191*4882a593Smuzhiyun ;
192*4882a593Smuzhiyun
193*4882a593Smuzhiyun decl_specifier:
194*4882a593Smuzhiyun storage_class_specifier
195*4882a593Smuzhiyun { /* Version 2 checksumming ignores storage class, as that
196*4882a593Smuzhiyun is really irrelevant to the linkage. */
197*4882a593Smuzhiyun remove_node($1);
198*4882a593Smuzhiyun $$ = $1;
199*4882a593Smuzhiyun }
200*4882a593Smuzhiyun | type_specifier
201*4882a593Smuzhiyun ;
202*4882a593Smuzhiyun
203*4882a593Smuzhiyun storage_class_specifier:
204*4882a593Smuzhiyun AUTO_KEYW
205*4882a593Smuzhiyun | REGISTER_KEYW
206*4882a593Smuzhiyun | STATIC_KEYW
207*4882a593Smuzhiyun | EXTERN_KEYW { is_extern = 1; $$ = $1; }
208*4882a593Smuzhiyun | INLINE_KEYW { is_extern = 0; $$ = $1; }
209*4882a593Smuzhiyun ;
210*4882a593Smuzhiyun
211*4882a593Smuzhiyun type_specifier:
212*4882a593Smuzhiyun simple_type_specifier
213*4882a593Smuzhiyun | cvar_qualifier
214*4882a593Smuzhiyun | TYPEOF_KEYW '(' parameter_declaration ')'
215*4882a593Smuzhiyun | TYPEOF_PHRASE
216*4882a593Smuzhiyun
217*4882a593Smuzhiyun /* References to s/u/e's defined elsewhere. Rearrange things
218*4882a593Smuzhiyun so that it is easier to expand the definition fully later. */
219*4882a593Smuzhiyun | STRUCT_KEYW IDENT
220*4882a593Smuzhiyun { remove_node($1); (*$2)->tag = SYM_STRUCT; $$ = $2; }
221*4882a593Smuzhiyun | UNION_KEYW IDENT
222*4882a593Smuzhiyun { remove_node($1); (*$2)->tag = SYM_UNION; $$ = $2; }
223*4882a593Smuzhiyun | ENUM_KEYW IDENT
224*4882a593Smuzhiyun { remove_node($1); (*$2)->tag = SYM_ENUM; $$ = $2; }
225*4882a593Smuzhiyun
226*4882a593Smuzhiyun /* Full definitions of an s/u/e. Record it. */
227*4882a593Smuzhiyun | STRUCT_KEYW IDENT class_body
228*4882a593Smuzhiyun { record_compound($1, $2, $3, SYM_STRUCT); $$ = $3; }
229*4882a593Smuzhiyun | UNION_KEYW IDENT class_body
230*4882a593Smuzhiyun { record_compound($1, $2, $3, SYM_UNION); $$ = $3; }
231*4882a593Smuzhiyun | ENUM_KEYW IDENT enum_body
232*4882a593Smuzhiyun { record_compound($1, $2, $3, SYM_ENUM); $$ = $3; }
233*4882a593Smuzhiyun /*
234*4882a593Smuzhiyun * Anonymous enum definition. Tell add_symbol() to restart its counter.
235*4882a593Smuzhiyun */
236*4882a593Smuzhiyun | ENUM_KEYW enum_body
237*4882a593Smuzhiyun { add_symbol(NULL, SYM_ENUM, NULL, 0); $$ = $2; }
238*4882a593Smuzhiyun /* Anonymous s/u definitions. Nothing needs doing. */
239*4882a593Smuzhiyun | STRUCT_KEYW class_body { $$ = $2; }
240*4882a593Smuzhiyun | UNION_KEYW class_body { $$ = $2; }
241*4882a593Smuzhiyun ;
242*4882a593Smuzhiyun
243*4882a593Smuzhiyun simple_type_specifier:
244*4882a593Smuzhiyun CHAR_KEYW
245*4882a593Smuzhiyun | SHORT_KEYW
246*4882a593Smuzhiyun | INT_KEYW
247*4882a593Smuzhiyun | LONG_KEYW
248*4882a593Smuzhiyun | SIGNED_KEYW
249*4882a593Smuzhiyun | UNSIGNED_KEYW
250*4882a593Smuzhiyun | FLOAT_KEYW
251*4882a593Smuzhiyun | DOUBLE_KEYW
252*4882a593Smuzhiyun | VOID_KEYW
253*4882a593Smuzhiyun | BOOL_KEYW
254*4882a593Smuzhiyun | VA_LIST_KEYW
255*4882a593Smuzhiyun | BUILTIN_INT_KEYW
256*4882a593Smuzhiyun | TYPE { (*$1)->tag = SYM_TYPEDEF; $$ = $1; }
257*4882a593Smuzhiyun ;
258*4882a593Smuzhiyun
259*4882a593Smuzhiyun ptr_operator:
260*4882a593Smuzhiyun '*' cvar_qualifier_seq_opt
261*4882a593Smuzhiyun { $$ = $2 ? $2 : $1; }
262*4882a593Smuzhiyun ;
263*4882a593Smuzhiyun
264*4882a593Smuzhiyun cvar_qualifier_seq_opt:
265*4882a593Smuzhiyun /* empty */ { $$ = NULL; }
266*4882a593Smuzhiyun | cvar_qualifier_seq
267*4882a593Smuzhiyun ;
268*4882a593Smuzhiyun
269*4882a593Smuzhiyun cvar_qualifier_seq:
270*4882a593Smuzhiyun cvar_qualifier
271*4882a593Smuzhiyun | cvar_qualifier_seq cvar_qualifier { $$ = $2; }
272*4882a593Smuzhiyun ;
273*4882a593Smuzhiyun
274*4882a593Smuzhiyun cvar_qualifier:
275*4882a593Smuzhiyun CONST_KEYW | VOLATILE_KEYW | ATTRIBUTE_PHRASE
276*4882a593Smuzhiyun | RESTRICT_KEYW
277*4882a593Smuzhiyun { /* restrict has no effect in prototypes so ignore it */
278*4882a593Smuzhiyun remove_node($1);
279*4882a593Smuzhiyun $$ = $1;
280*4882a593Smuzhiyun }
281*4882a593Smuzhiyun ;
282*4882a593Smuzhiyun
283*4882a593Smuzhiyun declarator:
284*4882a593Smuzhiyun ptr_operator declarator { $$ = $2; }
285*4882a593Smuzhiyun | direct_declarator
286*4882a593Smuzhiyun ;
287*4882a593Smuzhiyun
288*4882a593Smuzhiyun direct_declarator:
289*4882a593Smuzhiyun IDENT
290*4882a593Smuzhiyun { if (current_name != NULL) {
291*4882a593Smuzhiyun error_with_pos("unexpected second declaration name");
292*4882a593Smuzhiyun YYERROR;
293*4882a593Smuzhiyun } else {
294*4882a593Smuzhiyun current_name = (*$1)->string;
295*4882a593Smuzhiyun $$ = $1;
296*4882a593Smuzhiyun }
297*4882a593Smuzhiyun }
298*4882a593Smuzhiyun | TYPE
299*4882a593Smuzhiyun { if (current_name != NULL) {
300*4882a593Smuzhiyun error_with_pos("unexpected second declaration name");
301*4882a593Smuzhiyun YYERROR;
302*4882a593Smuzhiyun } else {
303*4882a593Smuzhiyun current_name = (*$1)->string;
304*4882a593Smuzhiyun $$ = $1;
305*4882a593Smuzhiyun }
306*4882a593Smuzhiyun }
307*4882a593Smuzhiyun | direct_declarator '(' parameter_declaration_clause ')'
308*4882a593Smuzhiyun { $$ = $4; }
309*4882a593Smuzhiyun | direct_declarator '(' error ')'
310*4882a593Smuzhiyun { $$ = $4; }
311*4882a593Smuzhiyun | direct_declarator BRACKET_PHRASE
312*4882a593Smuzhiyun { $$ = $2; }
313*4882a593Smuzhiyun | '(' declarator ')'
314*4882a593Smuzhiyun { $$ = $3; }
315*4882a593Smuzhiyun ;
316*4882a593Smuzhiyun
317*4882a593Smuzhiyun /* Nested declarators differ from regular declarators in that they do
318*4882a593Smuzhiyun not record the symbols they find in the global symbol table. */
319*4882a593Smuzhiyun nested_declarator:
320*4882a593Smuzhiyun ptr_operator nested_declarator { $$ = $2; }
321*4882a593Smuzhiyun | direct_nested_declarator
322*4882a593Smuzhiyun ;
323*4882a593Smuzhiyun
324*4882a593Smuzhiyun direct_nested_declarator:
325*4882a593Smuzhiyun IDENT
326*4882a593Smuzhiyun | TYPE
327*4882a593Smuzhiyun | direct_nested_declarator '(' parameter_declaration_clause ')'
328*4882a593Smuzhiyun { $$ = $4; }
329*4882a593Smuzhiyun | direct_nested_declarator '(' error ')'
330*4882a593Smuzhiyun { $$ = $4; }
331*4882a593Smuzhiyun | direct_nested_declarator BRACKET_PHRASE
332*4882a593Smuzhiyun { $$ = $2; }
333*4882a593Smuzhiyun | '(' nested_declarator ')'
334*4882a593Smuzhiyun { $$ = $3; }
335*4882a593Smuzhiyun | '(' error ')'
336*4882a593Smuzhiyun { $$ = $3; }
337*4882a593Smuzhiyun ;
338*4882a593Smuzhiyun
339*4882a593Smuzhiyun parameter_declaration_clause:
340*4882a593Smuzhiyun parameter_declaration_list_opt DOTS { $$ = $2; }
341*4882a593Smuzhiyun | parameter_declaration_list_opt
342*4882a593Smuzhiyun | parameter_declaration_list ',' DOTS { $$ = $3; }
343*4882a593Smuzhiyun ;
344*4882a593Smuzhiyun
345*4882a593Smuzhiyun parameter_declaration_list_opt:
346*4882a593Smuzhiyun /* empty */ { $$ = NULL; }
347*4882a593Smuzhiyun | parameter_declaration_list
348*4882a593Smuzhiyun ;
349*4882a593Smuzhiyun
350*4882a593Smuzhiyun parameter_declaration_list:
351*4882a593Smuzhiyun parameter_declaration
352*4882a593Smuzhiyun | parameter_declaration_list ',' parameter_declaration
353*4882a593Smuzhiyun { $$ = $3; }
354*4882a593Smuzhiyun ;
355*4882a593Smuzhiyun
356*4882a593Smuzhiyun parameter_declaration:
357*4882a593Smuzhiyun decl_specifier_seq m_abstract_declarator
358*4882a593Smuzhiyun { $$ = $2 ? $2 : $1; }
359*4882a593Smuzhiyun ;
360*4882a593Smuzhiyun
361*4882a593Smuzhiyun m_abstract_declarator:
362*4882a593Smuzhiyun ptr_operator m_abstract_declarator
363*4882a593Smuzhiyun { $$ = $2 ? $2 : $1; }
364*4882a593Smuzhiyun | direct_m_abstract_declarator
365*4882a593Smuzhiyun ;
366*4882a593Smuzhiyun
367*4882a593Smuzhiyun direct_m_abstract_declarator:
368*4882a593Smuzhiyun /* empty */ { $$ = NULL; }
369*4882a593Smuzhiyun | IDENT
370*4882a593Smuzhiyun { /* For version 2 checksums, we don't want to remember
371*4882a593Smuzhiyun private parameter names. */
372*4882a593Smuzhiyun remove_node($1);
373*4882a593Smuzhiyun $$ = $1;
374*4882a593Smuzhiyun }
375*4882a593Smuzhiyun /* This wasn't really a typedef name but an identifier that
376*4882a593Smuzhiyun shadows one. */
377*4882a593Smuzhiyun | TYPE
378*4882a593Smuzhiyun { remove_node($1);
379*4882a593Smuzhiyun $$ = $1;
380*4882a593Smuzhiyun }
381*4882a593Smuzhiyun | direct_m_abstract_declarator '(' parameter_declaration_clause ')'
382*4882a593Smuzhiyun { $$ = $4; }
383*4882a593Smuzhiyun | direct_m_abstract_declarator '(' error ')'
384*4882a593Smuzhiyun { $$ = $4; }
385*4882a593Smuzhiyun | direct_m_abstract_declarator BRACKET_PHRASE
386*4882a593Smuzhiyun { $$ = $2; }
387*4882a593Smuzhiyun | '(' m_abstract_declarator ')'
388*4882a593Smuzhiyun { $$ = $3; }
389*4882a593Smuzhiyun | '(' error ')'
390*4882a593Smuzhiyun { $$ = $3; }
391*4882a593Smuzhiyun ;
392*4882a593Smuzhiyun
393*4882a593Smuzhiyun function_definition:
394*4882a593Smuzhiyun decl_specifier_seq_opt declarator BRACE_PHRASE
395*4882a593Smuzhiyun { struct string_list *decl = *$2;
396*4882a593Smuzhiyun *$2 = NULL;
397*4882a593Smuzhiyun add_symbol(current_name, SYM_NORMAL, decl, is_extern);
398*4882a593Smuzhiyun $$ = $3;
399*4882a593Smuzhiyun }
400*4882a593Smuzhiyun ;
401*4882a593Smuzhiyun
402*4882a593Smuzhiyun initializer_opt:
403*4882a593Smuzhiyun /* empty */ { $$ = NULL; }
404*4882a593Smuzhiyun | initializer
405*4882a593Smuzhiyun ;
406*4882a593Smuzhiyun
407*4882a593Smuzhiyun /* We never care about the contents of an initializer. */
408*4882a593Smuzhiyun initializer:
409*4882a593Smuzhiyun '=' EXPRESSION_PHRASE
410*4882a593Smuzhiyun { remove_list($2, &(*$1)->next); $$ = $2; }
411*4882a593Smuzhiyun ;
412*4882a593Smuzhiyun
413*4882a593Smuzhiyun class_body:
414*4882a593Smuzhiyun '{' member_specification_opt '}' { $$ = $3; }
415*4882a593Smuzhiyun | '{' error '}' { $$ = $3; }
416*4882a593Smuzhiyun ;
417*4882a593Smuzhiyun
418*4882a593Smuzhiyun member_specification_opt:
419*4882a593Smuzhiyun /* empty */ { $$ = NULL; }
420*4882a593Smuzhiyun | member_specification
421*4882a593Smuzhiyun ;
422*4882a593Smuzhiyun
423*4882a593Smuzhiyun member_specification:
424*4882a593Smuzhiyun member_declaration
425*4882a593Smuzhiyun | member_specification member_declaration { $$ = $2; }
426*4882a593Smuzhiyun ;
427*4882a593Smuzhiyun
428*4882a593Smuzhiyun member_declaration:
429*4882a593Smuzhiyun decl_specifier_seq_opt member_declarator_list_opt ';'
430*4882a593Smuzhiyun { $$ = $3; }
431*4882a593Smuzhiyun | error ';'
432*4882a593Smuzhiyun { $$ = $2; }
433*4882a593Smuzhiyun ;
434*4882a593Smuzhiyun
435*4882a593Smuzhiyun member_declarator_list_opt:
436*4882a593Smuzhiyun /* empty */ { $$ = NULL; }
437*4882a593Smuzhiyun | member_declarator_list
438*4882a593Smuzhiyun ;
439*4882a593Smuzhiyun
440*4882a593Smuzhiyun member_declarator_list:
441*4882a593Smuzhiyun member_declarator
442*4882a593Smuzhiyun | member_declarator_list ',' member_declarator { $$ = $3; }
443*4882a593Smuzhiyun ;
444*4882a593Smuzhiyun
445*4882a593Smuzhiyun member_declarator:
446*4882a593Smuzhiyun nested_declarator attribute_opt { $$ = $2 ? $2 : $1; }
447*4882a593Smuzhiyun | IDENT member_bitfield_declarator { $$ = $2; }
448*4882a593Smuzhiyun | member_bitfield_declarator
449*4882a593Smuzhiyun ;
450*4882a593Smuzhiyun
451*4882a593Smuzhiyun member_bitfield_declarator:
452*4882a593Smuzhiyun ':' EXPRESSION_PHRASE { $$ = $2; }
453*4882a593Smuzhiyun ;
454*4882a593Smuzhiyun
455*4882a593Smuzhiyun attribute_opt:
456*4882a593Smuzhiyun /* empty */ { $$ = NULL; }
457*4882a593Smuzhiyun | attribute_opt ATTRIBUTE_PHRASE
458*4882a593Smuzhiyun ;
459*4882a593Smuzhiyun
460*4882a593Smuzhiyun enum_body:
461*4882a593Smuzhiyun '{' enumerator_list '}' { $$ = $3; }
462*4882a593Smuzhiyun | '{' enumerator_list ',' '}' { $$ = $4; }
463*4882a593Smuzhiyun ;
464*4882a593Smuzhiyun
465*4882a593Smuzhiyun enumerator_list:
466*4882a593Smuzhiyun enumerator
467*4882a593Smuzhiyun | enumerator_list ',' enumerator
468*4882a593Smuzhiyun
469*4882a593Smuzhiyun enumerator:
470*4882a593Smuzhiyun IDENT
471*4882a593Smuzhiyun {
472*4882a593Smuzhiyun const char *name = strdup((*$1)->string);
473*4882a593Smuzhiyun add_symbol(name, SYM_ENUM_CONST, NULL, 0);
474*4882a593Smuzhiyun }
475*4882a593Smuzhiyun | IDENT '=' EXPRESSION_PHRASE
476*4882a593Smuzhiyun {
477*4882a593Smuzhiyun const char *name = strdup((*$1)->string);
478*4882a593Smuzhiyun struct string_list *expr = copy_list_range(*$3, *$2);
479*4882a593Smuzhiyun add_symbol(name, SYM_ENUM_CONST, expr, 0);
480*4882a593Smuzhiyun }
481*4882a593Smuzhiyun
482*4882a593Smuzhiyun asm_definition:
483*4882a593Smuzhiyun ASM_PHRASE ';' { $$ = $2; }
484*4882a593Smuzhiyun ;
485*4882a593Smuzhiyun
486*4882a593Smuzhiyun asm_phrase_opt:
487*4882a593Smuzhiyun /* empty */ { $$ = NULL; }
488*4882a593Smuzhiyun | ASM_PHRASE
489*4882a593Smuzhiyun ;
490*4882a593Smuzhiyun
491*4882a593Smuzhiyun export_definition:
492*4882a593Smuzhiyun EXPORT_SYMBOL_KEYW '(' IDENT ')' ';'
493*4882a593Smuzhiyun { export_symbol((*$3)->string); $$ = $5; }
494*4882a593Smuzhiyun ;
495*4882a593Smuzhiyun
496*4882a593Smuzhiyun
497*4882a593Smuzhiyun %%
498*4882a593Smuzhiyun
499*4882a593Smuzhiyun static void
500*4882a593Smuzhiyun yyerror(const char *e)
501*4882a593Smuzhiyun {
502*4882a593Smuzhiyun error_with_pos("%s", e);
503*4882a593Smuzhiyun }
504