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 ',' 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 IDENT { $$ = $1; dont_want_type_specifier = false; } 335 | direct_nested_declarator '(' parameter_declaration_clause ')' 336 { $$ = $4; } 337 | direct_nested_declarator '(' error ')' 338 { $$ = $4; } 339 | direct_nested_declarator BRACKET_PHRASE 340 { $$ = $2; } 341 | '(' nested_declarator ')' 342 { $$ = $3; } 343 | '(' error ')' 344 { $$ = $3; } 345 ; 346 347 parameter_declaration_clause: 348 parameter_declaration_list_opt DOTS { $$ = $2; } 349 | parameter_declaration_list_opt 350 | parameter_declaration_list ',' DOTS { $$ = $3; } 351 ; 352 353 parameter_declaration_list_opt: 354 /* empty */ { $$ = NULL; } 355 | parameter_declaration_list 356 ; 357 358 parameter_declaration_list: 359 parameter_declaration 360 { $$ = $1; dont_want_type_specifier = false; } 361 | parameter_declaration_list ',' parameter_declaration 362 { $$ = $3; dont_want_type_specifier = false; } 363 ; 364 365 parameter_declaration: 366 decl_specifier_seq abstract_declarator_opt 367 { $$ = $2 ? $2 : $1; } 368 ; 369 370 abstract_declarator_opt: 371 /* empty */ { $$ = NULL; } 372 | abstract_declarator 373 ; 374 375 abstract_declarator: 376 ptr_operator 377 | ptr_operator abstract_declarator 378 { $$ = $2 ? $2 : $1; } 379 | direct_abstract_declarator 380 { $$ = $1; dont_want_type_specifier = false; } 381 ; 382 383 direct_abstract_declarator: 384 IDENT 385 { /* For version 2 checksums, we don't want to remember 386 private parameter names. */ 387 remove_node($1); 388 $$ = $1; 389 } 390 | direct_abstract_declarator open_paren parameter_declaration_clause ')' 391 { $$ = $4; } 392 | direct_abstract_declarator open_paren error ')' 393 { $$ = $4; } 394 | direct_abstract_declarator BRACKET_PHRASE 395 { $$ = $2; } 396 | open_paren parameter_declaration_clause ')' 397 { $$ = $3; } 398 | open_paren abstract_declarator ')' 399 { $$ = $3; } 400 | open_paren error ')' 401 { $$ = $3; } 402 | BRACKET_PHRASE 403 ; 404 405 open_paren: 406 '(' { $$ = $1; dont_want_type_specifier = false; } 407 ; 408 409 function_definition: 410 decl_specifier_seq_opt declarator BRACE_PHRASE 411 { struct string_list *decl = *$2; 412 *$2 = NULL; 413 add_symbol(current_name, SYM_NORMAL, decl, is_extern); 414 $$ = $3; 415 } 416 ; 417 418 initializer_opt: 419 /* empty */ { $$ = NULL; } 420 | initializer 421 ; 422 423 /* We never care about the contents of an initializer. */ 424 initializer: 425 '=' EXPRESSION_PHRASE 426 { remove_list($2, &(*$1)->next); $$ = $2; } 427 ; 428 429 class_body: 430 '{' member_specification_opt '}' { $$ = $3; } 431 | '{' error '}' { $$ = $3; } 432 ; 433 434 member_specification_opt: 435 /* empty */ { $$ = NULL; } 436 | member_specification 437 ; 438 439 member_specification: 440 member_declaration 441 | member_specification member_declaration { $$ = $2; } 442 ; 443 444 member_declaration: 445 decl_specifier_seq_opt member_declarator_list_opt ';' 446 { $$ = $3; dont_want_type_specifier = false; } 447 | error ';' 448 { $$ = $2; dont_want_type_specifier = false; } 449 ; 450 451 member_declarator_list_opt: 452 /* empty */ { $$ = NULL; } 453 | member_declarator_list 454 ; 455 456 member_declarator_list: 457 member_declarator 458 { $$ = $1; dont_want_type_specifier = true; } 459 | member_declarator_list ',' member_declarator 460 { $$ = $3; dont_want_type_specifier = true; } 461 ; 462 463 member_declarator: 464 nested_declarator attribute_opt { $$ = $2 ? $2 : $1; } 465 | IDENT member_bitfield_declarator { $$ = $2; } 466 | member_bitfield_declarator 467 ; 468 469 member_bitfield_declarator: 470 ':' EXPRESSION_PHRASE { $$ = $2; } 471 ; 472 473 attribute_opt: 474 /* empty */ { $$ = NULL; } 475 | attribute_opt ATTRIBUTE_PHRASE 476 ; 477 478 enum_body: 479 '{' enumerator_list '}' { $$ = $3; } 480 | '{' enumerator_list ',' '}' { $$ = $4; } 481 ; 482 483 enumerator_list: 484 enumerator 485 | enumerator_list ',' enumerator 486 487 enumerator: 488 IDENT 489 { 490 const char *name = (*$1)->string; 491 add_symbol(name, SYM_ENUM_CONST, NULL, 0); 492 } 493 | IDENT '=' EXPRESSION_PHRASE 494 { 495 const char *name = (*$1)->string; 496 struct string_list *expr = copy_list_range(*$3, *$2); 497 add_symbol(name, SYM_ENUM_CONST, expr, 0); 498 } 499 500 asm_definition: 501 ASM_PHRASE ';' { $$ = $2; } 502 ; 503 504 asm_phrase_opt: 505 /* empty */ { $$ = NULL; } 506 | ASM_PHRASE 507 ; 508 509 export_definition: 510 EXPORT_SYMBOL_KEYW '(' IDENT ')' ';' 511 { export_symbol((*$3)->string); $$ = $5; } 512 ; 513 514 /* Ignore any module scoped _Static_assert(...) */ 515 static_assert: 516 STATIC_ASSERT_PHRASE ';' { $$ = $2; } 517 ; 518 519 %% 520 521 static void 522 yyerror(const char *e) 523 { 524 error_with_pos("%s", e); 525 } 526