0001 /* SPDX-License-Identifier: GPL-2.0-or-later */
0002 /*
0003 * C global declaration parser for genksyms.
0004 * Copyright 1996, 1997 Linux International.
0005 *
0006 * New implementation contributed by Richard Henderson <rth@tamu.edu>
0007 * Based on original work by Bjorn Ekwall <bj0rn@blox.se>
0008 *
0009 * This file is part of the Linux modutils.
0010 */
0011
0012 %{
0013
0014 #include <assert.h>
0015 #include <stdlib.h>
0016 #include <string.h>
0017 #include "genksyms.h"
0018
0019 static int is_typedef;
0020 static int is_extern;
0021 static char *current_name;
0022 static struct string_list *decl_spec;
0023
0024 static void yyerror(const char *);
0025
0026 static inline void
0027 remove_node(struct string_list **p)
0028 {
0029 struct string_list *node = *p;
0030 *p = node->next;
0031 free_node(node);
0032 }
0033
0034 static inline void
0035 remove_list(struct string_list **pb, struct string_list **pe)
0036 {
0037 struct string_list *b = *pb, *e = *pe;
0038 *pb = e;
0039 free_list(b, e);
0040 }
0041
0042 /* Record definition of a struct/union/enum */
0043 static void record_compound(struct string_list **keyw,
0044 struct string_list **ident,
0045 struct string_list **body,
0046 enum symbol_type type)
0047 {
0048 struct string_list *b = *body, *i = *ident, *r;
0049
0050 if (i->in_source_file) {
0051 remove_node(keyw);
0052 (*ident)->tag = type;
0053 remove_list(body, ident);
0054 return;
0055 }
0056 r = copy_node(i); r->tag = type;
0057 r->next = (*keyw)->next; *body = r; (*keyw)->next = NULL;
0058 add_symbol(i->string, type, b, is_extern);
0059 }
0060
0061 %}
0062
0063 %token ASM_KEYW
0064 %token ATTRIBUTE_KEYW
0065 %token AUTO_KEYW
0066 %token BOOL_KEYW
0067 %token BUILTIN_INT_KEYW
0068 %token CHAR_KEYW
0069 %token CONST_KEYW
0070 %token DOUBLE_KEYW
0071 %token ENUM_KEYW
0072 %token EXTERN_KEYW
0073 %token EXTENSION_KEYW
0074 %token FLOAT_KEYW
0075 %token INLINE_KEYW
0076 %token INT_KEYW
0077 %token LONG_KEYW
0078 %token REGISTER_KEYW
0079 %token RESTRICT_KEYW
0080 %token SHORT_KEYW
0081 %token SIGNED_KEYW
0082 %token STATIC_KEYW
0083 %token STATIC_ASSERT_KEYW
0084 %token STRUCT_KEYW
0085 %token TYPEDEF_KEYW
0086 %token UNION_KEYW
0087 %token UNSIGNED_KEYW
0088 %token VOID_KEYW
0089 %token VOLATILE_KEYW
0090 %token TYPEOF_KEYW
0091 %token VA_LIST_KEYW
0092
0093 %token EXPORT_SYMBOL_KEYW
0094
0095 %token ASM_PHRASE
0096 %token ATTRIBUTE_PHRASE
0097 %token TYPEOF_PHRASE
0098 %token BRACE_PHRASE
0099 %token BRACKET_PHRASE
0100 %token EXPRESSION_PHRASE
0101 %token STATIC_ASSERT_PHRASE
0102
0103 %token CHAR
0104 %token DOTS
0105 %token IDENT
0106 %token INT
0107 %token REAL
0108 %token STRING
0109 %token TYPE
0110 %token OTHER
0111 %token FILENAME
0112
0113 %%
0114
0115 declaration_seq:
0116 declaration
0117 | declaration_seq declaration
0118 ;
0119
0120 declaration:
0121 { is_typedef = 0; is_extern = 0; current_name = NULL; decl_spec = NULL; }
0122 declaration1
0123 { free_list(*$2, NULL); *$2 = NULL; }
0124 ;
0125
0126 declaration1:
0127 EXTENSION_KEYW TYPEDEF_KEYW { is_typedef = 1; } simple_declaration
0128 { $$ = $4; }
0129 | TYPEDEF_KEYW { is_typedef = 1; } simple_declaration
0130 { $$ = $3; }
0131 | simple_declaration
0132 | function_definition
0133 | asm_definition
0134 | export_definition
0135 | static_assert
0136 | error ';' { $$ = $2; }
0137 | error '}' { $$ = $2; }
0138 ;
0139
0140 simple_declaration:
0141 decl_specifier_seq_opt init_declarator_list_opt ';'
0142 { if (current_name) {
0143 struct string_list *decl = (*$3)->next;
0144 (*$3)->next = NULL;
0145 add_symbol(current_name,
0146 is_typedef ? SYM_TYPEDEF : SYM_NORMAL,
0147 decl, is_extern);
0148 current_name = NULL;
0149 }
0150 $$ = $3;
0151 }
0152 ;
0153
0154 init_declarator_list_opt:
0155 /* empty */ { $$ = NULL; }
0156 | init_declarator_list
0157 ;
0158
0159 init_declarator_list:
0160 init_declarator
0161 { struct string_list *decl = *$1;
0162 *$1 = NULL;
0163 add_symbol(current_name,
0164 is_typedef ? SYM_TYPEDEF : SYM_NORMAL, decl, is_extern);
0165 current_name = NULL;
0166 $$ = $1;
0167 }
0168 | init_declarator_list ',' init_declarator
0169 { struct string_list *decl = *$3;
0170 *$3 = NULL;
0171 free_list(*$2, NULL);
0172 *$2 = decl_spec;
0173 add_symbol(current_name,
0174 is_typedef ? SYM_TYPEDEF : SYM_NORMAL, decl, is_extern);
0175 current_name = NULL;
0176 $$ = $3;
0177 }
0178 ;
0179
0180 init_declarator:
0181 declarator asm_phrase_opt attribute_opt initializer_opt
0182 { $$ = $4 ? $4 : $3 ? $3 : $2 ? $2 : $1; }
0183 ;
0184
0185 /* Hang on to the specifiers so that we can reuse them. */
0186 decl_specifier_seq_opt:
0187 /* empty */ { decl_spec = NULL; }
0188 | decl_specifier_seq
0189 ;
0190
0191 decl_specifier_seq:
0192 decl_specifier { decl_spec = *$1; }
0193 | decl_specifier_seq decl_specifier { decl_spec = *$2; }
0194 ;
0195
0196 decl_specifier:
0197 storage_class_specifier
0198 { /* Version 2 checksumming ignores storage class, as that
0199 is really irrelevant to the linkage. */
0200 remove_node($1);
0201 $$ = $1;
0202 }
0203 | type_specifier
0204 ;
0205
0206 storage_class_specifier:
0207 AUTO_KEYW
0208 | REGISTER_KEYW
0209 | STATIC_KEYW
0210 | EXTERN_KEYW { is_extern = 1; $$ = $1; }
0211 | INLINE_KEYW { is_extern = 0; $$ = $1; }
0212 ;
0213
0214 type_specifier:
0215 simple_type_specifier
0216 | cvar_qualifier
0217 | TYPEOF_KEYW '(' parameter_declaration ')'
0218 | TYPEOF_PHRASE
0219
0220 /* References to s/u/e's defined elsewhere. Rearrange things
0221 so that it is easier to expand the definition fully later. */
0222 | STRUCT_KEYW IDENT
0223 { remove_node($1); (*$2)->tag = SYM_STRUCT; $$ = $2; }
0224 | UNION_KEYW IDENT
0225 { remove_node($1); (*$2)->tag = SYM_UNION; $$ = $2; }
0226 | ENUM_KEYW IDENT
0227 { remove_node($1); (*$2)->tag = SYM_ENUM; $$ = $2; }
0228
0229 /* Full definitions of an s/u/e. Record it. */
0230 | STRUCT_KEYW IDENT class_body
0231 { record_compound($1, $2, $3, SYM_STRUCT); $$ = $3; }
0232 | UNION_KEYW IDENT class_body
0233 { record_compound($1, $2, $3, SYM_UNION); $$ = $3; }
0234 | ENUM_KEYW IDENT enum_body
0235 { record_compound($1, $2, $3, SYM_ENUM); $$ = $3; }
0236 /*
0237 * Anonymous enum definition. Tell add_symbol() to restart its counter.
0238 */
0239 | ENUM_KEYW enum_body
0240 { add_symbol(NULL, SYM_ENUM, NULL, 0); $$ = $2; }
0241 /* Anonymous s/u definitions. Nothing needs doing. */
0242 | STRUCT_KEYW class_body { $$ = $2; }
0243 | UNION_KEYW class_body { $$ = $2; }
0244 ;
0245
0246 simple_type_specifier:
0247 CHAR_KEYW
0248 | SHORT_KEYW
0249 | INT_KEYW
0250 | LONG_KEYW
0251 | SIGNED_KEYW
0252 | UNSIGNED_KEYW
0253 | FLOAT_KEYW
0254 | DOUBLE_KEYW
0255 | VOID_KEYW
0256 | BOOL_KEYW
0257 | VA_LIST_KEYW
0258 | BUILTIN_INT_KEYW
0259 | TYPE { (*$1)->tag = SYM_TYPEDEF; $$ = $1; }
0260 ;
0261
0262 ptr_operator:
0263 '*' cvar_qualifier_seq_opt
0264 { $$ = $2 ? $2 : $1; }
0265 ;
0266
0267 cvar_qualifier_seq_opt:
0268 /* empty */ { $$ = NULL; }
0269 | cvar_qualifier_seq
0270 ;
0271
0272 cvar_qualifier_seq:
0273 cvar_qualifier
0274 | cvar_qualifier_seq cvar_qualifier { $$ = $2; }
0275 ;
0276
0277 cvar_qualifier:
0278 CONST_KEYW | VOLATILE_KEYW | ATTRIBUTE_PHRASE
0279 | RESTRICT_KEYW
0280 { /* restrict has no effect in prototypes so ignore it */
0281 remove_node($1);
0282 $$ = $1;
0283 }
0284 ;
0285
0286 declarator:
0287 ptr_operator declarator { $$ = $2; }
0288 | direct_declarator
0289 ;
0290
0291 direct_declarator:
0292 IDENT
0293 { if (current_name != NULL) {
0294 error_with_pos("unexpected second declaration name");
0295 YYERROR;
0296 } else {
0297 current_name = (*$1)->string;
0298 $$ = $1;
0299 }
0300 }
0301 | TYPE
0302 { if (current_name != NULL) {
0303 error_with_pos("unexpected second declaration name");
0304 YYERROR;
0305 } else {
0306 current_name = (*$1)->string;
0307 $$ = $1;
0308 }
0309 }
0310 | direct_declarator '(' parameter_declaration_clause ')'
0311 { $$ = $4; }
0312 | direct_declarator '(' error ')'
0313 { $$ = $4; }
0314 | direct_declarator BRACKET_PHRASE
0315 { $$ = $2; }
0316 | '(' declarator ')'
0317 { $$ = $3; }
0318 ;
0319
0320 /* Nested declarators differ from regular declarators in that they do
0321 not record the symbols they find in the global symbol table. */
0322 nested_declarator:
0323 ptr_operator nested_declarator { $$ = $2; }
0324 | direct_nested_declarator
0325 ;
0326
0327 direct_nested_declarator:
0328 IDENT
0329 | TYPE
0330 | direct_nested_declarator '(' parameter_declaration_clause ')'
0331 { $$ = $4; }
0332 | direct_nested_declarator '(' error ')'
0333 { $$ = $4; }
0334 | direct_nested_declarator BRACKET_PHRASE
0335 { $$ = $2; }
0336 | '(' nested_declarator ')'
0337 { $$ = $3; }
0338 | '(' error ')'
0339 { $$ = $3; }
0340 ;
0341
0342 parameter_declaration_clause:
0343 parameter_declaration_list_opt DOTS { $$ = $2; }
0344 | parameter_declaration_list_opt
0345 | parameter_declaration_list ',' DOTS { $$ = $3; }
0346 ;
0347
0348 parameter_declaration_list_opt:
0349 /* empty */ { $$ = NULL; }
0350 | parameter_declaration_list
0351 ;
0352
0353 parameter_declaration_list:
0354 parameter_declaration
0355 | parameter_declaration_list ',' parameter_declaration
0356 { $$ = $3; }
0357 ;
0358
0359 parameter_declaration:
0360 decl_specifier_seq m_abstract_declarator
0361 { $$ = $2 ? $2 : $1; }
0362 ;
0363
0364 m_abstract_declarator:
0365 ptr_operator m_abstract_declarator
0366 { $$ = $2 ? $2 : $1; }
0367 | direct_m_abstract_declarator
0368 ;
0369
0370 direct_m_abstract_declarator:
0371 /* empty */ { $$ = NULL; }
0372 | IDENT
0373 { /* For version 2 checksums, we don't want to remember
0374 private parameter names. */
0375 remove_node($1);
0376 $$ = $1;
0377 }
0378 /* This wasn't really a typedef name but an identifier that
0379 shadows one. */
0380 | TYPE
0381 { remove_node($1);
0382 $$ = $1;
0383 }
0384 | direct_m_abstract_declarator '(' parameter_declaration_clause ')'
0385 { $$ = $4; }
0386 | direct_m_abstract_declarator '(' error ')'
0387 { $$ = $4; }
0388 | direct_m_abstract_declarator BRACKET_PHRASE
0389 { $$ = $2; }
0390 | '(' m_abstract_declarator ')'
0391 { $$ = $3; }
0392 | '(' error ')'
0393 { $$ = $3; }
0394 ;
0395
0396 function_definition:
0397 decl_specifier_seq_opt declarator BRACE_PHRASE
0398 { struct string_list *decl = *$2;
0399 *$2 = NULL;
0400 add_symbol(current_name, SYM_NORMAL, decl, is_extern);
0401 $$ = $3;
0402 }
0403 ;
0404
0405 initializer_opt:
0406 /* empty */ { $$ = NULL; }
0407 | initializer
0408 ;
0409
0410 /* We never care about the contents of an initializer. */
0411 initializer:
0412 '=' EXPRESSION_PHRASE
0413 { remove_list($2, &(*$1)->next); $$ = $2; }
0414 ;
0415
0416 class_body:
0417 '{' member_specification_opt '}' { $$ = $3; }
0418 | '{' error '}' { $$ = $3; }
0419 ;
0420
0421 member_specification_opt:
0422 /* empty */ { $$ = NULL; }
0423 | member_specification
0424 ;
0425
0426 member_specification:
0427 member_declaration
0428 | member_specification member_declaration { $$ = $2; }
0429 ;
0430
0431 member_declaration:
0432 decl_specifier_seq_opt member_declarator_list_opt ';'
0433 { $$ = $3; }
0434 | error ';'
0435 { $$ = $2; }
0436 ;
0437
0438 member_declarator_list_opt:
0439 /* empty */ { $$ = NULL; }
0440 | member_declarator_list
0441 ;
0442
0443 member_declarator_list:
0444 member_declarator
0445 | member_declarator_list ',' member_declarator { $$ = $3; }
0446 ;
0447
0448 member_declarator:
0449 nested_declarator attribute_opt { $$ = $2 ? $2 : $1; }
0450 | IDENT member_bitfield_declarator { $$ = $2; }
0451 | member_bitfield_declarator
0452 ;
0453
0454 member_bitfield_declarator:
0455 ':' EXPRESSION_PHRASE { $$ = $2; }
0456 ;
0457
0458 attribute_opt:
0459 /* empty */ { $$ = NULL; }
0460 | attribute_opt ATTRIBUTE_PHRASE
0461 ;
0462
0463 enum_body:
0464 '{' enumerator_list '}' { $$ = $3; }
0465 | '{' enumerator_list ',' '}' { $$ = $4; }
0466 ;
0467
0468 enumerator_list:
0469 enumerator
0470 | enumerator_list ',' enumerator
0471
0472 enumerator:
0473 IDENT
0474 {
0475 const char *name = strdup((*$1)->string);
0476 add_symbol(name, SYM_ENUM_CONST, NULL, 0);
0477 }
0478 | IDENT '=' EXPRESSION_PHRASE
0479 {
0480 const char *name = strdup((*$1)->string);
0481 struct string_list *expr = copy_list_range(*$3, *$2);
0482 add_symbol(name, SYM_ENUM_CONST, expr, 0);
0483 }
0484
0485 asm_definition:
0486 ASM_PHRASE ';' { $$ = $2; }
0487 ;
0488
0489 asm_phrase_opt:
0490 /* empty */ { $$ = NULL; }
0491 | ASM_PHRASE
0492 ;
0493
0494 export_definition:
0495 EXPORT_SYMBOL_KEYW '(' IDENT ')' ';'
0496 { export_symbol((*$3)->string); $$ = $5; }
0497 ;
0498
0499 /* Ignore any module scoped _Static_assert(...) */
0500 static_assert:
0501 STATIC_ASSERT_PHRASE ';' { $$ = $2; }
0502 ;
0503
0504 %%
0505
0506 static void
0507 yyerror(const char *e)
0508 {
0509 error_with_pos("%s", e);
0510 }