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 * 340 dft_decl_spec (void) 341 { 342 return (lintLibrary() && !return_val) ? "void" : "int"; 343 } 344 345 static int 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 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 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 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 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