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