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 <stdlib.h> 16 #include <string.h> 17 #include "genksyms.h" 18 19 static int is_typedef; 20 static int is_extern; 21 static char *current_name; 22 static struct string_list *decl_spec; 23 24 static void yyerror(const char *); 25 26 static inline void 27 remove_node(struct string_list **p) 28 { 29 struct string_list *node = *p; 30 *p = node->next; 31 free_node(node); 32 } 33 34 static inline void 35 remove_list(struct string_list **pb, struct string_list **pe) 36 { 37 struct string_list *b = *pb, *e = *pe; 38 *pb = e; 39 free_list(b, e); 40 } 41 42 /* Record definition of a struct/union/enum */ 43 static void record_compound(struct string_list **keyw, 44 struct string_list **ident, 45 struct string_list **body, 46 enum symbol_type type) 47 { 48 struct string_list *b = *body, *i = *ident, *r; 49 50 if (i->in_source_file) { 51 remove_node(keyw); 52 (*ident)->tag = type; 53 remove_list(body, ident); 54 return; 55 } 56 r = copy_node(i); r->tag = type; 57 r->next = (*keyw)->next; *body = r; (*keyw)->next = NULL; 58 add_symbol(i->string, type, b, is_extern); 59 } 60 61 %} 62 63 %token ASM_KEYW 64 %token ATTRIBUTE_KEYW 65 %token AUTO_KEYW 66 %token BOOL_KEYW 67 %token BUILTIN_INT_KEYW 68 %token CHAR_KEYW 69 %token CONST_KEYW 70 %token DOUBLE_KEYW 71 %token ENUM_KEYW 72 %token EXTERN_KEYW 73 %token EXTENSION_KEYW 74 %token FLOAT_KEYW 75 %token INLINE_KEYW 76 %token INT_KEYW 77 %token LONG_KEYW 78 %token REGISTER_KEYW 79 %token RESTRICT_KEYW 80 %token SHORT_KEYW 81 %token SIGNED_KEYW 82 %token STATIC_KEYW 83 %token STATIC_ASSERT_KEYW 84 %token STRUCT_KEYW 85 %token TYPEDEF_KEYW 86 %token UNION_KEYW 87 %token UNSIGNED_KEYW 88 %token VOID_KEYW 89 %token VOLATILE_KEYW 90 %token TYPEOF_KEYW 91 %token VA_LIST_KEYW 92 93 %token EXPORT_SYMBOL_KEYW 94 95 %token ASM_PHRASE 96 %token ATTRIBUTE_PHRASE 97 %token TYPEOF_PHRASE 98 %token BRACE_PHRASE 99 %token BRACKET_PHRASE 100 %token EXPRESSION_PHRASE 101 %token STATIC_ASSERT_PHRASE 102 103 %token CHAR 104 %token DOTS 105 %token IDENT 106 %token INT 107 %token REAL 108 %token STRING 109 %token TYPE 110 %token OTHER 111 %token FILENAME 112 113 %% 114 115 declaration_seq: 116 declaration 117 | declaration_seq declaration 118 ; 119 120 declaration: 121 { is_typedef = 0; is_extern = 0; current_name = NULL; decl_spec = NULL; } 122 declaration1 123 { free_list(*$2, NULL); *$2 = NULL; } 124 ; 125 126 declaration1: 127 EXTENSION_KEYW TYPEDEF_KEYW { is_typedef = 1; } simple_declaration 128 { $$ = $4; } 129 | TYPEDEF_KEYW { is_typedef = 1; } simple_declaration 130 { $$ = $3; } 131 | simple_declaration 132 | function_definition 133 | asm_definition 134 | export_definition 135 | static_assert 136 | error ';' { $$ = $2; } 137 | error '}' { $$ = $2; } 138 ; 139 140 simple_declaration: 141 decl_specifier_seq_opt init_declarator_list_opt ';' 142 { if (current_name) { 143 struct string_list *decl = (*$3)->next; 144 (*$3)->next = NULL; 145 add_symbol(current_name, 146 is_typedef ? SYM_TYPEDEF : SYM_NORMAL, 147 decl, is_extern); 148 current_name = NULL; 149 } 150 $$ = $3; 151 } 152 ; 153 154 init_declarator_list_opt: 155 /* empty */ { $$ = NULL; } 156 | init_declarator_list 157 ; 158 159 init_declarator_list: 160 init_declarator 161 { struct string_list *decl = *$1; 162 *$1 = NULL; 163 add_symbol(current_name, 164 is_typedef ? SYM_TYPEDEF : SYM_NORMAL, decl, is_extern); 165 current_name = NULL; 166 $$ = $1; 167 } 168 | init_declarator_list ',' init_declarator 169 { struct string_list *decl = *$3; 170 *$3 = NULL; 171 free_list(*$2, NULL); 172 *$2 = decl_spec; 173 add_symbol(current_name, 174 is_typedef ? SYM_TYPEDEF : SYM_NORMAL, decl, is_extern); 175 current_name = NULL; 176 $$ = $3; 177 } 178 ; 179 180 init_declarator: 181 declarator asm_phrase_opt attribute_opt initializer_opt 182 { $$ = $4 ? $4 : $3 ? $3 : $2 ? $2 : $1; } 183 ; 184 185 /* Hang on to the specifiers so that we can reuse them. */ 186 decl_specifier_seq_opt: 187 /* empty */ { decl_spec = NULL; } 188 | decl_specifier_seq 189 ; 190 191 decl_specifier_seq: 192 decl_specifier { decl_spec = *$1; } 193 | decl_specifier_seq decl_specifier { decl_spec = *$2; } 194 ; 195 196 decl_specifier: 197 storage_class_specifier 198 { /* Version 2 checksumming ignores storage class, as that 199 is really irrelevant to the linkage. */ 200 remove_node($1); 201 $$ = $1; 202 } 203 | type_specifier 204 ; 205 206 storage_class_specifier: 207 AUTO_KEYW 208 | REGISTER_KEYW 209 | STATIC_KEYW 210 | EXTERN_KEYW { is_extern = 1; $$ = $1; } 211 | INLINE_KEYW { is_extern = 0; $$ = $1; } 212 ; 213 214 type_specifier: 215 simple_type_specifier 216 | cvar_qualifier 217 | TYPEOF_KEYW '(' parameter_declaration ')' 218 | TYPEOF_PHRASE 219 220 /* References to s/u/e's defined elsewhere. Rearrange things 221 so that it is easier to expand the definition fully later. */ 222 | STRUCT_KEYW IDENT 223 { remove_node($1); (*$2)->tag = SYM_STRUCT; $$ = $2; } 224 | UNION_KEYW IDENT 225 { remove_node($1); (*$2)->tag = SYM_UNION; $$ = $2; } 226 | ENUM_KEYW IDENT 227 { remove_node($1); (*$2)->tag = SYM_ENUM; $$ = $2; } 228 229 /* Full definitions of an s/u/e. Record it. */ 230 | STRUCT_KEYW IDENT class_body 231 { record_compound($1, $2, $3, SYM_STRUCT); $$ = $3; } 232 | UNION_KEYW IDENT class_body 233 { record_compound($1, $2, $3, SYM_UNION); $$ = $3; } 234 | ENUM_KEYW IDENT enum_body 235 { record_compound($1, $2, $3, SYM_ENUM); $$ = $3; } 236 /* 237 * Anonymous enum definition. Tell add_symbol() to restart its counter. 238 */ 239 | ENUM_KEYW enum_body 240 { add_symbol(NULL, SYM_ENUM, NULL, 0); $$ = $2; } 241 /* Anonymous s/u definitions. Nothing needs doing. */ 242 | STRUCT_KEYW class_body { $$ = $2; } 243 | UNION_KEYW class_body { $$ = $2; } 244 ; 245 246 simple_type_specifier: 247 CHAR_KEYW 248 | SHORT_KEYW 249 | INT_KEYW 250 | LONG_KEYW 251 | SIGNED_KEYW 252 | UNSIGNED_KEYW 253 | FLOAT_KEYW 254 | DOUBLE_KEYW 255 | VOID_KEYW 256 | BOOL_KEYW 257 | VA_LIST_KEYW 258 | BUILTIN_INT_KEYW 259 | TYPE { (*$1)->tag = SYM_TYPEDEF; $$ = $1; } 260 ; 261 262 ptr_operator: 263 '*' cvar_qualifier_seq_opt 264 { $$ = $2 ? $2 : $1; } 265 ; 266 267 cvar_qualifier_seq_opt: 268 /* empty */ { $$ = NULL; } 269 | cvar_qualifier_seq 270 ; 271 272 cvar_qualifier_seq: 273 cvar_qualifier 274 | cvar_qualifier_seq cvar_qualifier { $$ = $2; } 275 ; 276 277 cvar_qualifier: 278 CONST_KEYW | VOLATILE_KEYW | ATTRIBUTE_PHRASE 279 | RESTRICT_KEYW 280 { /* restrict has no effect in prototypes so ignore it */ 281 remove_node($1); 282 $$ = $1; 283 } 284 ; 285 286 declarator: 287 ptr_operator declarator { $$ = $2; } 288 | direct_declarator 289 ; 290 291 direct_declarator: 292 IDENT 293 { if (current_name != NULL) { 294 error_with_pos("unexpected second declaration name"); 295 YYERROR; 296 } else { 297 current_name = (*$1)->string; 298 $$ = $1; 299 } 300 } 301 | TYPE 302 { if (current_name != NULL) { 303 error_with_pos("unexpected second declaration name"); 304 YYERROR; 305 } else { 306 current_name = (*$1)->string; 307 $$ = $1; 308 } 309 } 310 | direct_declarator '(' parameter_declaration_clause ')' 311 { $$ = $4; } 312 | direct_declarator '(' error ')' 313 { $$ = $4; } 314 | direct_declarator BRACKET_PHRASE 315 { $$ = $2; } 316 | '(' declarator ')' 317 { $$ = $3; } 318 ; 319 320 /* Nested declarators differ from regular declarators in that they do 321 not record the symbols they find in the global symbol table. */ 322 nested_declarator: 323 ptr_operator nested_declarator { $$ = $2; } 324 | direct_nested_declarator 325 ; 326 327 direct_nested_declarator: 328 IDENT 329 | TYPE 330 | direct_nested_declarator '(' parameter_declaration_clause ')' 331 { $$ = $4; } 332 | direct_nested_declarator '(' error ')' 333 { $$ = $4; } 334 | direct_nested_declarator BRACKET_PHRASE 335 { $$ = $2; } 336 | '(' nested_declarator ')' 337 { $$ = $3; } 338 | '(' error ')' 339 { $$ = $3; } 340 ; 341 342 parameter_declaration_clause: 343 parameter_declaration_list_opt DOTS { $$ = $2; } 344 | parameter_declaration_list_opt 345 | parameter_declaration_list ',' DOTS { $$ = $3; } 346 ; 347 348 parameter_declaration_list_opt: 349 /* empty */ { $$ = NULL; } 350 | parameter_declaration_list 351 ; 352 353 parameter_declaration_list: 354 parameter_declaration 355 | parameter_declaration_list ',' parameter_declaration 356 { $$ = $3; } 357 ; 358 359 parameter_declaration: 360 decl_specifier_seq m_abstract_declarator 361 { $$ = $2 ? $2 : $1; } 362 ; 363 364 m_abstract_declarator: 365 ptr_operator m_abstract_declarator 366 { $$ = $2 ? $2 : $1; } 367 | direct_m_abstract_declarator 368 ; 369 370 direct_m_abstract_declarator: 371 /* empty */ { $$ = NULL; } 372 | IDENT 373 { /* For version 2 checksums, we don't want to remember 374 private parameter names. */ 375 remove_node($1); 376 $$ = $1; 377 } 378 /* This wasn't really a typedef name but an identifier that 379 shadows one. */ 380 | TYPE 381 { remove_node($1); 382 $$ = $1; 383 } 384 | direct_m_abstract_declarator '(' parameter_declaration_clause ')' 385 { $$ = $4; } 386 | direct_m_abstract_declarator '(' error ')' 387 { $$ = $4; } 388 | direct_m_abstract_declarator BRACKET_PHRASE 389 { $$ = $2; } 390 | '(' m_abstract_declarator ')' 391 { $$ = $3; } 392 | '(' error ')' 393 { $$ = $3; } 394 ; 395 396 function_definition: 397 decl_specifier_seq_opt declarator BRACE_PHRASE 398 { struct string_list *decl = *$2; 399 *$2 = NULL; 400 add_symbol(current_name, SYM_NORMAL, decl, is_extern); 401 $$ = $3; 402 } 403 ; 404 405 initializer_opt: 406 /* empty */ { $$ = NULL; } 407 | initializer 408 ; 409 410 /* We never care about the contents of an initializer. */ 411 initializer: 412 '=' EXPRESSION_PHRASE 413 { remove_list($2, &(*$1)->next); $$ = $2; } 414 ; 415 416 class_body: 417 '{' member_specification_opt '}' { $$ = $3; } 418 | '{' error '}' { $$ = $3; } 419 ; 420 421 member_specification_opt: 422 /* empty */ { $$ = NULL; } 423 | member_specification 424 ; 425 426 member_specification: 427 member_declaration 428 | member_specification member_declaration { $$ = $2; } 429 ; 430 431 member_declaration: 432 decl_specifier_seq_opt member_declarator_list_opt ';' 433 { $$ = $3; } 434 | error ';' 435 { $$ = $2; } 436 ; 437 438 member_declarator_list_opt: 439 /* empty */ { $$ = NULL; } 440 | member_declarator_list 441 ; 442 443 member_declarator_list: 444 member_declarator 445 | member_declarator_list ',' member_declarator { $$ = $3; } 446 ; 447 448 member_declarator: 449 nested_declarator attribute_opt { $$ = $2 ? $2 : $1; } 450 | IDENT member_bitfield_declarator { $$ = $2; } 451 | member_bitfield_declarator 452 ; 453 454 member_bitfield_declarator: 455 ':' EXPRESSION_PHRASE { $$ = $2; } 456 ; 457 458 attribute_opt: 459 /* empty */ { $$ = NULL; } 460 | attribute_opt ATTRIBUTE_PHRASE 461 ; 462 463 enum_body: 464 '{' enumerator_list '}' { $$ = $3; } 465 | '{' enumerator_list ',' '}' { $$ = $4; } 466 ; 467 468 enumerator_list: 469 enumerator 470 | enumerator_list ',' enumerator 471 472 enumerator: 473 IDENT 474 { 475 const char *name = strdup((*$1)->string); 476 add_symbol(name, SYM_ENUM_CONST, NULL, 0); 477 } 478 | IDENT '=' EXPRESSION_PHRASE 479 { 480 const char *name = strdup((*$1)->string); 481 struct string_list *expr = copy_list_range(*$3, *$2); 482 add_symbol(name, SYM_ENUM_CONST, expr, 0); 483 } 484 485 asm_definition: 486 ASM_PHRASE ';' { $$ = $2; } 487 ; 488 489 asm_phrase_opt: 490 /* empty */ { $$ = NULL; } 491 | ASM_PHRASE 492 ; 493 494 export_definition: 495 EXPORT_SYMBOL_KEYW '(' IDENT ')' ';' 496 { export_symbol((*$3)->string); $$ = $5; } 497 ; 498 499 /* Ignore any module scoped _Static_assert(...) */ 500 static_assert: 501 STATIC_ASSERT_PHRASE ';' { $$ = $2; } 502 ; 503 504 %% 505 506 static void 507 yyerror(const char *e) 508 { 509 error_with_pos("%s", e); 510 }
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.