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