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