Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0-or-later */
0002 /*
0003  * C global declaration parser for genksyms.
0004  * Copyright 1996, 1997 Linux International.
0005  *
0006  * New implementation contributed by Richard Henderson <rth@tamu.edu>
0007  * Based on original work by Bjorn Ekwall <bj0rn@blox.se>
0008  *
0009  * This file is part of the Linux modutils.
0010  */
0011 
0012 %{
0013 
0014 #include <assert.h>
0015 #include <stdlib.h>
0016 #include <string.h>
0017 #include "genksyms.h"
0018 
0019 static int is_typedef;
0020 static int is_extern;
0021 static char *current_name;
0022 static struct string_list *decl_spec;
0023 
0024 static void yyerror(const char *);
0025 
0026 static inline void
0027 remove_node(struct string_list **p)
0028 {
0029   struct string_list *node = *p;
0030   *p = node->next;
0031   free_node(node);
0032 }
0033 
0034 static inline void
0035 remove_list(struct string_list **pb, struct string_list **pe)
0036 {
0037   struct string_list *b = *pb, *e = *pe;
0038   *pb = e;
0039   free_list(b, e);
0040 }
0041 
0042 /* Record definition of a struct/union/enum */
0043 static void record_compound(struct string_list **keyw,
0044                        struct string_list **ident,
0045                        struct string_list **body,
0046                        enum symbol_type type)
0047 {
0048         struct string_list *b = *body, *i = *ident, *r;
0049 
0050         if (i->in_source_file) {
0051                 remove_node(keyw);
0052                 (*ident)->tag = type;
0053                 remove_list(body, ident);
0054                 return;
0055         }
0056         r = copy_node(i); r->tag = type;
0057         r->next = (*keyw)->next; *body = r; (*keyw)->next = NULL;
0058         add_symbol(i->string, type, b, is_extern);
0059 }
0060 
0061 %}
0062 
0063 %token ASM_KEYW
0064 %token ATTRIBUTE_KEYW
0065 %token AUTO_KEYW
0066 %token BOOL_KEYW
0067 %token BUILTIN_INT_KEYW
0068 %token CHAR_KEYW
0069 %token CONST_KEYW
0070 %token DOUBLE_KEYW
0071 %token ENUM_KEYW
0072 %token EXTERN_KEYW
0073 %token EXTENSION_KEYW
0074 %token FLOAT_KEYW
0075 %token INLINE_KEYW
0076 %token INT_KEYW
0077 %token LONG_KEYW
0078 %token REGISTER_KEYW
0079 %token RESTRICT_KEYW
0080 %token SHORT_KEYW
0081 %token SIGNED_KEYW
0082 %token STATIC_KEYW
0083 %token STATIC_ASSERT_KEYW
0084 %token STRUCT_KEYW
0085 %token TYPEDEF_KEYW
0086 %token UNION_KEYW
0087 %token UNSIGNED_KEYW
0088 %token VOID_KEYW
0089 %token VOLATILE_KEYW
0090 %token TYPEOF_KEYW
0091 %token VA_LIST_KEYW
0092 
0093 %token EXPORT_SYMBOL_KEYW
0094 
0095 %token ASM_PHRASE
0096 %token ATTRIBUTE_PHRASE
0097 %token TYPEOF_PHRASE
0098 %token BRACE_PHRASE
0099 %token BRACKET_PHRASE
0100 %token EXPRESSION_PHRASE
0101 %token STATIC_ASSERT_PHRASE
0102 
0103 %token CHAR
0104 %token DOTS
0105 %token IDENT
0106 %token INT
0107 %token REAL
0108 %token STRING
0109 %token TYPE
0110 %token OTHER
0111 %token FILENAME
0112 
0113 %%
0114 
0115 declaration_seq:
0116         declaration
0117         | declaration_seq declaration
0118         ;
0119 
0120 declaration:
0121         { is_typedef = 0; is_extern = 0; current_name = NULL; decl_spec = NULL; }
0122         declaration1
0123         { free_list(*$2, NULL); *$2 = NULL; }
0124         ;
0125 
0126 declaration1:
0127         EXTENSION_KEYW TYPEDEF_KEYW { is_typedef = 1; } simple_declaration
0128                 { $$ = $4; }
0129         | TYPEDEF_KEYW { is_typedef = 1; } simple_declaration
0130                 { $$ = $3; }
0131         | simple_declaration
0132         | function_definition
0133         | asm_definition
0134         | export_definition
0135         | static_assert
0136         | error ';'                             { $$ = $2; }
0137         | error '}'                             { $$ = $2; }
0138         ;
0139 
0140 simple_declaration:
0141         decl_specifier_seq_opt init_declarator_list_opt ';'
0142                 { if (current_name) {
0143                     struct string_list *decl = (*$3)->next;
0144                     (*$3)->next = NULL;
0145                     add_symbol(current_name,
0146                                is_typedef ? SYM_TYPEDEF : SYM_NORMAL,
0147                                decl, is_extern);
0148                     current_name = NULL;
0149                   }
0150                   $$ = $3;
0151                 }
0152         ;
0153 
0154 init_declarator_list_opt:
0155         /* empty */                             { $$ = NULL; }
0156         | init_declarator_list
0157         ;
0158 
0159 init_declarator_list:
0160         init_declarator
0161                 { struct string_list *decl = *$1;
0162                   *$1 = NULL;
0163                   add_symbol(current_name,
0164                              is_typedef ? SYM_TYPEDEF : SYM_NORMAL, decl, is_extern);
0165                   current_name = NULL;
0166                   $$ = $1;
0167                 }
0168         | init_declarator_list ',' init_declarator
0169                 { struct string_list *decl = *$3;
0170                   *$3 = NULL;
0171                   free_list(*$2, NULL);
0172                   *$2 = decl_spec;
0173                   add_symbol(current_name,
0174                              is_typedef ? SYM_TYPEDEF : SYM_NORMAL, decl, is_extern);
0175                   current_name = NULL;
0176                   $$ = $3;
0177                 }
0178         ;
0179 
0180 init_declarator:
0181         declarator asm_phrase_opt attribute_opt initializer_opt
0182                 { $$ = $4 ? $4 : $3 ? $3 : $2 ? $2 : $1; }
0183         ;
0184 
0185 /* Hang on to the specifiers so that we can reuse them.  */
0186 decl_specifier_seq_opt:
0187         /* empty */                             { decl_spec = NULL; }
0188         | decl_specifier_seq
0189         ;
0190 
0191 decl_specifier_seq:
0192         decl_specifier                          { decl_spec = *$1; }
0193         | decl_specifier_seq decl_specifier     { decl_spec = *$2; }
0194         ;
0195 
0196 decl_specifier:
0197         storage_class_specifier
0198                 { /* Version 2 checksumming ignores storage class, as that
0199                      is really irrelevant to the linkage.  */
0200                   remove_node($1);
0201                   $$ = $1;
0202                 }
0203         | type_specifier
0204         ;
0205 
0206 storage_class_specifier:
0207         AUTO_KEYW
0208         | REGISTER_KEYW
0209         | STATIC_KEYW
0210         | EXTERN_KEYW   { is_extern = 1; $$ = $1; }
0211         | INLINE_KEYW   { is_extern = 0; $$ = $1; }
0212         ;
0213 
0214 type_specifier:
0215         simple_type_specifier
0216         | cvar_qualifier
0217         | TYPEOF_KEYW '(' parameter_declaration ')'
0218         | TYPEOF_PHRASE
0219 
0220         /* References to s/u/e's defined elsewhere.  Rearrange things
0221            so that it is easier to expand the definition fully later.  */
0222         | STRUCT_KEYW IDENT
0223                 { remove_node($1); (*$2)->tag = SYM_STRUCT; $$ = $2; }
0224         | UNION_KEYW IDENT
0225                 { remove_node($1); (*$2)->tag = SYM_UNION; $$ = $2; }
0226         | ENUM_KEYW IDENT
0227                 { remove_node($1); (*$2)->tag = SYM_ENUM; $$ = $2; }
0228 
0229         /* Full definitions of an s/u/e.  Record it.  */
0230         | STRUCT_KEYW IDENT class_body
0231                 { record_compound($1, $2, $3, SYM_STRUCT); $$ = $3; }
0232         | UNION_KEYW IDENT class_body
0233                 { record_compound($1, $2, $3, SYM_UNION); $$ = $3; }
0234         | ENUM_KEYW IDENT enum_body
0235                 { record_compound($1, $2, $3, SYM_ENUM); $$ = $3; }
0236         /*
0237          * Anonymous enum definition. Tell add_symbol() to restart its counter.
0238          */
0239         | ENUM_KEYW enum_body
0240                 { add_symbol(NULL, SYM_ENUM, NULL, 0); $$ = $2; }
0241         /* Anonymous s/u definitions.  Nothing needs doing.  */
0242         | STRUCT_KEYW class_body                        { $$ = $2; }
0243         | UNION_KEYW class_body                         { $$ = $2; }
0244         ;
0245 
0246 simple_type_specifier:
0247         CHAR_KEYW
0248         | SHORT_KEYW
0249         | INT_KEYW
0250         | LONG_KEYW
0251         | SIGNED_KEYW
0252         | UNSIGNED_KEYW
0253         | FLOAT_KEYW
0254         | DOUBLE_KEYW
0255         | VOID_KEYW
0256         | BOOL_KEYW
0257         | VA_LIST_KEYW
0258         | BUILTIN_INT_KEYW
0259         | TYPE                  { (*$1)->tag = SYM_TYPEDEF; $$ = $1; }
0260         ;
0261 
0262 ptr_operator:
0263         '*' cvar_qualifier_seq_opt
0264                 { $$ = $2 ? $2 : $1; }
0265         ;
0266 
0267 cvar_qualifier_seq_opt:
0268         /* empty */                                     { $$ = NULL; }
0269         | cvar_qualifier_seq
0270         ;
0271 
0272 cvar_qualifier_seq:
0273         cvar_qualifier
0274         | cvar_qualifier_seq cvar_qualifier             { $$ = $2; }
0275         ;
0276 
0277 cvar_qualifier:
0278         CONST_KEYW | VOLATILE_KEYW | ATTRIBUTE_PHRASE
0279         | RESTRICT_KEYW
0280                 { /* restrict has no effect in prototypes so ignore it */
0281                   remove_node($1);
0282                   $$ = $1;
0283                 }
0284         ;
0285 
0286 declarator:
0287         ptr_operator declarator                 { $$ = $2; }
0288         | direct_declarator
0289         ;
0290 
0291 direct_declarator:
0292         IDENT
0293                 { if (current_name != NULL) {
0294                     error_with_pos("unexpected second declaration name");
0295                     YYERROR;
0296                   } else {
0297                     current_name = (*$1)->string;
0298                     $$ = $1;
0299                   }
0300                 }
0301         | TYPE
0302                 { if (current_name != NULL) {
0303                     error_with_pos("unexpected second declaration name");
0304                     YYERROR;
0305                   } else {
0306                     current_name = (*$1)->string;
0307                     $$ = $1;
0308                   }
0309                 }
0310         | direct_declarator '(' parameter_declaration_clause ')'
0311                 { $$ = $4; }
0312         | direct_declarator '(' error ')'
0313                 { $$ = $4; }
0314         | direct_declarator BRACKET_PHRASE
0315                 { $$ = $2; }
0316         | '(' declarator ')'
0317                 { $$ = $3; }
0318         ;
0319 
0320 /* Nested declarators differ from regular declarators in that they do
0321    not record the symbols they find in the global symbol table.  */
0322 nested_declarator:
0323         ptr_operator nested_declarator          { $$ = $2; }
0324         | direct_nested_declarator
0325         ;
0326 
0327 direct_nested_declarator:
0328         IDENT
0329         | TYPE
0330         | direct_nested_declarator '(' parameter_declaration_clause ')'
0331                 { $$ = $4; }
0332         | direct_nested_declarator '(' error ')'
0333                 { $$ = $4; }
0334         | direct_nested_declarator BRACKET_PHRASE
0335                 { $$ = $2; }
0336         | '(' nested_declarator ')'
0337                 { $$ = $3; }
0338         | '(' error ')'
0339                 { $$ = $3; }
0340         ;
0341 
0342 parameter_declaration_clause:
0343         parameter_declaration_list_opt DOTS             { $$ = $2; }
0344         | parameter_declaration_list_opt
0345         | parameter_declaration_list ',' DOTS           { $$ = $3; }
0346         ;
0347 
0348 parameter_declaration_list_opt:
0349         /* empty */                                     { $$ = NULL; }
0350         | parameter_declaration_list
0351         ;
0352 
0353 parameter_declaration_list:
0354         parameter_declaration
0355         | parameter_declaration_list ',' parameter_declaration
0356                 { $$ = $3; }
0357         ;
0358 
0359 parameter_declaration:
0360         decl_specifier_seq m_abstract_declarator
0361                 { $$ = $2 ? $2 : $1; }
0362         ;
0363 
0364 m_abstract_declarator:
0365         ptr_operator m_abstract_declarator
0366                 { $$ = $2 ? $2 : $1; }
0367         | direct_m_abstract_declarator
0368         ;
0369 
0370 direct_m_abstract_declarator:
0371         /* empty */                                     { $$ = NULL; }
0372         | IDENT
0373                 { /* For version 2 checksums, we don't want to remember
0374                      private parameter names.  */
0375                   remove_node($1);
0376                   $$ = $1;
0377                 }
0378         /* This wasn't really a typedef name but an identifier that
0379            shadows one.  */
0380         | TYPE
0381                 { remove_node($1);
0382                   $$ = $1;
0383                 }
0384         | direct_m_abstract_declarator '(' parameter_declaration_clause ')'
0385                 { $$ = $4; }
0386         | direct_m_abstract_declarator '(' error ')'
0387                 { $$ = $4; }
0388         | direct_m_abstract_declarator BRACKET_PHRASE
0389                 { $$ = $2; }
0390         | '(' m_abstract_declarator ')'
0391                 { $$ = $3; }
0392         | '(' error ')'
0393                 { $$ = $3; }
0394         ;
0395 
0396 function_definition:
0397         decl_specifier_seq_opt declarator BRACE_PHRASE
0398                 { struct string_list *decl = *$2;
0399                   *$2 = NULL;
0400                   add_symbol(current_name, SYM_NORMAL, decl, is_extern);
0401                   $$ = $3;
0402                 }
0403         ;
0404 
0405 initializer_opt:
0406         /* empty */                                     { $$ = NULL; }
0407         | initializer
0408         ;
0409 
0410 /* We never care about the contents of an initializer.  */
0411 initializer:
0412         '=' EXPRESSION_PHRASE
0413                 { remove_list($2, &(*$1)->next); $$ = $2; }
0414         ;
0415 
0416 class_body:
0417         '{' member_specification_opt '}'                { $$ = $3; }
0418         | '{' error '}'                                 { $$ = $3; }
0419         ;
0420 
0421 member_specification_opt:
0422         /* empty */                                     { $$ = NULL; }
0423         | member_specification
0424         ;
0425 
0426 member_specification:
0427         member_declaration
0428         | member_specification member_declaration       { $$ = $2; }
0429         ;
0430 
0431 member_declaration:
0432         decl_specifier_seq_opt member_declarator_list_opt ';'
0433                 { $$ = $3; }
0434         | error ';'
0435                 { $$ = $2; }
0436         ;
0437 
0438 member_declarator_list_opt:
0439         /* empty */                                     { $$ = NULL; }
0440         | member_declarator_list
0441         ;
0442 
0443 member_declarator_list:
0444         member_declarator
0445         | member_declarator_list ',' member_declarator  { $$ = $3; }
0446         ;
0447 
0448 member_declarator:
0449         nested_declarator attribute_opt                 { $$ = $2 ? $2 : $1; }
0450         | IDENT member_bitfield_declarator              { $$ = $2; }
0451         | member_bitfield_declarator
0452         ;
0453 
0454 member_bitfield_declarator:
0455         ':' EXPRESSION_PHRASE                           { $$ = $2; }
0456         ;
0457 
0458 attribute_opt:
0459         /* empty */                                     { $$ = NULL; }
0460         | attribute_opt ATTRIBUTE_PHRASE
0461         ;
0462 
0463 enum_body:
0464         '{' enumerator_list '}'                         { $$ = $3; }
0465         | '{' enumerator_list ',' '}'                   { $$ = $4; }
0466          ;
0467 
0468 enumerator_list:
0469         enumerator
0470         | enumerator_list ',' enumerator
0471 
0472 enumerator:
0473         IDENT
0474                 {
0475                         const char *name = strdup((*$1)->string);
0476                         add_symbol(name, SYM_ENUM_CONST, NULL, 0);
0477                 }
0478         | IDENT '=' EXPRESSION_PHRASE
0479                 {
0480                         const char *name = strdup((*$1)->string);
0481                         struct string_list *expr = copy_list_range(*$3, *$2);
0482                         add_symbol(name, SYM_ENUM_CONST, expr, 0);
0483                 }
0484 
0485 asm_definition:
0486         ASM_PHRASE ';'                                  { $$ = $2; }
0487         ;
0488 
0489 asm_phrase_opt:
0490         /* empty */                                     { $$ = NULL; }
0491         | ASM_PHRASE
0492         ;
0493 
0494 export_definition:
0495         EXPORT_SYMBOL_KEYW '(' IDENT ')' ';'
0496                 { export_symbol((*$3)->string); $$ = $5; }
0497         ;
0498 
0499 /* Ignore any module scoped _Static_assert(...) */
0500 static_assert:
0501         STATIC_ASSERT_PHRASE ';'                        { $$ = $2; }
0502         ;
0503 
0504 %%
0505 
0506 static void
0507 yyerror(const char *e)
0508 {
0509   error_with_pos("%s", e);
0510 }