1 /* C global declaration parser for genksyms. 2 Copyright 1996, 1997 Linux International. 3 4 New implementation contributed by Richard Henderson <rth@tamu.edu> 5 Based on original work by Bjorn Ekwall <bj0rn@blox.se> 6 7 This file is part of the Linux modutils. 8 9 This program is free software; you can redistribute it and/or modify it 10 under the terms of the GNU General Public License as published by the 11 Free Software Foundation; either version 2 of the License, or (at your 12 option) any later version. 13 14 This program is distributed in the hope that it will be useful, but 15 WITHOUT ANY WARRANTY; without even the implied warranty of 16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 General Public License for more details. 18 19 You should have received a copy of the GNU General Public License 20 along with this program; if not, write to the Free Software Foundation, 21 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ 22 23 24 %{ 25 26 #include <assert.h> 27 #include <malloc.h> 28 #include "genksyms.h" 29 30 static int is_typedef; 31 static int is_extern; 32 static char *current_name; 33 static struct string_list *decl_spec; 34 35 static void yyerror(const char *); 36 37 static inline void 38 remove_node(struct string_list **p) 39 { 40 struct string_list *node = *p; 41 *p = node->next; 42 free_node(node); 43 } 44 45 static inline void 46 remove_list(struct string_list **pb, struct string_list **pe) 47 { 48 struct string_list *b = *pb, *e = *pe; 49 *pb = e; 50 free_list(b, e); 51 } 52 53 %} 54 55 %token ASM_KEYW 56 %token ATTRIBUTE_KEYW 57 %token AUTO_KEYW 58 %token BOOL_KEYW 59 %token CHAR_KEYW 60 %token CONST_KEYW 61 %token DOUBLE_KEYW 62 %token ENUM_KEYW 63 %token EXTERN_KEYW 64 %token FLOAT_KEYW 65 %token INLINE_KEYW 66 %token INT_KEYW 67 %token LONG_KEYW 68 %token REGISTER_KEYW 69 %token RESTRICT_KEYW 70 %token SHORT_KEYW 71 %token SIGNED_KEYW 72 %token STATIC_KEYW 73 %token STRUCT_KEYW 74 %token TYPEDEF_KEYW 75 %token UNION_KEYW 76 %token UNSIGNED_KEYW 77 %token VOID_KEYW 78 %token VOLATILE_KEYW 79 %token TYPEOF_KEYW 80 81 %token EXPORT_SYMBOL_KEYW 82 83 %token ASM_PHRASE 84 %token ATTRIBUTE_PHRASE 85 %token BRACE_PHRASE 86 %token BRACKET_PHRASE 87 %token EXPRESSION_PHRASE 88 89 %token CHAR 90 %token DOTS 91 %token IDENT 92 %token INT 93 %token REAL 94 %token STRING 95 %token TYPE 96 %token OTHER 97 %token FILENAME 98 99 %% 100 101 declaration_seq: 102 declaration 103 | declaration_seq declaration 104 ; 105 106 declaration: 107 { is_typedef = 0; is_extern = 0; current_name = NULL; decl_spec = NULL; } 108 declaration1 109 { free_list(*$2, NULL); *$2 = NULL; } 110 ; 111 112 declaration1: 113 TYPEDEF_KEYW { is_typedef = 1; } simple_declaration 114 { $$ = $3; } 115 | simple_declaration 116 | function_definition 117 | asm_definition 118 | export_definition 119 | error ';' { $$ = $2; } 120 | error '}' { $$ = $2; } 121 ; 122 123 simple_declaration: 124 decl_specifier_seq_opt init_declarator_list_opt ';' 125 { if (current_name) { 126 struct string_list *decl = (*$3)->next; 127 (*$3)->next = NULL; 128 add_symbol(current_name, 129 is_typedef ? SYM_TYPEDEF : SYM_NORMAL, 130 decl, is_extern); 131 current_name = NULL; 132 } 133 $$ = $3; 134 } 135 ; 136 137 init_declarator_list_opt: 138 /* empty */ { $$ = NULL; } 139 | init_declarator_list 140 ; 141 142 init_declarator_list: 143 init_declarator 144 { struct string_list *decl = *$1; 145 *$1 = NULL; 146 add_symbol(current_name, 147 is_typedef ? SYM_TYPEDEF : SYM_NORMAL, decl, is_extern); 148 current_name = NULL; 149 $$ = $1; 150 } 151 | init_declarator_list ',' init_declarator 152 { struct string_list *decl = *$3; 153 *$3 = NULL; 154 free_list(*$2, NULL); 155 *$2 = decl_spec; 156 add_symbol(current_name, 157 is_typedef ? SYM_TYPEDEF : SYM_NORMAL, decl, is_extern); 158 current_name = NULL; 159 $$ = $3; 160 } 161 ; 162 163 init_declarator: 164 declarator asm_phrase_opt attribute_opt initializer_opt 165 { $$ = $4 ? $4 : $3 ? $3 : $2 ? $2 : $1; } 166 ; 167 168 /* Hang on to the specifiers so that we can reuse them. */ 169 decl_specifier_seq_opt: 170 /* empty */ { decl_spec = NULL; } 171 | decl_specifier_seq 172 ; 173 174 decl_specifier_seq: 175 decl_specifier { decl_spec = *$1; } 176 | decl_specifier_seq decl_specifier { decl_spec = *$2; } 177 ; 178 179 decl_specifier: 180 storage_class_specifier 181 { /* Version 2 checksumming ignores storage class, as that 182 is really irrelevant to the linkage. */ 183 remove_node($1); 184 $$ = $1; 185 } 186 | type_specifier 187 ; 188 189 storage_class_specifier: 190 AUTO_KEYW 191 | REGISTER_KEYW 192 | STATIC_KEYW 193 | EXTERN_KEYW { is_extern = 1; $$ = $1; } 194 | INLINE_KEYW { is_extern = 0; $$ = $1; } 195 ; 196 197 type_specifier: 198 simple_type_specifier 199 | cvar_qualifier 200 | TYPEOF_KEYW '(' decl_specifier_seq ')' 201 202 /* References to s/u/e's defined elsewhere. Rearrange things 203 so that it is easier to expand the definition fully later. */ 204 | STRUCT_KEYW IDENT 205 { remove_node($1); (*$2)->tag = SYM_STRUCT; $$ = $2; } 206 | UNION_KEYW IDENT 207 { remove_node($1); (*$2)->tag = SYM_UNION; $$ = $2; } 208 | ENUM_KEYW IDENT 209 { remove_node($1); (*$2)->tag = SYM_ENUM; $$ = $2; } 210 211 /* Full definitions of an s/u/e. Record it. */ 212 | STRUCT_KEYW IDENT class_body 213 { struct string_list *s = *$3, *i = *$2, *r; 214 r = copy_node(i); r->tag = SYM_STRUCT; 215 r->next = (*$1)->next; *$3 = r; (*$1)->next = NULL; 216 add_symbol(i->string, SYM_STRUCT, s, is_extern); 217 $$ = $3; 218 } 219 | UNION_KEYW IDENT class_body 220 { struct string_list *s = *$3, *i = *$2, *r; 221 r = copy_node(i); r->tag = SYM_UNION; 222 r->next = (*$1)->next; *$3 = r; (*$1)->next = NULL; 223 add_symbol(i->string, SYM_UNION, s, is_extern); 224 $$ = $3; 225 } 226 | ENUM_KEYW IDENT BRACE_PHRASE 227 { struct string_list *s = *$3, *i = *$2, *r; 228 r = copy_node(i); r->tag = SYM_ENUM; 229 r->next = (*$1)->next; *$3 = r; (*$1)->next = NULL; 230 add_symbol(i->string, SYM_ENUM, s, is_extern); 231 $$ = $3; 232 } 233 234 /* Anonymous s/u/e definitions. Nothing needs doing. */ 235 | ENUM_KEYW BRACE_PHRASE { $$ = $2; } 236 | STRUCT_KEYW class_body { $$ = $2; } 237 | UNION_KEYW class_body { $$ = $2; } 238 ; 239 240 simple_type_specifier: 241 CHAR_KEYW 242 | SHORT_KEYW 243 | INT_KEYW 244 | LONG_KEYW 245 | SIGNED_KEYW 246 | UNSIGNED_KEYW 247 | FLOAT_KEYW 248 | DOUBLE_KEYW 249 | VOID_KEYW 250 | BOOL_KEYW 251 | TYPE { (*$1)->tag = SYM_TYPEDEF; $$ = $1; } 252 ; 253 254 ptr_operator: 255 '*' cvar_qualifier_seq_opt 256 { $$ = $2 ? $2 : $1; } 257 ; 258 259 cvar_qualifier_seq_opt: 260 /* empty */ { $$ = NULL; } 261 | cvar_qualifier_seq 262 ; 263 264 cvar_qualifier_seq: 265 cvar_qualifier 266 | cvar_qualifier_seq cvar_qualifier { $$ = $2; } 267 ; 268 269 cvar_qualifier: 270 CONST_KEYW | VOLATILE_KEYW | ATTRIBUTE_PHRASE 271 | RESTRICT_KEYW 272 { /* restrict has no effect in prototypes so ignore it */ 273 remove_node($1); 274 $$ = $1; 275 } 276 ; 277 278 declarator: 279 ptr_operator declarator { $$ = $2; } 280 | direct_declarator 281 ; 282 283 direct_declarator: 284 IDENT 285 { if (current_name != NULL) { 286 error_with_pos("unexpected second declaration name"); 287 YYERROR; 288 } else { 289 current_name = (*$1)->string; 290 $$ = $1; 291 } 292 } 293 | direct_declarator '(' parameter_declaration_clause ')' 294 { $$ = $4; } 295 | direct_declarator '(' error ')' 296 { $$ = $4; } 297 | direct_declarator BRACKET_PHRASE 298 { $$ = $2; } 299 | '(' declarator ')' 300 { $$ = $3; } 301 | '(' error ')' 302 { $$ = $3; } 303 ; 304 305 /* Nested declarators differ from regular declarators in that they do 306 not record the symbols they find in the global symbol table. */ 307 nested_declarator: 308 ptr_operator nested_declarator { $$ = $2; } 309 | direct_nested_declarator 310 ; 311 312 direct_nested_declarator: 313 IDENT 314 | TYPE 315 | direct_nested_declarator '(' parameter_declaration_clause ')' 316 { $$ = $4; } 317 | direct_nested_declarator '(' error ')' 318 { $$ = $4; } 319 | direct_nested_declarator BRACKET_PHRASE 320 { $$ = $2; } 321 | '(' nested_declarator ')' 322 { $$ = $3; } 323 | '(' error ')' 324 { $$ = $3; } 325 ; 326 327 parameter_declaration_clause: 328 parameter_declaration_list_opt DOTS { $$ = $2; } 329 | parameter_declaration_list_opt 330 | parameter_declaration_list ',' DOTS { $$ = $3; } 331 ; 332 333 parameter_declaration_list_opt: 334 /* empty */ { $$ = NULL; } 335 | parameter_declaration_list 336 ; 337 338 parameter_declaration_list: 339 parameter_declaration 340 | parameter_declaration_list ',' parameter_declaration 341 { $$ = $3; } 342 ; 343 344 parameter_declaration: 345 decl_specifier_seq m_abstract_declarator 346 { $$ = $2 ? $2 : $1; } 347 ; 348 349 m_abstract_declarator: 350 ptr_operator m_abstract_declarator 351 { $$ = $2 ? $2 : $1; } 352 | direct_m_abstract_declarator 353 ; 354 355 direct_m_abstract_declarator: 356 /* empty */ { $$ = NULL; } 357 | IDENT 358 { /* For version 2 checksums, we don't want to remember 359 private parameter names. */ 360 remove_node($1); 361 $$ = $1; 362 } 363 /* This wasn't really a typedef name but an identifier that 364 shadows one. */ 365 | TYPE 366 { remove_node($1); 367 $$ = $1; 368 } 369 | direct_m_abstract_declarator '(' parameter_declaration_clause ')' 370 { $$ = $4; } 371 | direct_m_abstract_declarator '(' error ')' 372 { $$ = $4; } 373 | direct_m_abstract_declarator BRACKET_PHRASE 374 { $$ = $2; } 375 | '(' m_abstract_declarator ')' 376 { $$ = $3; } 377 | '(' error ')' 378 { $$ = $3; } 379 ; 380 381 function_definition: 382 decl_specifier_seq_opt declarator BRACE_PHRASE 383 { struct string_list *decl = *$2; 384 *$2 = NULL; 385 add_symbol(current_name, SYM_NORMAL, decl, is_extern); 386 $$ = $3; 387 } 388 ; 389 390 initializer_opt: 391 /* empty */ { $$ = NULL; } 392 | initializer 393 ; 394 395 /* We never care about the contents of an initializer. */ 396 initializer: 397 '=' EXPRESSION_PHRASE 398 { remove_list($2, &(*$1)->next); $$ = $2; } 399 ; 400 401 class_body: 402 '{' member_specification_opt '}' { $$ = $3; } 403 | '{' error '}' { $$ = $3; } 404 ; 405 406 member_specification_opt: 407 /* empty */ { $$ = NULL; } 408 | member_specification 409 ; 410 411 member_specification: 412 member_declaration 413 | member_specification member_declaration { $$ = $2; } 414 ; 415 416 member_declaration: 417 decl_specifier_seq_opt member_declarator_list_opt ';' 418 { $$ = $3; } 419 | error ';' 420 { $$ = $2; } 421 ; 422 423 member_declarator_list_opt: 424 /* empty */ { $$ = NULL; } 425 | member_declarator_list 426 ; 427 428 member_declarator_list: 429 member_declarator 430 | member_declarator_list ',' member_declarator { $$ = $3; } 431 ; 432 433 member_declarator: 434 nested_declarator attribute_opt { $$ = $2 ? $2 : $1; } 435 | IDENT member_bitfield_declarator { $$ = $2; } 436 | member_bitfield_declarator 437 ; 438 439 member_bitfield_declarator: 440 ':' EXPRESSION_PHRASE { $$ = $2; } 441 ; 442 443 attribute_opt: 444 /* empty */ { $$ = NULL; } 445 | ATTRIBUTE_PHRASE 446 ; 447 448 asm_definition: 449 ASM_PHRASE ';' { $$ = $2; } 450 ; 451 452 asm_phrase_opt: 453 /* empty */ { $$ = NULL; } 454 | ASM_PHRASE 455 ; 456 457 export_definition: 458 EXPORT_SYMBOL_KEYW '(' IDENT ')' ';' 459 { export_symbol((*$3)->string); $$ = $5; } 460 ; 461 462 463 %% 464 465 static void 466 yyerror(const char *e) 467 { 468 error_with_pos("%s", e); 469 } 470