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