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