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