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