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