162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-or-later */ 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * C global declaration parser for genksyms. 462306a36Sopenharmony_ci * Copyright 1996, 1997 Linux International. 562306a36Sopenharmony_ci * 662306a36Sopenharmony_ci * New implementation contributed by Richard Henderson <rth@tamu.edu> 762306a36Sopenharmony_ci * Based on original work by Bjorn Ekwall <bj0rn@blox.se> 862306a36Sopenharmony_ci * 962306a36Sopenharmony_ci * This file is part of the Linux modutils. 1062306a36Sopenharmony_ci */ 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_ci%{ 1362306a36Sopenharmony_ci 1462306a36Sopenharmony_ci#include <assert.h> 1562306a36Sopenharmony_ci#include <stdlib.h> 1662306a36Sopenharmony_ci#include <string.h> 1762306a36Sopenharmony_ci#include "genksyms.h" 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_cistatic int is_typedef; 2062306a36Sopenharmony_cistatic int is_extern; 2162306a36Sopenharmony_cistatic char *current_name; 2262306a36Sopenharmony_cistatic struct string_list *decl_spec; 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_cistatic void yyerror(const char *); 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_cistatic inline void 2762306a36Sopenharmony_ciremove_node(struct string_list **p) 2862306a36Sopenharmony_ci{ 2962306a36Sopenharmony_ci struct string_list *node = *p; 3062306a36Sopenharmony_ci *p = node->next; 3162306a36Sopenharmony_ci free_node(node); 3262306a36Sopenharmony_ci} 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_cistatic inline void 3562306a36Sopenharmony_ciremove_list(struct string_list **pb, struct string_list **pe) 3662306a36Sopenharmony_ci{ 3762306a36Sopenharmony_ci struct string_list *b = *pb, *e = *pe; 3862306a36Sopenharmony_ci *pb = e; 3962306a36Sopenharmony_ci free_list(b, e); 4062306a36Sopenharmony_ci} 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_ci/* Record definition of a struct/union/enum */ 4362306a36Sopenharmony_cistatic void record_compound(struct string_list **keyw, 4462306a36Sopenharmony_ci struct string_list **ident, 4562306a36Sopenharmony_ci struct string_list **body, 4662306a36Sopenharmony_ci enum symbol_type type) 4762306a36Sopenharmony_ci{ 4862306a36Sopenharmony_ci struct string_list *b = *body, *i = *ident, *r; 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_ci if (i->in_source_file) { 5162306a36Sopenharmony_ci remove_node(keyw); 5262306a36Sopenharmony_ci (*ident)->tag = type; 5362306a36Sopenharmony_ci remove_list(body, ident); 5462306a36Sopenharmony_ci return; 5562306a36Sopenharmony_ci } 5662306a36Sopenharmony_ci r = copy_node(i); r->tag = type; 5762306a36Sopenharmony_ci r->next = (*keyw)->next; *body = r; (*keyw)->next = NULL; 5862306a36Sopenharmony_ci add_symbol(i->string, type, b, is_extern); 5962306a36Sopenharmony_ci} 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_ci%} 6262306a36Sopenharmony_ci 6362306a36Sopenharmony_ci%token ASM_KEYW 6462306a36Sopenharmony_ci%token ATTRIBUTE_KEYW 6562306a36Sopenharmony_ci%token AUTO_KEYW 6662306a36Sopenharmony_ci%token BOOL_KEYW 6762306a36Sopenharmony_ci%token BUILTIN_INT_KEYW 6862306a36Sopenharmony_ci%token CHAR_KEYW 6962306a36Sopenharmony_ci%token CONST_KEYW 7062306a36Sopenharmony_ci%token DOUBLE_KEYW 7162306a36Sopenharmony_ci%token ENUM_KEYW 7262306a36Sopenharmony_ci%token EXTERN_KEYW 7362306a36Sopenharmony_ci%token EXTENSION_KEYW 7462306a36Sopenharmony_ci%token FLOAT_KEYW 7562306a36Sopenharmony_ci%token INLINE_KEYW 7662306a36Sopenharmony_ci%token INT_KEYW 7762306a36Sopenharmony_ci%token LONG_KEYW 7862306a36Sopenharmony_ci%token REGISTER_KEYW 7962306a36Sopenharmony_ci%token RESTRICT_KEYW 8062306a36Sopenharmony_ci%token SHORT_KEYW 8162306a36Sopenharmony_ci%token SIGNED_KEYW 8262306a36Sopenharmony_ci%token STATIC_KEYW 8362306a36Sopenharmony_ci%token STATIC_ASSERT_KEYW 8462306a36Sopenharmony_ci%token STRUCT_KEYW 8562306a36Sopenharmony_ci%token TYPEDEF_KEYW 8662306a36Sopenharmony_ci%token UNION_KEYW 8762306a36Sopenharmony_ci%token UNSIGNED_KEYW 8862306a36Sopenharmony_ci%token VOID_KEYW 8962306a36Sopenharmony_ci%token VOLATILE_KEYW 9062306a36Sopenharmony_ci%token TYPEOF_KEYW 9162306a36Sopenharmony_ci%token VA_LIST_KEYW 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_ci%token EXPORT_SYMBOL_KEYW 9462306a36Sopenharmony_ci 9562306a36Sopenharmony_ci%token ASM_PHRASE 9662306a36Sopenharmony_ci%token ATTRIBUTE_PHRASE 9762306a36Sopenharmony_ci%token TYPEOF_PHRASE 9862306a36Sopenharmony_ci%token BRACE_PHRASE 9962306a36Sopenharmony_ci%token BRACKET_PHRASE 10062306a36Sopenharmony_ci%token EXPRESSION_PHRASE 10162306a36Sopenharmony_ci%token STATIC_ASSERT_PHRASE 10262306a36Sopenharmony_ci 10362306a36Sopenharmony_ci%token CHAR 10462306a36Sopenharmony_ci%token DOTS 10562306a36Sopenharmony_ci%token IDENT 10662306a36Sopenharmony_ci%token INT 10762306a36Sopenharmony_ci%token REAL 10862306a36Sopenharmony_ci%token STRING 10962306a36Sopenharmony_ci%token TYPE 11062306a36Sopenharmony_ci%token OTHER 11162306a36Sopenharmony_ci%token FILENAME 11262306a36Sopenharmony_ci 11362306a36Sopenharmony_ci%% 11462306a36Sopenharmony_ci 11562306a36Sopenharmony_cideclaration_seq: 11662306a36Sopenharmony_ci declaration 11762306a36Sopenharmony_ci | declaration_seq declaration 11862306a36Sopenharmony_ci ; 11962306a36Sopenharmony_ci 12062306a36Sopenharmony_cideclaration: 12162306a36Sopenharmony_ci { is_typedef = 0; is_extern = 0; current_name = NULL; decl_spec = NULL; } 12262306a36Sopenharmony_ci declaration1 12362306a36Sopenharmony_ci { free_list(*$2, NULL); *$2 = NULL; } 12462306a36Sopenharmony_ci ; 12562306a36Sopenharmony_ci 12662306a36Sopenharmony_cideclaration1: 12762306a36Sopenharmony_ci EXTENSION_KEYW TYPEDEF_KEYW { is_typedef = 1; } simple_declaration 12862306a36Sopenharmony_ci { $$ = $4; } 12962306a36Sopenharmony_ci | TYPEDEF_KEYW { is_typedef = 1; } simple_declaration 13062306a36Sopenharmony_ci { $$ = $3; } 13162306a36Sopenharmony_ci | simple_declaration 13262306a36Sopenharmony_ci | function_definition 13362306a36Sopenharmony_ci | asm_definition 13462306a36Sopenharmony_ci | export_definition 13562306a36Sopenharmony_ci | static_assert 13662306a36Sopenharmony_ci | error ';' { $$ = $2; } 13762306a36Sopenharmony_ci | error '}' { $$ = $2; } 13862306a36Sopenharmony_ci ; 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_cisimple_declaration: 14162306a36Sopenharmony_ci decl_specifier_seq_opt init_declarator_list_opt ';' 14262306a36Sopenharmony_ci { if (current_name) { 14362306a36Sopenharmony_ci struct string_list *decl = (*$3)->next; 14462306a36Sopenharmony_ci (*$3)->next = NULL; 14562306a36Sopenharmony_ci add_symbol(current_name, 14662306a36Sopenharmony_ci is_typedef ? SYM_TYPEDEF : SYM_NORMAL, 14762306a36Sopenharmony_ci decl, is_extern); 14862306a36Sopenharmony_ci current_name = NULL; 14962306a36Sopenharmony_ci } 15062306a36Sopenharmony_ci $$ = $3; 15162306a36Sopenharmony_ci } 15262306a36Sopenharmony_ci ; 15362306a36Sopenharmony_ci 15462306a36Sopenharmony_ciinit_declarator_list_opt: 15562306a36Sopenharmony_ci /* empty */ { $$ = NULL; } 15662306a36Sopenharmony_ci | init_declarator_list 15762306a36Sopenharmony_ci ; 15862306a36Sopenharmony_ci 15962306a36Sopenharmony_ciinit_declarator_list: 16062306a36Sopenharmony_ci init_declarator 16162306a36Sopenharmony_ci { struct string_list *decl = *$1; 16262306a36Sopenharmony_ci *$1 = NULL; 16362306a36Sopenharmony_ci add_symbol(current_name, 16462306a36Sopenharmony_ci is_typedef ? SYM_TYPEDEF : SYM_NORMAL, decl, is_extern); 16562306a36Sopenharmony_ci current_name = NULL; 16662306a36Sopenharmony_ci $$ = $1; 16762306a36Sopenharmony_ci } 16862306a36Sopenharmony_ci | init_declarator_list ',' init_declarator 16962306a36Sopenharmony_ci { struct string_list *decl = *$3; 17062306a36Sopenharmony_ci *$3 = NULL; 17162306a36Sopenharmony_ci free_list(*$2, NULL); 17262306a36Sopenharmony_ci *$2 = decl_spec; 17362306a36Sopenharmony_ci add_symbol(current_name, 17462306a36Sopenharmony_ci is_typedef ? SYM_TYPEDEF : SYM_NORMAL, decl, is_extern); 17562306a36Sopenharmony_ci current_name = NULL; 17662306a36Sopenharmony_ci $$ = $3; 17762306a36Sopenharmony_ci } 17862306a36Sopenharmony_ci ; 17962306a36Sopenharmony_ci 18062306a36Sopenharmony_ciinit_declarator: 18162306a36Sopenharmony_ci declarator asm_phrase_opt attribute_opt initializer_opt 18262306a36Sopenharmony_ci { $$ = $4 ? $4 : $3 ? $3 : $2 ? $2 : $1; } 18362306a36Sopenharmony_ci ; 18462306a36Sopenharmony_ci 18562306a36Sopenharmony_ci/* Hang on to the specifiers so that we can reuse them. */ 18662306a36Sopenharmony_cidecl_specifier_seq_opt: 18762306a36Sopenharmony_ci /* empty */ { decl_spec = NULL; } 18862306a36Sopenharmony_ci | decl_specifier_seq 18962306a36Sopenharmony_ci ; 19062306a36Sopenharmony_ci 19162306a36Sopenharmony_cidecl_specifier_seq: 19262306a36Sopenharmony_ci decl_specifier { decl_spec = *$1; } 19362306a36Sopenharmony_ci | decl_specifier_seq decl_specifier { decl_spec = *$2; } 19462306a36Sopenharmony_ci ; 19562306a36Sopenharmony_ci 19662306a36Sopenharmony_cidecl_specifier: 19762306a36Sopenharmony_ci storage_class_specifier 19862306a36Sopenharmony_ci { /* Version 2 checksumming ignores storage class, as that 19962306a36Sopenharmony_ci is really irrelevant to the linkage. */ 20062306a36Sopenharmony_ci remove_node($1); 20162306a36Sopenharmony_ci $$ = $1; 20262306a36Sopenharmony_ci } 20362306a36Sopenharmony_ci | type_specifier 20462306a36Sopenharmony_ci ; 20562306a36Sopenharmony_ci 20662306a36Sopenharmony_cistorage_class_specifier: 20762306a36Sopenharmony_ci AUTO_KEYW 20862306a36Sopenharmony_ci | REGISTER_KEYW 20962306a36Sopenharmony_ci | STATIC_KEYW 21062306a36Sopenharmony_ci | EXTERN_KEYW { is_extern = 1; $$ = $1; } 21162306a36Sopenharmony_ci | INLINE_KEYW { is_extern = 0; $$ = $1; } 21262306a36Sopenharmony_ci ; 21362306a36Sopenharmony_ci 21462306a36Sopenharmony_citype_specifier: 21562306a36Sopenharmony_ci simple_type_specifier 21662306a36Sopenharmony_ci | cvar_qualifier 21762306a36Sopenharmony_ci | TYPEOF_KEYW '(' parameter_declaration ')' 21862306a36Sopenharmony_ci | TYPEOF_PHRASE 21962306a36Sopenharmony_ci 22062306a36Sopenharmony_ci /* References to s/u/e's defined elsewhere. Rearrange things 22162306a36Sopenharmony_ci so that it is easier to expand the definition fully later. */ 22262306a36Sopenharmony_ci | STRUCT_KEYW IDENT 22362306a36Sopenharmony_ci { remove_node($1); (*$2)->tag = SYM_STRUCT; $$ = $2; } 22462306a36Sopenharmony_ci | UNION_KEYW IDENT 22562306a36Sopenharmony_ci { remove_node($1); (*$2)->tag = SYM_UNION; $$ = $2; } 22662306a36Sopenharmony_ci | ENUM_KEYW IDENT 22762306a36Sopenharmony_ci { remove_node($1); (*$2)->tag = SYM_ENUM; $$ = $2; } 22862306a36Sopenharmony_ci 22962306a36Sopenharmony_ci /* Full definitions of an s/u/e. Record it. */ 23062306a36Sopenharmony_ci | STRUCT_KEYW IDENT class_body 23162306a36Sopenharmony_ci { record_compound($1, $2, $3, SYM_STRUCT); $$ = $3; } 23262306a36Sopenharmony_ci | UNION_KEYW IDENT class_body 23362306a36Sopenharmony_ci { record_compound($1, $2, $3, SYM_UNION); $$ = $3; } 23462306a36Sopenharmony_ci | ENUM_KEYW IDENT enum_body 23562306a36Sopenharmony_ci { record_compound($1, $2, $3, SYM_ENUM); $$ = $3; } 23662306a36Sopenharmony_ci /* 23762306a36Sopenharmony_ci * Anonymous enum definition. Tell add_symbol() to restart its counter. 23862306a36Sopenharmony_ci */ 23962306a36Sopenharmony_ci | ENUM_KEYW enum_body 24062306a36Sopenharmony_ci { add_symbol(NULL, SYM_ENUM, NULL, 0); $$ = $2; } 24162306a36Sopenharmony_ci /* Anonymous s/u definitions. Nothing needs doing. */ 24262306a36Sopenharmony_ci | STRUCT_KEYW class_body { $$ = $2; } 24362306a36Sopenharmony_ci | UNION_KEYW class_body { $$ = $2; } 24462306a36Sopenharmony_ci ; 24562306a36Sopenharmony_ci 24662306a36Sopenharmony_cisimple_type_specifier: 24762306a36Sopenharmony_ci CHAR_KEYW 24862306a36Sopenharmony_ci | SHORT_KEYW 24962306a36Sopenharmony_ci | INT_KEYW 25062306a36Sopenharmony_ci | LONG_KEYW 25162306a36Sopenharmony_ci | SIGNED_KEYW 25262306a36Sopenharmony_ci | UNSIGNED_KEYW 25362306a36Sopenharmony_ci | FLOAT_KEYW 25462306a36Sopenharmony_ci | DOUBLE_KEYW 25562306a36Sopenharmony_ci | VOID_KEYW 25662306a36Sopenharmony_ci | BOOL_KEYW 25762306a36Sopenharmony_ci | VA_LIST_KEYW 25862306a36Sopenharmony_ci | BUILTIN_INT_KEYW 25962306a36Sopenharmony_ci | TYPE { (*$1)->tag = SYM_TYPEDEF; $$ = $1; } 26062306a36Sopenharmony_ci ; 26162306a36Sopenharmony_ci 26262306a36Sopenharmony_ciptr_operator: 26362306a36Sopenharmony_ci '*' cvar_qualifier_seq_opt 26462306a36Sopenharmony_ci { $$ = $2 ? $2 : $1; } 26562306a36Sopenharmony_ci ; 26662306a36Sopenharmony_ci 26762306a36Sopenharmony_cicvar_qualifier_seq_opt: 26862306a36Sopenharmony_ci /* empty */ { $$ = NULL; } 26962306a36Sopenharmony_ci | cvar_qualifier_seq 27062306a36Sopenharmony_ci ; 27162306a36Sopenharmony_ci 27262306a36Sopenharmony_cicvar_qualifier_seq: 27362306a36Sopenharmony_ci cvar_qualifier 27462306a36Sopenharmony_ci | cvar_qualifier_seq cvar_qualifier { $$ = $2; } 27562306a36Sopenharmony_ci ; 27662306a36Sopenharmony_ci 27762306a36Sopenharmony_cicvar_qualifier: 27862306a36Sopenharmony_ci CONST_KEYW | VOLATILE_KEYW | ATTRIBUTE_PHRASE 27962306a36Sopenharmony_ci | RESTRICT_KEYW 28062306a36Sopenharmony_ci { /* restrict has no effect in prototypes so ignore it */ 28162306a36Sopenharmony_ci remove_node($1); 28262306a36Sopenharmony_ci $$ = $1; 28362306a36Sopenharmony_ci } 28462306a36Sopenharmony_ci ; 28562306a36Sopenharmony_ci 28662306a36Sopenharmony_cideclarator: 28762306a36Sopenharmony_ci ptr_operator declarator { $$ = $2; } 28862306a36Sopenharmony_ci | direct_declarator 28962306a36Sopenharmony_ci ; 29062306a36Sopenharmony_ci 29162306a36Sopenharmony_cidirect_declarator: 29262306a36Sopenharmony_ci IDENT 29362306a36Sopenharmony_ci { if (current_name != NULL) { 29462306a36Sopenharmony_ci error_with_pos("unexpected second declaration name"); 29562306a36Sopenharmony_ci YYERROR; 29662306a36Sopenharmony_ci } else { 29762306a36Sopenharmony_ci current_name = (*$1)->string; 29862306a36Sopenharmony_ci $$ = $1; 29962306a36Sopenharmony_ci } 30062306a36Sopenharmony_ci } 30162306a36Sopenharmony_ci | TYPE 30262306a36Sopenharmony_ci { if (current_name != NULL) { 30362306a36Sopenharmony_ci error_with_pos("unexpected second declaration name"); 30462306a36Sopenharmony_ci YYERROR; 30562306a36Sopenharmony_ci } else { 30662306a36Sopenharmony_ci current_name = (*$1)->string; 30762306a36Sopenharmony_ci $$ = $1; 30862306a36Sopenharmony_ci } 30962306a36Sopenharmony_ci } 31062306a36Sopenharmony_ci | direct_declarator '(' parameter_declaration_clause ')' 31162306a36Sopenharmony_ci { $$ = $4; } 31262306a36Sopenharmony_ci | direct_declarator '(' error ')' 31362306a36Sopenharmony_ci { $$ = $4; } 31462306a36Sopenharmony_ci | direct_declarator BRACKET_PHRASE 31562306a36Sopenharmony_ci { $$ = $2; } 31662306a36Sopenharmony_ci | '(' declarator ')' 31762306a36Sopenharmony_ci { $$ = $3; } 31862306a36Sopenharmony_ci ; 31962306a36Sopenharmony_ci 32062306a36Sopenharmony_ci/* Nested declarators differ from regular declarators in that they do 32162306a36Sopenharmony_ci not record the symbols they find in the global symbol table. */ 32262306a36Sopenharmony_cinested_declarator: 32362306a36Sopenharmony_ci ptr_operator nested_declarator { $$ = $2; } 32462306a36Sopenharmony_ci | direct_nested_declarator 32562306a36Sopenharmony_ci ; 32662306a36Sopenharmony_ci 32762306a36Sopenharmony_cidirect_nested_declarator: 32862306a36Sopenharmony_ci IDENT 32962306a36Sopenharmony_ci | TYPE 33062306a36Sopenharmony_ci | direct_nested_declarator '(' parameter_declaration_clause ')' 33162306a36Sopenharmony_ci { $$ = $4; } 33262306a36Sopenharmony_ci | direct_nested_declarator '(' error ')' 33362306a36Sopenharmony_ci { $$ = $4; } 33462306a36Sopenharmony_ci | direct_nested_declarator BRACKET_PHRASE 33562306a36Sopenharmony_ci { $$ = $2; } 33662306a36Sopenharmony_ci | '(' nested_declarator ')' 33762306a36Sopenharmony_ci { $$ = $3; } 33862306a36Sopenharmony_ci | '(' error ')' 33962306a36Sopenharmony_ci { $$ = $3; } 34062306a36Sopenharmony_ci ; 34162306a36Sopenharmony_ci 34262306a36Sopenharmony_ciparameter_declaration_clause: 34362306a36Sopenharmony_ci parameter_declaration_list_opt DOTS { $$ = $2; } 34462306a36Sopenharmony_ci | parameter_declaration_list_opt 34562306a36Sopenharmony_ci | parameter_declaration_list ',' DOTS { $$ = $3; } 34662306a36Sopenharmony_ci ; 34762306a36Sopenharmony_ci 34862306a36Sopenharmony_ciparameter_declaration_list_opt: 34962306a36Sopenharmony_ci /* empty */ { $$ = NULL; } 35062306a36Sopenharmony_ci | parameter_declaration_list 35162306a36Sopenharmony_ci ; 35262306a36Sopenharmony_ci 35362306a36Sopenharmony_ciparameter_declaration_list: 35462306a36Sopenharmony_ci parameter_declaration 35562306a36Sopenharmony_ci | parameter_declaration_list ',' parameter_declaration 35662306a36Sopenharmony_ci { $$ = $3; } 35762306a36Sopenharmony_ci ; 35862306a36Sopenharmony_ci 35962306a36Sopenharmony_ciparameter_declaration: 36062306a36Sopenharmony_ci decl_specifier_seq m_abstract_declarator 36162306a36Sopenharmony_ci { $$ = $2 ? $2 : $1; } 36262306a36Sopenharmony_ci ; 36362306a36Sopenharmony_ci 36462306a36Sopenharmony_cim_abstract_declarator: 36562306a36Sopenharmony_ci ptr_operator m_abstract_declarator 36662306a36Sopenharmony_ci { $$ = $2 ? $2 : $1; } 36762306a36Sopenharmony_ci | direct_m_abstract_declarator 36862306a36Sopenharmony_ci ; 36962306a36Sopenharmony_ci 37062306a36Sopenharmony_cidirect_m_abstract_declarator: 37162306a36Sopenharmony_ci /* empty */ { $$ = NULL; } 37262306a36Sopenharmony_ci | IDENT 37362306a36Sopenharmony_ci { /* For version 2 checksums, we don't want to remember 37462306a36Sopenharmony_ci private parameter names. */ 37562306a36Sopenharmony_ci remove_node($1); 37662306a36Sopenharmony_ci $$ = $1; 37762306a36Sopenharmony_ci } 37862306a36Sopenharmony_ci /* This wasn't really a typedef name but an identifier that 37962306a36Sopenharmony_ci shadows one. */ 38062306a36Sopenharmony_ci | TYPE 38162306a36Sopenharmony_ci { remove_node($1); 38262306a36Sopenharmony_ci $$ = $1; 38362306a36Sopenharmony_ci } 38462306a36Sopenharmony_ci | direct_m_abstract_declarator '(' parameter_declaration_clause ')' 38562306a36Sopenharmony_ci { $$ = $4; } 38662306a36Sopenharmony_ci | direct_m_abstract_declarator '(' error ')' 38762306a36Sopenharmony_ci { $$ = $4; } 38862306a36Sopenharmony_ci | direct_m_abstract_declarator BRACKET_PHRASE 38962306a36Sopenharmony_ci { $$ = $2; } 39062306a36Sopenharmony_ci | '(' m_abstract_declarator ')' 39162306a36Sopenharmony_ci { $$ = $3; } 39262306a36Sopenharmony_ci | '(' error ')' 39362306a36Sopenharmony_ci { $$ = $3; } 39462306a36Sopenharmony_ci ; 39562306a36Sopenharmony_ci 39662306a36Sopenharmony_cifunction_definition: 39762306a36Sopenharmony_ci decl_specifier_seq_opt declarator BRACE_PHRASE 39862306a36Sopenharmony_ci { struct string_list *decl = *$2; 39962306a36Sopenharmony_ci *$2 = NULL; 40062306a36Sopenharmony_ci add_symbol(current_name, SYM_NORMAL, decl, is_extern); 40162306a36Sopenharmony_ci $$ = $3; 40262306a36Sopenharmony_ci } 40362306a36Sopenharmony_ci ; 40462306a36Sopenharmony_ci 40562306a36Sopenharmony_ciinitializer_opt: 40662306a36Sopenharmony_ci /* empty */ { $$ = NULL; } 40762306a36Sopenharmony_ci | initializer 40862306a36Sopenharmony_ci ; 40962306a36Sopenharmony_ci 41062306a36Sopenharmony_ci/* We never care about the contents of an initializer. */ 41162306a36Sopenharmony_ciinitializer: 41262306a36Sopenharmony_ci '=' EXPRESSION_PHRASE 41362306a36Sopenharmony_ci { remove_list($2, &(*$1)->next); $$ = $2; } 41462306a36Sopenharmony_ci ; 41562306a36Sopenharmony_ci 41662306a36Sopenharmony_ciclass_body: 41762306a36Sopenharmony_ci '{' member_specification_opt '}' { $$ = $3; } 41862306a36Sopenharmony_ci | '{' error '}' { $$ = $3; } 41962306a36Sopenharmony_ci ; 42062306a36Sopenharmony_ci 42162306a36Sopenharmony_cimember_specification_opt: 42262306a36Sopenharmony_ci /* empty */ { $$ = NULL; } 42362306a36Sopenharmony_ci | member_specification 42462306a36Sopenharmony_ci ; 42562306a36Sopenharmony_ci 42662306a36Sopenharmony_cimember_specification: 42762306a36Sopenharmony_ci member_declaration 42862306a36Sopenharmony_ci | member_specification member_declaration { $$ = $2; } 42962306a36Sopenharmony_ci ; 43062306a36Sopenharmony_ci 43162306a36Sopenharmony_cimember_declaration: 43262306a36Sopenharmony_ci decl_specifier_seq_opt member_declarator_list_opt ';' 43362306a36Sopenharmony_ci { $$ = $3; } 43462306a36Sopenharmony_ci | error ';' 43562306a36Sopenharmony_ci { $$ = $2; } 43662306a36Sopenharmony_ci ; 43762306a36Sopenharmony_ci 43862306a36Sopenharmony_cimember_declarator_list_opt: 43962306a36Sopenharmony_ci /* empty */ { $$ = NULL; } 44062306a36Sopenharmony_ci | member_declarator_list 44162306a36Sopenharmony_ci ; 44262306a36Sopenharmony_ci 44362306a36Sopenharmony_cimember_declarator_list: 44462306a36Sopenharmony_ci member_declarator 44562306a36Sopenharmony_ci | member_declarator_list ',' member_declarator { $$ = $3; } 44662306a36Sopenharmony_ci ; 44762306a36Sopenharmony_ci 44862306a36Sopenharmony_cimember_declarator: 44962306a36Sopenharmony_ci nested_declarator attribute_opt { $$ = $2 ? $2 : $1; } 45062306a36Sopenharmony_ci | IDENT member_bitfield_declarator { $$ = $2; } 45162306a36Sopenharmony_ci | member_bitfield_declarator 45262306a36Sopenharmony_ci ; 45362306a36Sopenharmony_ci 45462306a36Sopenharmony_cimember_bitfield_declarator: 45562306a36Sopenharmony_ci ':' EXPRESSION_PHRASE { $$ = $2; } 45662306a36Sopenharmony_ci ; 45762306a36Sopenharmony_ci 45862306a36Sopenharmony_ciattribute_opt: 45962306a36Sopenharmony_ci /* empty */ { $$ = NULL; } 46062306a36Sopenharmony_ci | attribute_opt ATTRIBUTE_PHRASE 46162306a36Sopenharmony_ci ; 46262306a36Sopenharmony_ci 46362306a36Sopenharmony_cienum_body: 46462306a36Sopenharmony_ci '{' enumerator_list '}' { $$ = $3; } 46562306a36Sopenharmony_ci | '{' enumerator_list ',' '}' { $$ = $4; } 46662306a36Sopenharmony_ci ; 46762306a36Sopenharmony_ci 46862306a36Sopenharmony_cienumerator_list: 46962306a36Sopenharmony_ci enumerator 47062306a36Sopenharmony_ci | enumerator_list ',' enumerator 47162306a36Sopenharmony_ci 47262306a36Sopenharmony_cienumerator: 47362306a36Sopenharmony_ci IDENT 47462306a36Sopenharmony_ci { 47562306a36Sopenharmony_ci const char *name = strdup((*$1)->string); 47662306a36Sopenharmony_ci add_symbol(name, SYM_ENUM_CONST, NULL, 0); 47762306a36Sopenharmony_ci } 47862306a36Sopenharmony_ci | IDENT '=' EXPRESSION_PHRASE 47962306a36Sopenharmony_ci { 48062306a36Sopenharmony_ci const char *name = strdup((*$1)->string); 48162306a36Sopenharmony_ci struct string_list *expr = copy_list_range(*$3, *$2); 48262306a36Sopenharmony_ci add_symbol(name, SYM_ENUM_CONST, expr, 0); 48362306a36Sopenharmony_ci } 48462306a36Sopenharmony_ci 48562306a36Sopenharmony_ciasm_definition: 48662306a36Sopenharmony_ci ASM_PHRASE ';' { $$ = $2; } 48762306a36Sopenharmony_ci ; 48862306a36Sopenharmony_ci 48962306a36Sopenharmony_ciasm_phrase_opt: 49062306a36Sopenharmony_ci /* empty */ { $$ = NULL; } 49162306a36Sopenharmony_ci | ASM_PHRASE 49262306a36Sopenharmony_ci ; 49362306a36Sopenharmony_ci 49462306a36Sopenharmony_ciexport_definition: 49562306a36Sopenharmony_ci EXPORT_SYMBOL_KEYW '(' IDENT ')' ';' 49662306a36Sopenharmony_ci { export_symbol((*$3)->string); $$ = $5; } 49762306a36Sopenharmony_ci ; 49862306a36Sopenharmony_ci 49962306a36Sopenharmony_ci/* Ignore any module scoped _Static_assert(...) */ 50062306a36Sopenharmony_cistatic_assert: 50162306a36Sopenharmony_ci STATIC_ASSERT_PHRASE ';' { $$ = $2; } 50262306a36Sopenharmony_ci ; 50362306a36Sopenharmony_ci 50462306a36Sopenharmony_ci%% 50562306a36Sopenharmony_ci 50662306a36Sopenharmony_cistatic void 50762306a36Sopenharmony_ciyyerror(const char *e) 50862306a36Sopenharmony_ci{ 50962306a36Sopenharmony_ci error_with_pos("%s", e); 51062306a36Sopenharmony_ci} 511