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