Home | History | Annotate | Line # | Download | only in test
grammar.y revision 1.1.1.6
      1 /* $Id: grammar.y,v 1.1.1.6 2016/01/09 21:55:11 christos Exp $
      2  *
      3  * yacc grammar for C function prototype generator
      4  * This was derived from the grammar in Appendix A of
      5  * "The C Programming Language" by Kernighan and Ritchie.
      6  */
      7 %expect 1
      8 %{
      9 #ifdef YYBISON
     10 #include <stdlib.h>
     11 #define YYSTYPE_IS_DECLARED
     12 #define yyerror yaccError
     13 #endif
     14 
     15 #if defined(YYBISON) || !defined(YYBYACC)
     16 static void yyerror(const char *s);
     17 #endif
     18 %}
     19 
     20 %token <text> '(' '*' '&'
     21 	/* identifiers that are not reserved words */
     22 	T_IDENTIFIER T_TYPEDEF_NAME T_DEFINE_NAME
     23 
     24 	/* storage class */
     25 	T_AUTO T_EXTERN T_REGISTER T_STATIC T_TYPEDEF
     26 	/* This keyword included for compatibility with C++. */
     27 	T_INLINE
     28 	/* This keyword included for compatibility with GCC */
     29 	T_EXTENSION
     30 
     31 	/* type specifiers */
     32 	T_CHAR T_DOUBLE T_FLOAT T_INT T_VOID
     33 	T_LONG T_SHORT T_SIGNED T_UNSIGNED
     34 	T_ENUM T_STRUCT T_UNION
     35 	/* C9X new types */
     36 	T_Bool T_Complex T_Imaginary
     37 
     38 	/* type qualifiers */
     39 	T_TYPE_QUALIFIER
     40 
     41 	/* paired square brackets and everything between them: [ ... ] */
     42 	T_BRACKETS
     43 
     44 %token
     45 	/* left brace */
     46 	T_LBRACE
     47 	/* all input to the matching right brace */
     48 	T_MATCHRBRACE
     49 
     50 	/* three periods */
     51 	T_ELLIPSIS
     52 
     53 	/* constant expression or paired braces following an equal sign */
     54 	T_INITIALIZER
     55 
     56 	/* string literal */
     57 	T_STRING_LITERAL
     58 
     59 	/* asm */
     60 	T_ASM
     61 	/* ( "string literal" ) following asm keyword */
     62 	T_ASMARG
     63 
     64 	/* va_dcl from <varargs.h> */
     65 	T_VA_DCL
     66 
     67 %type <decl_spec> decl_specifiers decl_specifier
     68 %type <decl_spec> storage_class type_specifier type_qualifier
     69 %type <decl_spec> struct_or_union_specifier enum_specifier
     70 %type <decl_list> init_declarator_list
     71 %type <declarator> init_declarator declarator direct_declarator
     72 %type <declarator> abs_declarator direct_abs_declarator
     73 %type <param_list> parameter_type_list parameter_list
     74 %type <parameter> parameter_declaration
     75 %type <param_list> opt_identifier_list identifier_list
     76 %type <text> struct_or_union pointer opt_type_qualifiers type_qualifier_list
     77 	any_id identifier_or_ref
     78 %type <text> enumeration
     79 
     80 %{
     81 #include <stdio.h>
     82 #include <ctype.h>
     83 #include <string.h>
     84 
     85 #define OPT_LINTLIBRARY 1
     86 
     87 #ifndef TRUE
     88 #define	TRUE	(1)
     89 #endif
     90 
     91 #ifndef FALSE
     92 #define	FALSE	(0)
     93 #endif
     94 
     95 /* #include "cproto.h" */
     96 #define MAX_TEXT_SIZE 1024
     97 
     98 /* Prototype styles */
     99 #if OPT_LINTLIBRARY
    100 #define PROTO_ANSI_LLIB		-2	/* form ANSI lint-library source */
    101 #define PROTO_LINTLIBRARY	-1	/* form lint-library source */
    102 #endif
    103 #define PROTO_NONE		0	/* do not output any prototypes */
    104 #define PROTO_TRADITIONAL	1	/* comment out parameters */
    105 #define PROTO_ABSTRACT		2	/* comment out parameter names */
    106 #define PROTO_ANSI		3	/* ANSI C prototype */
    107 
    108 typedef int PrototypeStyle;
    109 
    110 typedef char boolean;
    111 
    112 extern boolean types_out;
    113 extern PrototypeStyle proto_style;
    114 
    115 #define ansiLintLibrary() (proto_style == PROTO_ANSI_LLIB)
    116 #define knrLintLibrary()  (proto_style == PROTO_LINTLIBRARY)
    117 #define lintLibrary()     (knrLintLibrary() || ansiLintLibrary())
    118 
    119 #if OPT_LINTLIBRARY
    120 #define FUNC_UNKNOWN		-1	/* unspecified */
    121 #else
    122 #define FUNC_UNKNOWN		0	/* unspecified (same as FUNC_NONE) */
    123 #endif
    124 #define FUNC_NONE		0	/* not a function definition */
    125 #define FUNC_TRADITIONAL	1	/* traditional style */
    126 #define FUNC_ANSI		2	/* ANSI style */
    127 #define FUNC_BOTH		3	/* both styles */
    128 
    129 typedef int FuncDefStyle;
    130 
    131 /* Source file text */
    132 typedef struct text {
    133     char text[MAX_TEXT_SIZE];	/* source text */
    134     long begin; 		/* offset in temporary file */
    135 } Text;
    136 
    137 /* Declaration specifier flags */
    138 #define DS_NONE 	0	/* default */
    139 #define DS_EXTERN	1	/* contains "extern" specifier */
    140 #define DS_STATIC	2	/* contains "static" specifier */
    141 #define DS_CHAR 	4	/* contains "char" type specifier */
    142 #define DS_SHORT	8	/* contains "short" type specifier */
    143 #define DS_FLOAT	16	/* contains "float" type specifier */
    144 #define DS_INLINE	32	/* contains "inline" specifier */
    145 #define DS_JUNK 	64	/* we're not interested in this declaration */
    146 
    147 /* This structure stores information about a declaration specifier. */
    148 typedef struct decl_spec {
    149     unsigned short flags;	/* flags defined above */
    150     char *text; 		/* source text */
    151     long begin; 		/* offset in temporary file */
    152 } DeclSpec;
    153 
    154 /* This is a list of function parameters. */
    155 typedef struct _ParameterList {
    156     struct parameter *first;	/* pointer to first parameter in list */
    157     struct parameter *last;	/* pointer to last parameter in list */
    158     long begin_comment; 	/* begin offset of comment */
    159     long end_comment;		/* end offset of comment */
    160     char *comment;		/* comment at start of parameter list */
    161 } ParameterList;
    162 
    163 /* This structure stores information about a declarator. */
    164 typedef struct _Declarator {
    165     char *name; 			/* name of variable or function */
    166     char *text; 			/* source text */
    167     long begin; 			/* offset in temporary file */
    168     long begin_comment; 		/* begin offset of comment */
    169     long end_comment;			/* end offset of comment */
    170     FuncDefStyle func_def;		/* style of function definition */
    171     ParameterList params;		/* function parameters */
    172     boolean pointer;			/* TRUE if it declares a pointer */
    173     struct _Declarator *head;		/* head function declarator */
    174     struct _Declarator *func_stack;	/* stack of function declarators */
    175     struct _Declarator *next;		/* next declarator in list */
    176 } Declarator;
    177 
    178 /* This structure stores information about a function parameter. */
    179 typedef struct parameter {
    180     struct parameter *next;	/* next parameter in list */
    181     DeclSpec decl_spec;
    182     Declarator *declarator;
    183     char *comment;		/* comment following the parameter */
    184 } Parameter;
    185 
    186 /* This is a list of declarators. */
    187 typedef struct declarator_list {
    188     Declarator *first;		/* pointer to first declarator in list */
    189     Declarator *last;		/* pointer to last declarator in list */
    190 } DeclaratorList;
    191 
    192 /* #include "symbol.h" */
    193 typedef struct symbol {
    194     struct symbol *next;	/* next symbol in list */
    195     char *name; 		/* name of symbol */
    196     char *value;		/* value of symbol (for defines) */
    197     short flags;		/* symbol attributes */
    198 } Symbol;
    199 
    200 /* parser stack entry type */
    201 typedef union {
    202     Text text;
    203     DeclSpec decl_spec;
    204     Parameter *parameter;
    205     ParameterList param_list;
    206     Declarator *declarator;
    207     DeclaratorList decl_list;
    208 } YYSTYPE;
    209 
    210 /* The hash table length should be a prime number. */
    211 #define SYM_MAX_HASH 251
    212 
    213 typedef struct symbol_table {
    214     Symbol *bucket[SYM_MAX_HASH];	/* hash buckets */
    215 } SymbolTable;
    216 
    217 extern SymbolTable *new_symbol_table	/* Create symbol table */
    218 	(void);
    219 extern void free_symbol_table		/* Destroy symbol table */
    220 	(SymbolTable *s);
    221 extern Symbol *find_symbol		/* Lookup symbol name */
    222 	(SymbolTable *s, const char *n);
    223 extern Symbol *new_symbol		/* Define new symbol */
    224 	(SymbolTable *s, const char *n, const char *v, int f);
    225 
    226 /* #include "semantic.h" */
    227 extern void new_decl_spec (DeclSpec *, const char *, long, int);
    228 extern void free_decl_spec (DeclSpec *);
    229 extern void join_decl_specs (DeclSpec *, DeclSpec *, DeclSpec *);
    230 extern void check_untagged (DeclSpec *);
    231 extern Declarator *new_declarator (const char *, const char *, long);
    232 extern void free_declarator (Declarator *);
    233 extern void new_decl_list (DeclaratorList *, Declarator *);
    234 extern void free_decl_list (DeclaratorList *);
    235 extern void add_decl_list (DeclaratorList *, DeclaratorList *, Declarator *);
    236 extern Parameter *new_parameter (DeclSpec *, Declarator *);
    237 extern void free_parameter (Parameter *);
    238 extern void new_param_list (ParameterList *, Parameter *);
    239 extern void free_param_list (ParameterList *);
    240 extern void add_param_list (ParameterList *, ParameterList *, Parameter *);
    241 extern void new_ident_list (ParameterList *);
    242 extern void add_ident_list (ParameterList *, ParameterList *, const char *);
    243 extern void set_param_types (ParameterList *, DeclSpec *, DeclaratorList *);
    244 extern void gen_declarations (DeclSpec *, DeclaratorList *);
    245 extern void gen_prototype (DeclSpec *, Declarator *);
    246 extern void gen_func_declarator (Declarator *);
    247 extern void gen_func_definition (DeclSpec *, Declarator *);
    248 
    249 extern void init_parser     (void);
    250 extern void process_file    (FILE *infile, char *name);
    251 extern char *cur_text       (void);
    252 extern char *cur_file_name  (void);
    253 extern char *implied_typedef (void);
    254 extern void include_file    (char *name, int convert);
    255 extern char *supply_parm    (int count);
    256 extern char *xstrdup        (const char *);
    257 extern int already_declared (char *name);
    258 extern int is_actual_func   (Declarator *d);
    259 extern int lint_ellipsis    (Parameter *p);
    260 extern int want_typedef     (void);
    261 extern void begin_tracking  (void);
    262 extern void begin_typedef   (void);
    263 extern void copy_typedef    (char *s);
    264 extern void ellipsis_varargs (Declarator *d);
    265 extern void end_typedef     (void);
    266 extern void flush_varargs   (void);
    267 extern void fmt_library     (int code);
    268 extern void imply_typedef   (const char *s);
    269 extern void indent          (FILE *outf);
    270 extern void put_blankline   (FILE *outf);
    271 extern void put_body        (FILE *outf, DeclSpec *decl_spec, Declarator *declarator);
    272 extern void put_char        (FILE *outf, int c);
    273 extern void put_error       (void);
    274 extern void put_newline     (FILE *outf);
    275 extern void put_padded      (FILE *outf, const char *s);
    276 extern void put_string      (FILE *outf, const char *s);
    277 extern void track_in        (void);
    278 
    279 extern boolean file_comments;
    280 extern FuncDefStyle func_style;
    281 extern char base_file[];
    282 
    283 extern	int	yylex (void);
    284 
    285 /* declaration specifier attributes for the typedef statement currently being
    286  * scanned
    287  */
    288 static int cur_decl_spec_flags;
    289 
    290 /* pointer to parameter list for the current function definition */
    291 static ParameterList *func_params;
    292 
    293 /* A parser semantic action sets this pointer to the current declarator in
    294  * a function parameter declaration in order to catch any comments following
    295  * the parameter declaration on the same line.  If the lexer scans a comment
    296  * and <cur_declarator> is not NULL, then the comment is attached to the
    297  * declarator.  To ignore subsequent comments, the lexer sets this to NULL
    298  * after scanning a comment or end of line.
    299  */
    300 static Declarator *cur_declarator;
    301 
    302 /* temporary string buffer */
    303 static char buf[MAX_TEXT_SIZE];
    304 
    305 /* table of typedef names */
    306 static SymbolTable *typedef_names;
    307 
    308 /* table of define names */
    309 static SymbolTable *define_names;
    310 
    311 /* table of type qualifiers */
    312 static SymbolTable *type_qualifiers;
    313 
    314 /* information about the current input file */
    315 typedef struct {
    316     char *base_name;		/* base input file name */
    317     char *file_name;		/* current file name */
    318     FILE *file; 		/* input file */
    319     unsigned line_num;		/* current line number in input file */
    320     FILE *tmp_file;		/* temporary file */
    321     long begin_comment; 	/* tmp file offset after last written ) or ; */
    322     long end_comment;		/* tmp file offset after last comment */
    323     boolean convert;		/* if TRUE, convert function definitions */
    324     boolean changed;		/* TRUE if conversion done in this file */
    325 } IncludeStack;
    326 
    327 static IncludeStack *cur_file;	/* current input file */
    328 
    329 /* #include "yyerror.c" */
    330 
    331 static int haveAnsiParam (void);
    332 
    333 
    334 /* Flags to enable us to find if a procedure returns a value.
    335  */
    336 static int return_val;	/* nonzero on BRACES iff return-expression found */
    337 
    338 static const char *
    339 dft_decl_spec (void)
    340 {
    341     return (lintLibrary() && !return_val) ? "void" : "int";
    342 }
    343 
    344 static int
    345 haveAnsiParam (void)
    346 {
    347     Parameter *p;
    348     if (func_params != 0) {
    349 	for (p = func_params->first; p != 0; p = p->next) {
    350 	    if (p->declarator->func_def == FUNC_ANSI) {
    351 		return TRUE;
    352 	    }
    353 	}
    354     }
    355     return FALSE;
    356 }
    357 %}
    358 %%
    359 
    360 program
    361 	: /* empty */
    362 	| translation_unit
    363 	;
    364 
    365 translation_unit
    366 	: external_declaration
    367 	| translation_unit external_declaration
    368 	;
    369 
    370 external_declaration
    371 	: declaration
    372 	| function_definition
    373 	| ';'
    374 	| linkage_specification
    375 	| T_ASM T_ASMARG ';'
    376 	| error T_MATCHRBRACE
    377 	{
    378 	    yyerrok;
    379 	}
    380 	| error ';'
    381 	{
    382 	    yyerrok;
    383 	}
    384 	;
    385 
    386 braces
    387 	: T_LBRACE T_MATCHRBRACE
    388 	;
    389 
    390 linkage_specification
    391 	: T_EXTERN T_STRING_LITERAL braces
    392 	{
    393 	    /* Provide an empty action here so bison will not complain about
    394 	     * incompatible types in the default action it normally would
    395 	     * have generated.
    396 	     */
    397 	}
    398 	| T_EXTERN T_STRING_LITERAL declaration
    399 	{
    400 	    /* empty */
    401 	}
    402 	;
    403 
    404 declaration
    405 	: decl_specifiers ';'
    406 	{
    407 #if OPT_LINTLIBRARY
    408 	    if (types_out && want_typedef()) {
    409 		gen_declarations(&$1, (DeclaratorList *)0);
    410 		flush_varargs();
    411 	    }
    412 #endif
    413 	    free_decl_spec(&$1);
    414 	    end_typedef();
    415 	}
    416 	| decl_specifiers init_declarator_list ';'
    417 	{
    418 	    if (func_params != NULL) {
    419 		set_param_types(func_params, &$1, &$2);
    420 	    } else {
    421 		gen_declarations(&$1, &$2);
    422 #if OPT_LINTLIBRARY
    423 		flush_varargs();
    424 #endif
    425 		free_decl_list(&$2);
    426 	    }
    427 	    free_decl_spec(&$1);
    428 	    end_typedef();
    429 	}
    430 	| any_typedef decl_specifiers
    431 	{
    432 	    cur_decl_spec_flags = $2.flags;
    433 	    free_decl_spec(&$2);
    434 	}
    435 	  opt_declarator_list ';'
    436 	{
    437 	    end_typedef();
    438 	}
    439 	;
    440 
    441 any_typedef
    442 	: T_EXTENSION T_TYPEDEF
    443 	{
    444 	    begin_typedef();
    445 	}
    446 	| T_TYPEDEF
    447 	{
    448 	    begin_typedef();
    449 	}
    450 	;
    451 
    452 opt_declarator_list
    453 	: /* empty */
    454 	| declarator_list
    455 	;
    456 
    457 declarator_list
    458 	: declarator
    459 	{
    460 	    int flags = cur_decl_spec_flags;
    461 
    462 	    /* If the typedef is a pointer type, then reset the short type
    463 	     * flags so it does not get promoted.
    464 	     */
    465 	    if (strcmp($1->text, $1->name) != 0)
    466 		flags &= ~(DS_CHAR | DS_SHORT | DS_FLOAT);
    467 	    new_symbol(typedef_names, $1->name, NULL, flags);
    468 	    free_declarator($1);
    469 	}
    470 	| declarator_list ',' declarator
    471 	{
    472 	    int flags = cur_decl_spec_flags;
    473 
    474 	    if (strcmp($3->text, $3->name) != 0)
    475 		flags &= ~(DS_CHAR | DS_SHORT | DS_FLOAT);
    476 	    new_symbol(typedef_names, $3->name, NULL, flags);
    477 	    free_declarator($3);
    478 	}
    479 	;
    480 
    481 function_definition
    482 	: decl_specifiers declarator
    483 	{
    484 	    check_untagged(&$1);
    485 	    if ($2->func_def == FUNC_NONE) {
    486 		yyerror("syntax error");
    487 		YYERROR;
    488 	    }
    489 	    func_params = &($2->head->params);
    490 	    func_params->begin_comment = cur_file->begin_comment;
    491 	    func_params->end_comment = cur_file->end_comment;
    492 	}
    493 	  opt_declaration_list T_LBRACE
    494 	{
    495 	    /* If we're converting to K&R and we've got a nominally K&R
    496 	     * function which has a parameter which is ANSI (i.e., a prototyped
    497 	     * function pointer), then we must override the deciphered value of
    498 	     * 'func_def' so that the parameter will be converted.
    499 	     */
    500 	    if (func_style == FUNC_TRADITIONAL
    501 	     && haveAnsiParam()
    502 	     && $2->head->func_def == func_style) {
    503 		$2->head->func_def = FUNC_BOTH;
    504 	    }
    505 
    506 	    func_params = NULL;
    507 
    508 	    if (cur_file->convert)
    509 		gen_func_definition(&$1, $2);
    510 	    gen_prototype(&$1, $2);
    511 #if OPT_LINTLIBRARY
    512 	    flush_varargs();
    513 #endif
    514 	    free_decl_spec(&$1);
    515 	    free_declarator($2);
    516 	}
    517 	  T_MATCHRBRACE
    518 	| declarator
    519 	{
    520 	    if ($1->func_def == FUNC_NONE) {
    521 		yyerror("syntax error");
    522 		YYERROR;
    523 	    }
    524 	    func_params = &($1->head->params);
    525 	    func_params->begin_comment = cur_file->begin_comment;
    526 	    func_params->end_comment = cur_file->end_comment;
    527 	}
    528 	  opt_declaration_list T_LBRACE T_MATCHRBRACE
    529 	{
    530 	    DeclSpec decl_spec;
    531 
    532 	    func_params = NULL;
    533 
    534 	    new_decl_spec(&decl_spec, dft_decl_spec(), $1->begin, DS_NONE);
    535 	    if (cur_file->convert)
    536 		gen_func_definition(&decl_spec, $1);
    537 	    gen_prototype(&decl_spec, $1);
    538 #if OPT_LINTLIBRARY
    539 	    flush_varargs();
    540 #endif
    541 	    free_decl_spec(&decl_spec);
    542 	    free_declarator($1);
    543 	}
    544 	;
    545 
    546 opt_declaration_list
    547 	: /* empty */
    548 	| T_VA_DCL
    549 	| declaration_list
    550 	;
    551 
    552 declaration_list
    553 	: declaration
    554 	| declaration_list declaration
    555 	;
    556 
    557 decl_specifiers
    558 	: decl_specifier
    559 	| decl_specifiers decl_specifier
    560 	{
    561 	    join_decl_specs(&$$, &$1, &$2);
    562 	    free($1.text);
    563 	    free($2.text);
    564 	}
    565 	;
    566 
    567 decl_specifier
    568 	: storage_class
    569 	| type_specifier
    570 	| type_qualifier
    571 	;
    572 
    573 storage_class
    574 	: T_AUTO
    575 	{
    576 	    new_decl_spec(&$$, $1.text, $1.begin, DS_NONE);
    577 	}
    578 	| T_EXTERN
    579 	{
    580 	    new_decl_spec(&$$, $1.text, $1.begin, DS_EXTERN);
    581 	}
    582 	| T_REGISTER
    583 	{
    584 	    new_decl_spec(&$$, $1.text, $1.begin, DS_NONE);
    585 	}
    586 	| T_STATIC
    587 	{
    588 	    new_decl_spec(&$$, $1.text, $1.begin, DS_STATIC);
    589 	}
    590 	| T_INLINE
    591 	{
    592 	    new_decl_spec(&$$, $1.text, $1.begin, DS_INLINE);
    593 	}
    594 	| T_EXTENSION
    595 	{
    596 	    new_decl_spec(&$$, $1.text, $1.begin, DS_JUNK);
    597 	}
    598 	;
    599 
    600 type_specifier
    601 	: T_CHAR
    602 	{
    603 	    new_decl_spec(&$$, $1.text, $1.begin, DS_CHAR);
    604 	}
    605 	| T_DOUBLE
    606 	{
    607 	    new_decl_spec(&$$, $1.text, $1.begin, DS_NONE);
    608 	}
    609 	| T_FLOAT
    610 	{
    611 	    new_decl_spec(&$$, $1.text, $1.begin, DS_FLOAT);
    612 	}
    613 	| T_INT
    614 	{
    615 	    new_decl_spec(&$$, $1.text, $1.begin, DS_NONE);
    616 	}
    617 	| T_LONG
    618 	{
    619 	    new_decl_spec(&$$, $1.text, $1.begin, DS_NONE);
    620 	}
    621 	| T_SHORT
    622 	{
    623 	    new_decl_spec(&$$, $1.text, $1.begin, DS_SHORT);
    624 	}
    625 	| T_SIGNED
    626 	{
    627 	    new_decl_spec(&$$, $1.text, $1.begin, DS_NONE);
    628 	}
    629 	| T_UNSIGNED
    630 	{
    631 	    new_decl_spec(&$$, $1.text, $1.begin, DS_NONE);
    632 	}
    633 	| T_VOID
    634 	{
    635 	    new_decl_spec(&$$, $1.text, $1.begin, DS_NONE);
    636 	}
    637 	| T_Bool
    638 	{
    639 	    new_decl_spec(&$$, $1.text, $1.begin, DS_CHAR);
    640 	}
    641 	| T_Complex
    642 	{
    643 	    new_decl_spec(&$$, $1.text, $1.begin, DS_NONE);
    644 	}
    645 	| T_Imaginary
    646 	{
    647 	    new_decl_spec(&$$, $1.text, $1.begin, DS_NONE);
    648 	}
    649 	| T_TYPEDEF_NAME
    650 	{
    651 	    Symbol *s;
    652 	    s = find_symbol(typedef_names, $1.text);
    653 	    if (s != NULL)
    654 		new_decl_spec(&$$, $1.text, $1.begin, s->flags);
    655 	}
    656 	| struct_or_union_specifier
    657 	| enum_specifier
    658 	;
    659 
    660 type_qualifier
    661 	: T_TYPE_QUALIFIER
    662 	{
    663 	    new_decl_spec(&$$, $1.text, $1.begin, DS_NONE);
    664 	}
    665 	| T_DEFINE_NAME
    666 	{
    667 	    /* This rule allows the <pointer> nonterminal to scan #define
    668 	     * names as if they were type modifiers.
    669 	     */
    670 	    Symbol *s;
    671 	    s = find_symbol(define_names, $1.text);
    672 	    if (s != NULL)
    673 		new_decl_spec(&$$, $1.text, $1.begin, s->flags);
    674 	}
    675 	;
    676 
    677 struct_or_union_specifier
    678 	: struct_or_union any_id braces
    679 	{
    680 	    char *s;
    681 	    if ((s = implied_typedef()) == 0)
    682 	        (void)sprintf(s = buf, "%s %s", $1.text, $2.text);
    683 	    new_decl_spec(&$$, s, $1.begin, DS_NONE);
    684 	}
    685 	| struct_or_union braces
    686 	{
    687 	    char *s;
    688 	    if ((s = implied_typedef()) == 0)
    689 		(void)sprintf(s = buf, "%s {}", $1.text);
    690 	    new_decl_spec(&$$, s, $1.begin, DS_NONE);
    691 	}
    692 	| struct_or_union any_id
    693 	{
    694 	    (void)sprintf(buf, "%s %s", $1.text, $2.text);
    695 	    new_decl_spec(&$$, buf, $1.begin, DS_NONE);
    696 	}
    697 	;
    698 
    699 struct_or_union
    700 	: T_STRUCT
    701 	{
    702 	    imply_typedef($$.text);
    703 	}
    704 	| T_UNION
    705 	{
    706 	    imply_typedef($$.text);
    707 	}
    708 	;
    709 
    710 init_declarator_list
    711 	: init_declarator
    712 	{
    713 	    new_decl_list(&$$, $1);
    714 	}
    715 	| init_declarator_list ',' init_declarator
    716 	{
    717 	    add_decl_list(&$$, &$1, $3);
    718 	}
    719 	;
    720 
    721 init_declarator
    722 	: declarator
    723 	{
    724 	    if ($1->func_def != FUNC_NONE && func_params == NULL &&
    725 		func_style == FUNC_TRADITIONAL && cur_file->convert) {
    726 		gen_func_declarator($1);
    727 		fputs(cur_text(), cur_file->tmp_file);
    728 	    }
    729 	    cur_declarator = $$;
    730 	}
    731 	| declarator '='
    732 	{
    733 	    if ($1->func_def != FUNC_NONE && func_params == NULL &&
    734 		func_style == FUNC_TRADITIONAL && cur_file->convert) {
    735 		gen_func_declarator($1);
    736 		fputs(" =", cur_file->tmp_file);
    737 	    }
    738 	}
    739 	  T_INITIALIZER
    740 	;
    741 
    742 enum_specifier
    743 	: enumeration any_id braces
    744 	{
    745 	    char *s;
    746 	    if ((s = implied_typedef()) == 0)
    747 		(void)sprintf(s = buf, "enum %s", $2.text);
    748 	    new_decl_spec(&$$, s, $1.begin, DS_NONE);
    749 	}
    750 	| enumeration braces
    751 	{
    752 	    char *s;
    753 	    if ((s = implied_typedef()) == 0)
    754 		(void)sprintf(s = buf, "%s {}", $1.text);
    755 	    new_decl_spec(&$$, s, $1.begin, DS_NONE);
    756 	}
    757 	| enumeration any_id
    758 	{
    759 	    (void)sprintf(buf, "enum %s", $2.text);
    760 	    new_decl_spec(&$$, buf, $1.begin, DS_NONE);
    761 	}
    762 	;
    763 
    764 enumeration
    765 	: T_ENUM
    766 	{
    767 	    imply_typedef("enum");
    768 	    $$ = $1;
    769 	}
    770 	;
    771 
    772 any_id
    773 	: T_IDENTIFIER
    774 	| T_TYPEDEF_NAME
    775 	;
    776 
    777 declarator
    778 	: pointer direct_declarator
    779 	{
    780 	    $$ = $2;
    781 	    (void)sprintf(buf, "%s%s", $1.text, $$->text);
    782 	    free($$->text);
    783 	    $$->text = xstrdup(buf);
    784 	    $$->begin = $1.begin;
    785 	    $$->pointer = TRUE;
    786 	}
    787 	| direct_declarator
    788 	;
    789 
    790 direct_declarator
    791 	: identifier_or_ref
    792 	{
    793 	    $$ = new_declarator($1.text, $1.text, $1.begin);
    794 	}
    795 	| '(' declarator ')'
    796 	{
    797 	    $$ = $2;
    798 	    (void)sprintf(buf, "(%s)", $$->text);
    799 	    free($$->text);
    800 	    $$->text = xstrdup(buf);
    801 	    $$->begin = $1.begin;
    802 	}
    803 	| direct_declarator T_BRACKETS
    804 	{
    805 	    $$ = $1;
    806 	    (void)sprintf(buf, "%s%s", $$->text, $2.text);
    807 	    free($$->text);
    808 	    $$->text = xstrdup(buf);
    809 	}
    810 	| direct_declarator '(' parameter_type_list ')'
    811 	{
    812 	    $$ = new_declarator("%s()", $1->name, $1->begin);
    813 	    $$->params = $3;
    814 	    $$->func_stack = $1;
    815 	    $$->head = ($1->func_stack == NULL) ? $$ : $1->head;
    816 	    $$->func_def = FUNC_ANSI;
    817 	}
    818 	| direct_declarator '(' opt_identifier_list ')'
    819 	{
    820 	    $$ = new_declarator("%s()", $1->name, $1->begin);
    821 	    $$->params = $3;
    822 	    $$->func_stack = $1;
    823 	    $$->head = ($1->func_stack == NULL) ? $$ : $1->head;
    824 	    $$->func_def = FUNC_TRADITIONAL;
    825 	}
    826 	;
    827 
    828 pointer
    829 	: '*' opt_type_qualifiers
    830 	{
    831 	    (void)sprintf($$.text, "*%s", $2.text);
    832 	    $$.begin = $1.begin;
    833 	}
    834 	| '*' opt_type_qualifiers pointer
    835 	{
    836 	    (void)sprintf($$.text, "*%s%s", $2.text, $3.text);
    837 	    $$.begin = $1.begin;
    838 	}
    839 	;
    840 
    841 opt_type_qualifiers
    842 	: /* empty */
    843 	{
    844 	    strcpy($$.text, "");
    845 	    $$.begin = 0L;
    846 	}
    847 	| type_qualifier_list
    848 	;
    849 
    850 type_qualifier_list
    851 	: type_qualifier
    852 	{
    853 	    (void)sprintf($$.text, "%s ", $1.text);
    854 	    $$.begin = $1.begin;
    855 	    free($1.text);
    856 	}
    857 	| type_qualifier_list type_qualifier
    858 	{
    859 	    (void)sprintf($$.text, "%s%s ", $1.text, $2.text);
    860 	    $$.begin = $1.begin;
    861 	    free($2.text);
    862 	}
    863 	;
    864 
    865 parameter_type_list
    866 	: parameter_list
    867 	| parameter_list ',' T_ELLIPSIS
    868 	{
    869 	    add_ident_list(&$$, &$1, "...");
    870 	}
    871 	;
    872 
    873 parameter_list
    874 	: parameter_declaration
    875 	{
    876 	    new_param_list(&$$, $1);
    877 	}
    878 	| parameter_list ',' parameter_declaration
    879 	{
    880 	    add_param_list(&$$, &$1, $3);
    881 	}
    882 	;
    883 
    884 parameter_declaration
    885 	: decl_specifiers declarator
    886 	{
    887 	    check_untagged(&$1);
    888 	    $$ = new_parameter(&$1, $2);
    889 	}
    890 	| decl_specifiers abs_declarator
    891 	{
    892 	    check_untagged(&$1);
    893 	    $$ = new_parameter(&$1, $2);
    894 	}
    895 	| decl_specifiers
    896 	{
    897 	    check_untagged(&$1);
    898 	    $$ = new_parameter(&$1, (Declarator *)0);
    899 	}
    900 	;
    901 
    902 opt_identifier_list
    903 	: /* empty */
    904 	{
    905 	    new_ident_list(&$$);
    906 	}
    907 	| identifier_list
    908 	;
    909 
    910 identifier_list
    911 	: any_id
    912 	{
    913 	    new_ident_list(&$$);
    914 	    add_ident_list(&$$, &$$, $1.text);
    915 	}
    916 	| identifier_list ',' any_id
    917 	{
    918 	    add_ident_list(&$$, &$1, $3.text);
    919 	}
    920 	;
    921 
    922 identifier_or_ref
    923 	: any_id
    924 	{
    925 	    $$ = $1;
    926 	}
    927 	| '&' any_id
    928 	{
    929 #if OPT_LINTLIBRARY
    930 	    if (lintLibrary()) { /* Lint doesn't grok C++ ref variables */
    931 		$$ = $2;
    932 	    } else
    933 #endif
    934 		(void)sprintf($$.text, "&%s", $2.text);
    935 	    $$.begin = $1.begin;
    936 	}
    937 	;
    938 
    939 abs_declarator
    940 	: pointer
    941 	{
    942 	    $$ = new_declarator($1.text, "", $1.begin);
    943 	}
    944 	| pointer direct_abs_declarator
    945 	{
    946 	    $$ = $2;
    947 	    (void)sprintf(buf, "%s%s", $1.text, $$->text);
    948 	    free($$->text);
    949 	    $$->text = xstrdup(buf);
    950 	    $$->begin = $1.begin;
    951 	}
    952 	| direct_abs_declarator
    953 	;
    954 
    955 direct_abs_declarator
    956 	: '(' abs_declarator ')'
    957 	{
    958 	    $$ = $2;
    959 	    (void)sprintf(buf, "(%s)", $$->text);
    960 	    free($$->text);
    961 	    $$->text = xstrdup(buf);
    962 	    $$->begin = $1.begin;
    963 	}
    964 	| direct_abs_declarator T_BRACKETS
    965 	{
    966 	    $$ = $1;
    967 	    (void)sprintf(buf, "%s%s", $$->text, $2.text);
    968 	    free($$->text);
    969 	    $$->text = xstrdup(buf);
    970 	}
    971 	| T_BRACKETS
    972 	{
    973 	    $$ = new_declarator($1.text, "", $1.begin);
    974 	}
    975 	| direct_abs_declarator '(' parameter_type_list ')'
    976 	{
    977 	    $$ = new_declarator("%s()", "", $1->begin);
    978 	    $$->params = $3;
    979 	    $$->func_stack = $1;
    980 	    $$->head = ($1->func_stack == NULL) ? $$ : $1->head;
    981 	    $$->func_def = FUNC_ANSI;
    982 	}
    983 	| direct_abs_declarator '(' ')'
    984 	{
    985 	    $$ = new_declarator("%s()", "", $1->begin);
    986 	    $$->func_stack = $1;
    987 	    $$->head = ($1->func_stack == NULL) ? $$ : $1->head;
    988 	    $$->func_def = FUNC_ANSI;
    989 	}
    990 	| '(' parameter_type_list ')'
    991 	{
    992 	    Declarator *d;
    993 
    994 	    d = new_declarator("", "", $1.begin);
    995 	    $$ = new_declarator("%s()", "", $1.begin);
    996 	    $$->params = $2;
    997 	    $$->func_stack = d;
    998 	    $$->head = $$;
    999 	    $$->func_def = FUNC_ANSI;
   1000 	}
   1001 	| '(' ')'
   1002 	{
   1003 	    Declarator *d;
   1004 
   1005 	    d = new_declarator("", "", $1.begin);
   1006 	    $$ = new_declarator("%s()", "", $1.begin);
   1007 	    $$->func_stack = d;
   1008 	    $$->head = $$;
   1009 	    $$->func_def = FUNC_ANSI;
   1010 	}
   1011 	;
   1012 
   1013 %%
   1014 
   1015 /* lex.yy.c */
   1016 #define BEGIN yy_start = 1 + 2 *
   1017 
   1018 #define CPP1 1
   1019 #define INIT1 2
   1020 #define INIT2 3
   1021 #define CURLY 4
   1022 #define LEXYACC 5
   1023 #define ASM 6
   1024 #define CPP_INLINE 7
   1025 
   1026 extern char *yytext;
   1027 extern FILE *yyin, *yyout;
   1028 
   1029 static int curly;			/* number of curly brace nesting levels */
   1030 static int ly_count;			/* number of occurances of %% */
   1031 static int inc_depth;			/* include nesting level */
   1032 static SymbolTable *included_files;	/* files already included */
   1033 static int yy_start = 0;		/* start state number */
   1034 
   1035 #define grammar_error(s) yaccError(s)
   1036 
   1037 static void
   1038 yaccError (const char *msg)
   1039 {
   1040     func_params = NULL;
   1041     put_error();		/* tell what line we're on, and what file */
   1042     fprintf(stderr, "%s at token '%s'\n", msg, yytext);
   1043 }
   1044 
   1045 /* Initialize the table of type qualifier keywords recognized by the lexical
   1046  * analyzer.
   1047  */
   1048 void
   1049 init_parser (void)
   1050 {
   1051     static const char *keywords[] = {
   1052 	"const",
   1053 	"restrict",
   1054 	"volatile",
   1055 	"interrupt",
   1056 #ifdef vms
   1057 	"noshare",
   1058 	"readonly",
   1059 #endif
   1060 #if defined(MSDOS) || defined(OS2)
   1061 	"__cdecl",
   1062 	"__export",
   1063 	"__far",
   1064 	"__fastcall",
   1065 	"__fortran",
   1066 	"__huge",
   1067 	"__inline",
   1068 	"__interrupt",
   1069 	"__loadds",
   1070 	"__near",
   1071 	"__pascal",
   1072 	"__saveregs",
   1073 	"__segment",
   1074 	"__stdcall",
   1075 	"__syscall",
   1076 	"_cdecl",
   1077 	"_cs",
   1078 	"_ds",
   1079 	"_es",
   1080 	"_export",
   1081 	"_far",
   1082 	"_fastcall",
   1083 	"_fortran",
   1084 	"_huge",
   1085 	"_interrupt",
   1086 	"_loadds",
   1087 	"_near",
   1088 	"_pascal",
   1089 	"_saveregs",
   1090 	"_seg",
   1091 	"_segment",
   1092 	"_ss",
   1093 	"cdecl",
   1094 	"far",
   1095 	"huge",
   1096 	"near",
   1097 	"pascal",
   1098 #ifdef OS2
   1099 	"__far16",
   1100 #endif
   1101 #endif
   1102 #ifdef __GNUC__
   1103 	/* gcc aliases */
   1104 	"__builtin_va_arg",
   1105 	"__builtin_va_list",
   1106 	"__const",
   1107 	"__const__",
   1108 	"__inline",
   1109 	"__inline__",
   1110 	"__restrict",
   1111 	"__restrict__",
   1112 	"__volatile",
   1113 	"__volatile__",
   1114 #endif
   1115     };
   1116     unsigned i;
   1117 
   1118     /* Initialize type qualifier table. */
   1119     type_qualifiers = new_symbol_table();
   1120     for (i = 0; i < sizeof(keywords)/sizeof(keywords[0]); ++i) {
   1121 	new_symbol(type_qualifiers, keywords[i], NULL, DS_NONE);
   1122     }
   1123 }
   1124 
   1125 /* Process the C source file.  Write function prototypes to the standard
   1126  * output.  Convert function definitions and write the converted source
   1127  * code to a temporary file.
   1128  */
   1129 void
   1130 process_file (FILE *infile, char *name)
   1131 {
   1132     char *s;
   1133 
   1134     if (strlen(name) > 2) {
   1135 	s = name + strlen(name) - 2;
   1136 	if (*s == '.') {
   1137 	    ++s;
   1138 	    if (*s == 'l' || *s == 'y')
   1139 		BEGIN LEXYACC;
   1140 #if defined(MSDOS) || defined(OS2)
   1141 	    if (*s == 'L' || *s == 'Y')
   1142 		BEGIN LEXYACC;
   1143 #endif
   1144 	}
   1145     }
   1146 
   1147     included_files = new_symbol_table();
   1148     typedef_names = new_symbol_table();
   1149     define_names = new_symbol_table();
   1150     inc_depth = -1;
   1151     curly = 0;
   1152     ly_count = 0;
   1153     func_params = NULL;
   1154     yyin = infile;
   1155     include_file(strcpy(base_file, name), func_style != FUNC_NONE);
   1156     if (file_comments) {
   1157 #if OPT_LINTLIBRARY
   1158     	if (lintLibrary()) {
   1159 	    put_blankline(stdout);
   1160 	    begin_tracking();
   1161 	}
   1162 #endif
   1163 	put_string(stdout, "/* ");
   1164 	put_string(stdout, cur_file_name());
   1165 	put_string(stdout, " */\n");
   1166     }
   1167     yyparse();
   1168     free_symbol_table(define_names);
   1169     free_symbol_table(typedef_names);
   1170     free_symbol_table(included_files);
   1171 }
   1172 
   1173 #ifdef NO_LEAKS
   1174 void
   1175 free_parser(void)
   1176 {
   1177     free_symbol_table (type_qualifiers);
   1178 #ifdef FLEX_SCANNER
   1179     if (yy_current_buffer != 0)
   1180 	yy_delete_buffer(yy_current_buffer);
   1181 #endif
   1182 }
   1183 #endif
   1184