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