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