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