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