grammar.y revision 234949
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)
16static 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
108typedef int PrototypeStyle;
109
110typedef char boolean;
111
112extern boolean types_out;
113extern 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
129typedef int FuncDefStyle;
130
131/* Source file text */
132typedef 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. */
148typedef 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. */
155typedef 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. */
164typedef 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. */
179typedef 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. */
187typedef 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" */
193typedef 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 */
201typedef 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
213typedef struct symbol_table {
214    Symbol *bucket[SYM_MAX_HASH];	/* hash buckets */
215} SymbolTable;
216
217extern SymbolTable *new_symbol_table	/* Create symbol table */
218	(void);
219extern void free_symbol_table		/* Destroy symbol table */
220	(SymbolTable *s);
221extern Symbol *find_symbol		/* Lookup symbol name */
222	(SymbolTable *s, const char *n);
223extern Symbol *new_symbol		/* Define new symbol */
224	(SymbolTable *s, const char *n, const char *v, int f);
225
226/* #include "semantic.h" */
227extern void new_decl_spec (DeclSpec *, const char *, long, int);
228extern void free_decl_spec (DeclSpec *);
229extern void join_decl_specs (DeclSpec *, DeclSpec *, DeclSpec *);
230extern void check_untagged (DeclSpec *);
231extern Declarator *new_declarator (const char *, const char *, long);
232extern void free_declarator (Declarator *);
233extern void new_decl_list (DeclaratorList *, Declarator *);
234extern void free_decl_list (DeclaratorList *);
235extern void add_decl_list (DeclaratorList *, DeclaratorList *, Declarator *);
236extern Parameter *new_parameter (DeclSpec *, Declarator *);
237extern void free_parameter (Parameter *);
238extern void new_param_list (ParameterList *, Parameter *);
239extern void free_param_list (ParameterList *);
240extern void add_param_list (ParameterList *, ParameterList *, Parameter *);
241extern void new_ident_list (ParameterList *);
242extern void add_ident_list (ParameterList *, ParameterList *, const char *);
243extern void set_param_types (ParameterList *, DeclSpec *, DeclaratorList *);
244extern void gen_declarations (DeclSpec *, DeclaratorList *);
245extern void gen_prototype (DeclSpec *, Declarator *);
246extern void gen_func_declarator (Declarator *);
247extern void gen_func_definition (DeclSpec *, Declarator *);
248
249extern void init_parser     (void);
250extern void process_file    (FILE *infile, char *name);
251extern char *cur_text       (void);
252extern char *cur_file_name  (void);
253extern char *implied_typedef (void);
254extern void include_file    (char *name, int convert);
255extern char *supply_parm    (int count);
256extern char *xstrdup        (const char *);
257extern int already_declared (char *name);
258extern int is_actual_func   (Declarator *d);
259extern int lint_ellipsis    (Parameter *p);
260extern int want_typedef     (void);
261extern void begin_tracking  (void);
262extern void begin_typedef   (void);
263extern void copy_typedef    (char *s);
264extern void ellipsis_varargs (Declarator *d);
265extern void end_typedef     (void);
266extern void flush_varargs   (void);
267extern void fmt_library     (int code);
268extern void imply_typedef   (const char *s);
269extern void indent          (FILE *outf);
270extern void put_blankline   (FILE *outf);
271extern void put_body        (FILE *outf, DeclSpec *decl_spec, Declarator *declarator);
272extern void put_char        (FILE *outf, int c);
273extern void put_error       (void);
274extern void put_newline     (FILE *outf);
275extern void put_padded      (FILE *outf, const char *s);
276extern void put_string      (FILE *outf, const char *s);
277extern void track_in        (void);
278
279extern boolean file_comments;
280extern FuncDefStyle func_style;
281extern char base_file[];
282
283extern	int	yylex (void);
284
285/* declaration specifier attributes for the typedef statement currently being
286 * scanned
287 */
288static int cur_decl_spec_flags;
289
290/* pointer to parameter list for the current function definition */
291static 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 */
300static Declarator *cur_declarator;
301
302/* temporary string buffer */
303static char buf[MAX_TEXT_SIZE];
304
305/* table of typedef names */
306static SymbolTable *typedef_names;
307
308/* table of define names */
309static SymbolTable *define_names;
310
311/* table of type qualifiers */
312static SymbolTable *type_qualifiers;
313
314/* information about the current input file */
315typedef 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
327static IncludeStack *cur_file;	/* current input file */
328
329/* #include "yyerror.c" */
330
331static int haveAnsiParam (void);
332
333
334/* Flags to enable us to find if a procedure returns a value.
335 */
336static int return_val;	/* nonzero on BRACES iff return-expression found */
337
338static const char *
339dft_decl_spec (void)
340{
341    return (lintLibrary() && !return_val) ? "void" : "int";
342}
343
344static int
345haveAnsiParam (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
360program
361	: /* empty */
362	| translation_unit
363	;
364
365translation_unit
366	: external_declaration
367	| translation_unit external_declaration
368	;
369
370external_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
386braces
387	: T_LBRACE T_MATCHRBRACE
388	;
389
390linkage_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
404declaration
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
441any_typedef
442	: T_EXTENSION T_TYPEDEF
443	{
444	    begin_typedef();
445	}
446	| T_TYPEDEF
447	{
448	    begin_typedef();
449	}
450	;
451
452opt_declarator_list
453	: /* empty */
454	| declarator_list
455	;
456
457declarator_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
481function_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
546opt_declaration_list
547	: /* empty */
548	| T_VA_DCL
549	| declaration_list
550	;
551
552declaration_list
553	: declaration
554	| declaration_list declaration
555	;
556
557decl_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
567decl_specifier
568	: storage_class
569	| type_specifier
570	| type_qualifier
571	;
572
573storage_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
600type_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
660type_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
677struct_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
699struct_or_union
700	: T_STRUCT
701	{
702	    imply_typedef($$.text);
703	}
704	| T_UNION
705	{
706	    imply_typedef($$.text);
707	}
708	;
709
710init_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
721init_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
742enum_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
764enumeration
765	: T_ENUM
766	{
767	    imply_typedef("enum");
768	    $$ = $1;
769	}
770	;
771
772any_id
773	: T_IDENTIFIER
774	| T_TYPEDEF_NAME
775	;
776
777declarator
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
790direct_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
828pointer
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
841opt_type_qualifiers
842	: /* empty */
843	{
844	    strcpy($$.text, "");
845	    $$.begin = 0L;
846	}
847	| type_qualifier_list
848	;
849
850type_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
865parameter_type_list
866	: parameter_list
867	| parameter_list ',' T_ELLIPSIS
868	{
869	    add_ident_list(&$$, &$1, "...");
870	}
871	;
872
873parameter_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
884parameter_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
902opt_identifier_list
903	: /* empty */
904	{
905	    new_ident_list(&$$);
906	}
907	| identifier_list
908	;
909
910identifier_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
922identifier_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
939abs_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
955direct_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
1026extern char *yytext;
1027extern FILE *yyin, *yyout;
1028
1029static int curly;			/* number of curly brace nesting levels */
1030static int ly_count;			/* number of occurances of %% */
1031static int inc_depth;			/* include nesting level */
1032static SymbolTable *included_files;	/* files already included */
1033static int yy_start = 0;		/* start state number */
1034
1035#define grammar_error(s) yaccError(s)
1036
1037static void
1038yaccError (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 */
1048void
1049init_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 */
1129void
1130process_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
1174void
1175free_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
1184