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