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