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