1 /* $NetBSD: grammar.y,v 1.1.1.2 2010/12/23 23:36:28 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