File Index
Files and directories
Sign in
FILE

parse.y

File preview with syntax highlighting.

linux-6.19.14/scripts/genksyms/parse.y PLAIN TEXT
  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
 20static int is_typedef;
 21static int is_extern;
 22static char *current_name;
 23static struct string_list *decl_spec;
 24
 25static void yyerror(const char *);
 26
 27static inline void
 28remove_node(struct string_list **p)
 29{
 30  struct string_list *node = *p;
 31  *p = node->next;
 32  free_node(node);
 33}
 34
 35static inline void
 36remove_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 */
 44static 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
118declaration_seq:
119	declaration
120	| declaration_seq declaration
121	;
122
123declaration:
124	{ is_typedef = 0; is_extern = 0; current_name = NULL; decl_spec = NULL; }
125	declaration1
126	{ free_list(*$2, NULL); *$2 = NULL; }
127	;
128
129declaration1:
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
143simple_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
158init_declarator_list_opt:
159	/* empty */			{ $$ = NULL; }
160	| init_declarator_list		{ free_list(decl_spec, NULL); $$ = $1; }
161	;
162
163init_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
196init_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.  */
202decl_specifier_seq_opt:
203	/* empty */				{ decl_spec = NULL; }
204	| decl_specifier_seq
205	;
206
207decl_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
213decl_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
224storage_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
232type_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
263simple_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
279ptr_operator:
280	'*' type_qualifier_seq_opt
281		{ $$ = $2 ? $2 : $1; }
282	;
283
284type_qualifier_seq_opt:
285	/* empty */					{ $$ = NULL; }
286	| type_qualifier_seq
287	;
288
289type_qualifier_seq:
290	type_qualifier
291	| ATTRIBUTE_PHRASE
292	| type_qualifier_seq type_qualifier		{ $$ = $2; }
293	| type_qualifier_seq ATTRIBUTE_PHRASE		{ $$ = $2; }
294	;
295
296type_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
306declarator:
307	ptr_operator declarator			{ $$ = $2; }
308	| direct_declarator
309	;
310
311direct_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.  */
334nested_declarator:
335	ptr_operator nested_declarator		{ $$ = $2; }
336	| direct_nested_declarator
337	;
338
339direct_nested_declarator:
340	direct_nested_declarator1
341	| direct_nested_declarator1 '(' parameter_declaration_clause ')'
342		{ $$ = $4; }
343	;
344
345direct_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
357parameter_declaration_clause:
358	parameter_declaration_list_opt DOTS		{ $$ = $2; }
359	| parameter_declaration_list_opt
360	| parameter_declaration_list ',' DOTS		{ $$ = $3; }
361	;
362
363parameter_declaration_list_opt:
364	/* empty */					{ $$ = NULL; }
365	| parameter_declaration_list
366	;
367
368parameter_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
375parameter_declaration:
376	decl_specifier_seq abstract_declarator_opt
377		{ $$ = $2 ? $2 : $1; }
378	;
379
380abstract_declarator_opt:
381	/* empty */				{ $$ = NULL; }
382	| abstract_declarator
383	;
384
385abstract_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
393direct_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
401direct_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
419open_paren:
420	'('	{ $$ = $1; dont_want_type_specifier = false; }
421	;
422
423function_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
432initializer_opt:
433	/* empty */					{ $$ = NULL; }
434	| initializer
435	;
436
437/* We never care about the contents of an initializer.  */
438initializer:
439	'=' EXPRESSION_PHRASE
440		{ remove_list($2, &(*$1)->next); $$ = $2; }
441	;
442
443class_body:
444	'{' member_specification_opt '}'		{ $$ = $3; }
445	| '{' error '}'					{ $$ = $3; }
446	;
447
448member_specification_opt:
449	/* empty */					{ $$ = NULL; }
450	| member_specification
451	;
452
453member_specification:
454	member_declaration
455	| member_specification member_declaration	{ $$ = $2; }
456	;
457
458member_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
465member_declarator_list_opt:
466	/* empty */					{ $$ = NULL; }
467	| member_declarator_list
468	;
469
470member_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
477member_declarator:
478	nested_declarator attribute_opt			{ $$ = $2 ? $2 : $1; }
479	| IDENT member_bitfield_declarator		{ $$ = $2; }
480	| member_bitfield_declarator
481	;
482
483member_bitfield_declarator:
484	':' EXPRESSION_PHRASE				{ $$ = $2; }
485	;
486
487attribute_opt:
488	/* empty */					{ $$ = NULL; }
489	| attribute_opt ATTRIBUTE_PHRASE		{ $$ = $2; }
490	;
491
492enum_body:
493	'{' enumerator_list '}'				{ $$ = $3; }
494	| '{' enumerator_list ',' '}'			{ $$ = $4; }
495	 ;
496
497enumerator_list:
498	enumerator
499	| enumerator_list ',' enumerator
500
501enumerator:
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
514asm_definition:
515	ASM_PHRASE ';'					{ $$ = $2; }
516	;
517
518asm_phrase_opt:
519	/* empty */					{ $$ = NULL; }
520	| ASM_PHRASE
521	;
522
523export_definition:
524	EXPORT_SYMBOL_KEYW '(' IDENT ')' ';'
525		{ export_symbol((*$3)->string); $$ = $5; }
526	;
527
528/* Ignore any module scoped _Static_assert(...) */
529static_assert:
530	STATIC_ASSERT_PHRASE ';'			{ $$ = $2; }
531	;
532
533%%
534
535static void
536yyerror(const char *e)
537{
538  error_with_pos("%s", e);
539}
~/ Read-only file preview.