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