at master 12 kB view raw
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 20static int is_typedef; 21static int is_extern; 22static char *current_name; 23static struct string_list *decl_spec; 24 25static void yyerror(const char *); 26 27static inline void 28remove_node(struct string_list **p) 29{ 30 struct string_list *node = *p; 31 *p = node->next; 32 free_node(node); 33} 34 35static inline void 36remove_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 */ 44static 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 118declaration_seq: 119 declaration 120 | declaration_seq declaration 121 ; 122 123declaration: 124 { is_typedef = 0; is_extern = 0; current_name = NULL; decl_spec = NULL; } 125 declaration1 126 { free_list(*$2, NULL); *$2 = NULL; } 127 ; 128 129declaration1: 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 143simple_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 158init_declarator_list_opt: 159 /* empty */ { $$ = NULL; } 160 | init_declarator_list { free_list(decl_spec, NULL); $$ = $1; } 161 ; 162 163init_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 196init_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. */ 202decl_specifier_seq_opt: 203 /* empty */ { decl_spec = NULL; } 204 | decl_specifier_seq 205 ; 206 207decl_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 213decl_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 224storage_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 232type_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 263simple_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 279ptr_operator: 280 '*' type_qualifier_seq_opt 281 { $$ = $2 ? $2 : $1; } 282 ; 283 284type_qualifier_seq_opt: 285 /* empty */ { $$ = NULL; } 286 | type_qualifier_seq 287 ; 288 289type_qualifier_seq: 290 type_qualifier 291 | ATTRIBUTE_PHRASE 292 | type_qualifier_seq type_qualifier { $$ = $2; } 293 | type_qualifier_seq ATTRIBUTE_PHRASE { $$ = $2; } 294 ; 295 296type_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 306declarator: 307 ptr_operator declarator { $$ = $2; } 308 | direct_declarator 309 ; 310 311direct_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. */ 334nested_declarator: 335 ptr_operator nested_declarator { $$ = $2; } 336 | direct_nested_declarator 337 ; 338 339direct_nested_declarator: 340 direct_nested_declarator1 341 | direct_nested_declarator1 '(' parameter_declaration_clause ')' 342 { $$ = $4; } 343 ; 344 345direct_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 357parameter_declaration_clause: 358 parameter_declaration_list_opt DOTS { $$ = $2; } 359 | parameter_declaration_list_opt 360 | parameter_declaration_list ',' DOTS { $$ = $3; } 361 ; 362 363parameter_declaration_list_opt: 364 /* empty */ { $$ = NULL; } 365 | parameter_declaration_list 366 ; 367 368parameter_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 375parameter_declaration: 376 decl_specifier_seq abstract_declarator_opt 377 { $$ = $2 ? $2 : $1; } 378 ; 379 380abstract_declarator_opt: 381 /* empty */ { $$ = NULL; } 382 | abstract_declarator 383 ; 384 385abstract_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 393direct_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 401direct_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 419open_paren: 420 '(' { $$ = $1; dont_want_type_specifier = false; } 421 ; 422 423function_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 432initializer_opt: 433 /* empty */ { $$ = NULL; } 434 | initializer 435 ; 436 437/* We never care about the contents of an initializer. */ 438initializer: 439 '=' EXPRESSION_PHRASE 440 { remove_list($2, &(*$1)->next); $$ = $2; } 441 ; 442 443class_body: 444 '{' member_specification_opt '}' { $$ = $3; } 445 | '{' error '}' { $$ = $3; } 446 ; 447 448member_specification_opt: 449 /* empty */ { $$ = NULL; } 450 | member_specification 451 ; 452 453member_specification: 454 member_declaration 455 | member_specification member_declaration { $$ = $2; } 456 ; 457 458member_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 465member_declarator_list_opt: 466 /* empty */ { $$ = NULL; } 467 | member_declarator_list 468 ; 469 470member_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 477member_declarator: 478 nested_declarator attribute_opt { $$ = $2 ? $2 : $1; } 479 | IDENT member_bitfield_declarator { $$ = $2; } 480 | member_bitfield_declarator 481 ; 482 483member_bitfield_declarator: 484 ':' EXPRESSION_PHRASE { $$ = $2; } 485 ; 486 487attribute_opt: 488 /* empty */ { $$ = NULL; } 489 | attribute_opt ATTRIBUTE_PHRASE { $$ = $2; } 490 ; 491 492enum_body: 493 '{' enumerator_list '}' { $$ = $3; } 494 | '{' enumerator_list ',' '}' { $$ = $4; } 495 ; 496 497enumerator_list: 498 enumerator 499 | enumerator_list ',' enumerator 500 501enumerator: 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 514asm_definition: 515 ASM_PHRASE ';' { $$ = $2; } 516 ; 517 518asm_phrase_opt: 519 /* empty */ { $$ = NULL; } 520 | ASM_PHRASE 521 ; 522 523export_definition: 524 EXPORT_SYMBOL_KEYW '(' IDENT ')' ';' 525 { export_symbol((*$3)->string); $$ = $5; } 526 ; 527 528/* Ignore any module scoped _Static_assert(...) */ 529static_assert: 530 STATIC_ASSERT_PHRASE ';' { $$ = $2; } 531 ; 532 533%% 534 535static void 536yyerror(const char *e) 537{ 538 error_with_pos("%s", e); 539}