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