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