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