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