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 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 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 ',' init_declarator 177 { struct string_list *decl = *$3; 178 *$3 = 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 $$ = $3; 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 decl_specifier { decl_spec = *$1; } 207 | decl_specifier_seq decl_specifier { decl_spec = *$2; } 208 ; 209 210 decl_specifier: 211 storage_class_specifier 212 { /* Version 2 checksumming ignores storage class, as that 213 is really irrelevant to the linkage. */ 214 remove_node($1); 215 $$ = $1; 216 } 217 | type_specifier { dont_want_type_specifier = true; $$ = $1; } 218 | type_qualifier 219 ; 220 221 storage_class_specifier: 222 AUTO_KEYW 223 | REGISTER_KEYW 224 | STATIC_KEYW 225 | EXTERN_KEYW { is_extern = 1; $$ = $1; } 226 | INLINE_KEYW { is_extern = 0; $$ = $1; } 227 ; 228 229 type_specifier: 230 simple_type_specifier 231 | TYPEOF_KEYW '(' parameter_declaration ')' 232 | TYPEOF_PHRASE 233 234 /* References to s/u/e's defined elsewhere. Rearrange things 235 so that it is easier to expand the definition fully later. */ 236 | STRUCT_KEYW IDENT 237 { remove_node($1); (*$2)->tag = SYM_STRUCT; $$ = $2; } 238 | UNION_KEYW IDENT 239 { remove_node($1); (*$2)->tag = SYM_UNION; $$ = $2; } 240 | ENUM_KEYW IDENT 241 { remove_node($1); (*$2)->tag = SYM_ENUM; $$ = $2; } 242 243 /* Full definitions of an s/u/e. Record it. */ 244 | STRUCT_KEYW IDENT class_body 245 { record_compound($1, $2, $3, SYM_STRUCT); $$ = $3; } 246 | UNION_KEYW IDENT class_body 247 { record_compound($1, $2, $3, SYM_UNION); $$ = $3; } 248 | ENUM_KEYW IDENT enum_body 249 { record_compound($1, $2, $3, SYM_ENUM); $$ = $3; } 250 /* 251 * Anonymous enum definition. Tell add_symbol() to restart its counter. 252 */ 253 | ENUM_KEYW enum_body 254 { add_symbol(NULL, SYM_ENUM, NULL, 0); $$ = $2; } 255 /* Anonymous s/u definitions. Nothing needs doing. */ 256 | STRUCT_KEYW class_body { $$ = $2; } 257 | UNION_KEYW class_body { $$ = $2; } 258 ; 259 260 simple_type_specifier: 261 CHAR_KEYW 262 | SHORT_KEYW 263 | INT_KEYW 264 | LONG_KEYW 265 | SIGNED_KEYW 266 | UNSIGNED_KEYW 267 | FLOAT_KEYW 268 | DOUBLE_KEYW 269 | VOID_KEYW 270 | BOOL_KEYW 271 | VA_LIST_KEYW 272 | BUILTIN_INT_KEYW 273 | TYPE { (*$1)->tag = SYM_TYPEDEF; $$ = $1; } 274 ; 275 276 ptr_operator: 277 '*' type_qualifier_seq_opt 278 { $$ = $2 ? $2 : $1; } 279 ; 280 281 type_qualifier_seq_opt: 282 /* empty */ { $$ = NULL; } 283 | type_qualifier_seq 284 ; 285 286 type_qualifier_seq: 287 type_qualifier 288 | type_qualifier_seq type_qualifier { $$ = $2; } 289 ; 290 291 type_qualifier: 292 CONST_KEYW | VOLATILE_KEYW | ATTRIBUTE_PHRASE 293 | RESTRICT_KEYW 294 { /* restrict has no effect in prototypes so ignore it */ 295 remove_node($1); 296 $$ = $1; 297 } 298 ; 299 300 declarator: 301 ptr_operator declarator { $$ = $2; } 302 | direct_declarator 303 ; 304 305 direct_declarator: 306 IDENT 307 { if (current_name != NULL) { 308 error_with_pos("unexpected second declaration name"); 309 YYERROR; 310 } else { 311 current_name = (*$1)->string; 312 $$ = $1; 313 } 314 dont_want_type_specifier = false; 315 } 316 | direct_declarator '(' parameter_declaration_clause ')' 317 { $$ = $4; } 318 | direct_declarator '(' error ')' 319 { $$ = $4; } 320 | direct_declarator BRACKET_PHRASE 321 { $$ = $2; } 322 | '(' declarator ')' 323 { $$ = $3; } 324 ; 325 326 /* Nested declarators differ from regular declarators in that they do 327 not record the symbols they find in the global symbol table. */ 328 nested_declarator: 329 ptr_operator nested_declarator { $$ = $2; } 330 | direct_nested_declarator 331 ; 332 333 direct_nested_declarator: 334 direct_nested_declarator1 335 | direct_nested_declarator1 '(' parameter_declaration_clause ')' 336 { $$ = $4; } 337 ; 338 339 direct_nested_declarator1: 340 IDENT { $$ = $1; dont_want_type_specifier = false; } 341 | direct_nested_declarator1 '(' error ')' 342 { $$ = $4; } 343 | direct_nested_declarator1 BRACKET_PHRASE 344 { $$ = $2; } 345 | '(' nested_declarator ')' 346 { $$ = $3; } 347 | '(' error ')' 348 { $$ = $3; } 349 ; 350 351 parameter_declaration_clause: 352 parameter_declaration_list_opt DOTS { $$ = $2; } 353 | parameter_declaration_list_opt 354 | parameter_declaration_list ',' DOTS { $$ = $3; } 355 ; 356 357 parameter_declaration_list_opt: 358 /* empty */ { $$ = NULL; } 359 | parameter_declaration_list 360 ; 361 362 parameter_declaration_list: 363 parameter_declaration 364 { $$ = $1; dont_want_type_specifier = false; } 365 | parameter_declaration_list ',' parameter_declaration 366 { $$ = $3; dont_want_type_specifier = false; } 367 ; 368 369 parameter_declaration: 370 decl_specifier_seq abstract_declarator_opt 371 { $$ = $2 ? $2 : $1; } 372 ; 373 374 abstract_declarator_opt: 375 /* empty */ { $$ = NULL; } 376 | abstract_declarator 377 ; 378 379 abstract_declarator: 380 ptr_operator 381 | ptr_operator abstract_declarator 382 { $$ = $2 ? $2 : $1; } 383 | direct_abstract_declarator 384 { $$ = $1; dont_want_type_specifier = false; } 385 ; 386 387 direct_abstract_declarator: 388 direct_abstract_declarator1 389 | direct_abstract_declarator1 open_paren parameter_declaration_clause ')' 390 { $$ = $4; } 391 | open_paren parameter_declaration_clause ')' 392 { $$ = $3; } 393 ; 394 395 direct_abstract_declarator1: 396 IDENT 397 { /* For version 2 checksums, we don't want to remember 398 private parameter names. */ 399 remove_node($1); 400 $$ = $1; 401 } 402 | direct_abstract_declarator1 open_paren error ')' 403 { $$ = $4; } 404 | direct_abstract_declarator1 BRACKET_PHRASE 405 { $$ = $2; } 406 | open_paren abstract_declarator ')' 407 { $$ = $3; } 408 | open_paren error ')' 409 { $$ = $3; } 410 | BRACKET_PHRASE 411 ; 412 413 open_paren: 414 '(' { $$ = $1; dont_want_type_specifier = false; } 415 ; 416 417 function_definition: 418 decl_specifier_seq_opt declarator BRACE_PHRASE 419 { struct string_list *decl = *$2; 420 *$2 = NULL; 421 add_symbol(current_name, SYM_NORMAL, decl, is_extern); 422 $$ = $3; 423 } 424 ; 425 426 initializer_opt: 427 /* empty */ { $$ = NULL; } 428 | initializer 429 ; 430 431 /* We never care about the contents of an initializer. */ 432 initializer: 433 '=' EXPRESSION_PHRASE 434 { remove_list($2, &(*$1)->next); $$ = $2; } 435 ; 436 437 class_body: 438 '{' member_specification_opt '}' { $$ = $3; } 439 | '{' error '}' { $$ = $3; } 440 ; 441 442 member_specification_opt: 443 /* empty */ { $$ = NULL; } 444 | member_specification 445 ; 446 447 member_specification: 448 member_declaration 449 | member_specification member_declaration { $$ = $2; } 450 ; 451 452 member_declaration: 453 decl_specifier_seq_opt member_declarator_list_opt ';' 454 { $$ = $3; dont_want_type_specifier = false; } 455 | error ';' 456 { $$ = $2; dont_want_type_specifier = false; } 457 ; 458 459 member_declarator_list_opt: 460 /* empty */ { $$ = NULL; } 461 | member_declarator_list 462 ; 463 464 member_declarator_list: 465 member_declarator 466 { $$ = $1; dont_want_type_specifier = true; } 467 | member_declarator_list ',' member_declarator 468 { $$ = $3; dont_want_type_specifier = true; } 469 ; 470 471 member_declarator: 472 nested_declarator attribute_opt { $$ = $2 ? $2 : $1; } 473 | IDENT member_bitfield_declarator { $$ = $2; } 474 | member_bitfield_declarator 475 ; 476 477 member_bitfield_declarator: 478 ':' EXPRESSION_PHRASE { $$ = $2; } 479 ; 480 481 attribute_opt: 482 /* empty */ { $$ = NULL; } 483 | attribute_opt ATTRIBUTE_PHRASE 484 ; 485 486 enum_body: 487 '{' enumerator_list '}' { $$ = $3; } 488 | '{' enumerator_list ',' '}' { $$ = $4; } 489 ; 490 491 enumerator_list: 492 enumerator 493 | enumerator_list ',' enumerator 494 495 enumerator: 496 IDENT 497 { 498 const char *name = (*$1)->string; 499 add_symbol(name, SYM_ENUM_CONST, NULL, 0); 500 } 501 | IDENT '=' EXPRESSION_PHRASE 502 { 503 const char *name = (*$1)->string; 504 struct string_list *expr = copy_list_range(*$3, *$2); 505 add_symbol(name, SYM_ENUM_CONST, expr, 0); 506 } 507 508 asm_definition: 509 ASM_PHRASE ';' { $$ = $2; } 510 ; 511 512 asm_phrase_opt: 513 /* empty */ { $$ = NULL; } 514 | ASM_PHRASE 515 ; 516 517 export_definition: 518 EXPORT_SYMBOL_KEYW '(' IDENT ')' ';' 519 { export_symbol((*$3)->string); $$ = $5; } 520 ; 521 522 /* Ignore any module scoped _Static_assert(...) */ 523 static_assert: 524 STATIC_ASSERT_PHRASE ';' { $$ = $2; } 525 ; 526 527 %% 528 529 static void 530 yyerror(const char *e) 531 { 532 error_with_pos("%s", e); 533 } 534