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