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