1 %{ 2 /* 3 * CDDL HEADER START 4 * 5 * The contents of this file are subject to the terms of the 6 * Common Development and Distribution License, Version 1.0 only 7 * (the "License"). You may not use this file except in compliance 8 * with the License. 9 * 10 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 11 * or http://www.opensolaris.org/os/licensing. 12 * See the License for the specific language governing permissions 13 * and limitations under the License. 14 * 15 * When distributing Covered Code, include this CDDL HEADER in each 16 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 17 * If applicable, add the following below this CDDL HEADER, with the 18 * fields enclosed by brackets "[]" replaced with your own identifying 19 * information: Portions Copyright [yyyy] [name of copyright owner] 20 * 21 * CDDL HEADER END 22 */ 23 24 /* 25 * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 26 * Use is subject to license terms. 27 */ 28 29 #pragma ident "%Z%%M% %I% %E% SMI" 30 31 #include "parseproto.h" 32 #include <assert.h> 33 34 static decl_spec_t *declspec_Construct(void); 35 static void declspec_Destroy(decl_spec_t *); 36 static decl_spec_t *declspec_Init(stt_t, char *); 37 static char *declspec_VerifySTT(stt_t, stt_t); 38 static decl_spec_t *declspec_AddSTT(decl_spec_t *, stt_t, const char **); 39 static decl_spec_t *declspec_AddDS(decl_spec_t *, 40 decl_spec_t *, const char **); 41 static stt_t declspec_GetSTT(decl_spec_t *); 42 static char *declspec_GetTag(decl_spec_t *); 43 static type_t *type_Construct(void); 44 static void type_Destroy(type_t *); 45 static type_t *type_SetPtr(type_t *, stt_t); 46 static type_t *type_SetFun(type_t *, decl_t *); 47 static type_t *type_AddTail(type_t *, type_t *); 48 static const char *type_Verify(type_t *); 49 50 static decl_t *decl_Construct(void); 51 static decl_t *decl_AddArg(decl_t *, decl_t *); 52 static int decl_IsVoid(decl_t *); 53 static int decl_IsVoidArray(decl_t *); 54 static const char *decl_VerifyArgs(decl_t *); 55 static decl_t *decl_AddDS(decl_t *, decl_spec_t *, const char **); 56 static decl_t *decl_AddTypeTail(decl_t *, type_t *); 57 static decl_t *decl_addptr(decl_t *, type_t *); 58 static decl_t *decl_addary(decl_t *, char *); 59 static decl_t *decl_addfun(decl_t *, decl_t *); 60 static decl_t *decl_addellipsis(decl_t *); 61 62 #if defined(DEBUG) 63 static void type_PrintType(type_t *, int); 64 static void decl_PrintDecl(decl_t *, int); 65 static void decl_PrintTraceInfo(decl_t *); 66 static char *de_const(char *); 67 #endif 68 69 70 71 static int yylex(void); 72 static void yyerror(const char *); 73 static int yyparse(void); 74 75 #if defined(MEM_DEBUG) 76 static int declspec_Construct_calls; 77 static int type_Construct_calls; 78 static int decl_Construct_calls; 79 #endif 80 81 #if defined(DEBUG) 82 static char *de_const(char *); 83 #endif 84 %} 85 86 %union { 87 char *s_val; 88 int i_val; 89 stt_t stt_val; 90 decl_spec_t *ds_val; 91 type_t *t_val; 92 decl_t *d_val; 93 } 94 95 %token <i_val> ELLIPSIS 96 97 %token <s_val> INTEGER 98 %token <s_val> IDENTIFIER 99 %token <s_val> TYPEDEF_NAME 100 %type <s_val> constant_expression 101 102 %token <stt_val> REGISTER 103 %token <stt_val> TYPEDEF EXTERN AUTO STATIC 104 %token <stt_val> VOID CHAR SHORT INT LONG 105 %token <stt_val> FLOAT DOUBLE SIGNED UNSIGNED 106 %token <stt_val> CONST VOLATILE RESTRICT RESTRICT_KYWD 107 %type <stt_val> struct_or_union 108 %type <ds_val> storage_class_specifier 109 %type <ds_val> type_qualifier 110 %type <ds_val> type_qualifier_list 111 112 %token <ds_val> STRUCT UNION 113 %token <ds_val> ENUM 114 %type <ds_val> declaration_specifiers 115 %type <ds_val> type_specifier 116 %type <ds_val> struct_or_union_specifier enum_specifier 117 %type <ds_val> typedef_name 118 119 %type <t_val> pointer 120 121 %type <d_val> declaration 122 %type <d_val> init_declarator_list init_declarator 123 %type <d_val> declarator 124 %type <d_val> direct_declarator 125 %type <d_val> parameter_type_list parameter_list 126 %type <d_val> parameter_declaration 127 %type <d_val> abstract_declarator 128 %type <d_val> direct_abstract_declarator 129 130 %start declaration 131 132 %% 133 134 /* 135 * The grammar is derived from ANSI/ISO 9899-1990. 136 */ 137 138 declaration 139 : declaration_specifiers init_declarator_list ';' 140 { 141 decl_t *dp; 142 143 protop = $$ = $2; 144 145 /* only one declaration allowed */ 146 assert(protop->d_next == NULL); 147 148 for (dp = $2; dp && (errstr == NULL); 149 dp = dp->d_next) { 150 const char *sp; 151 152 decl_AddDS(dp, $1, &errstr); 153 if (sp = decl_Verify(dp)) 154 errstr = sp; 155 } 156 declspec_Destroy($1); 157 } 158 | error ';' 159 { 160 protop = $$ = NULL; 161 errstr = "function prototype syntax error"; 162 } 163 /* 164 * XXX - Does not support a "stand-alone" declaration specifier. It is 165 * essentially a type declaration, for example: 166 * 167 * typedef enum { FALSE = 0, TRUE = 1 } boolean_t; 168 * or 169 * struct _name { char *first; char *last }; 170 */ 171 172 /* XXX | declaration_specifiers */ 173 ; 174 175 declaration_specifiers 176 : storage_class_specifier declaration_specifiers 177 { 178 char const *ep; 179 180 $$ = declspec_AddDS($2, $1, &ep); 181 declspec_Destroy($1); 182 183 if (errstr == NULL) 184 errstr = ep; 185 } 186 | storage_class_specifier 187 | type_specifier declaration_specifiers 188 { 189 const char *ep; 190 191 $$ = declspec_AddDS($2, $1, &ep); 192 declspec_Destroy($1); 193 194 if (errstr == NULL) 195 errstr = ep; 196 } 197 | type_specifier 198 | type_qualifier declaration_specifiers 199 { 200 const char *ep; 201 202 $$ = declspec_AddDS($2, $1, &ep); 203 declspec_Destroy($1); 204 205 if (errstr == NULL) 206 errstr = ep; 207 } 208 | type_qualifier 209 ; 210 211 storage_class_specifier 212 : REGISTER 213 { 214 $$ = declspec_Init(SCS_REGISTER, NULL); 215 } 216 /* 217 * XXX - Does not support any storage class specifier other than 218 * register, and then only for function arguments. 219 * 220 | TYPEDEF 221 { 222 $$ = declspec_Init(SCS_TYPEDEF, NULL); 223 } 224 | EXTERN 225 { 226 $$ = declspec_Init(SCS_EXTERN, NULL); 227 } 228 | STATIC 229 { 230 $$ = declspec_Init(SCS_STATIC, NULL); 231 } 232 | AUTO 233 { 234 $$ = declspec_Init(SCS_AUTO, NULL); 235 } 236 */ 237 ; 238 239 type_specifier 240 : VOID 241 { 242 $$ = declspec_Init(TS_VOID, NULL); 243 atIDENT = 1; 244 } 245 | CHAR 246 { 247 $$ = declspec_Init(TS_CHAR, NULL); 248 atIDENT = 1; 249 } 250 | SHORT 251 { 252 $$ = declspec_Init(TS_SHORT, NULL); 253 atIDENT = 1; 254 } 255 | INT 256 { 257 $$ = declspec_Init(TS_INT, NULL); 258 atIDENT = 1; 259 } 260 | LONG 261 { 262 $$ = declspec_Init(TS_LONG, NULL); 263 atIDENT = 1; 264 } 265 | FLOAT 266 { 267 $$ = declspec_Init(TS_FLOAT, NULL); 268 atIDENT = 1; 269 } 270 | DOUBLE 271 { 272 $$ = declspec_Init(TS_DOUBLE, NULL); 273 atIDENT = 1; 274 } 275 | SIGNED 276 { 277 $$ = declspec_Init(TS_SIGNED, NULL); 278 atIDENT = 1; 279 } 280 | UNSIGNED 281 { 282 $$ = declspec_Init(TS_UNSIGNED, NULL); 283 atIDENT = 1; 284 } 285 | struct_or_union_specifier 286 | enum_specifier 287 | typedef_name 288 ; 289 290 typedef_name 291 : TYPEDEF_NAME 292 { 293 $$ = declspec_Init(TS_TYPEDEF, $1); 294 atIDENT = 1; 295 free($1); 296 } 297 ; 298 299 /* 300 * The "restrict" keyword is new in the C99 standard. 301 * It is type qualifier like const and volatile. 302 * We are using "_RESTRICT_KYWD" in headers and source code so 303 * it is easily turned on and off by various macros at compile time. 304 * In order for the "restrict" keyword to be recognized you must 305 * be using a C99 compliant compiler in its native mode. 306 */ 307 type_qualifier 308 : CONST 309 { 310 $$ = declspec_Init(TQ_CONST, NULL); 311 } 312 | VOLATILE 313 { 314 $$ = declspec_Init(TQ_VOLATILE, NULL); 315 } 316 | RESTRICT 317 { 318 $$ = declspec_Init(TQ_RESTRICT, NULL); 319 } 320 | RESTRICT_KYWD 321 { 322 $$ = declspec_Init(TQ_RESTRICT_KYWD, NULL); 323 } 324 ; 325 326 struct_or_union_specifier 327 : struct_or_union { atIDENT = 1; } IDENTIFIER 328 { 329 $$ = declspec_Init($1, $3); 330 free($3); 331 } 332 /* 333 * XXX - struct or union definitions are not supported. It is generally 334 * not done within the context of a function declaration (prototype) or 335 * variable definition. 336 337 | struct_or_union IDENTIFIER '{' struct_declaration_list '}' 338 | struct_or_union '{' struct_declaration_list '}' 339 */ 340 ; 341 342 struct_or_union 343 : STRUCT 344 { 345 $$ = TS_STRUCT; 346 } 347 | UNION 348 { 349 $$ = TS_UNION; 350 } 351 ; 352 353 init_declarator_list 354 : init_declarator 355 { 356 $$ = $1; 357 atIDENT = 1; 358 } 359 /* 360 * XXX - Does not support a comma separated list of declarations or 361 * definitions. Function prototypes or variable definitions must be 362 * given as one per C statement. 363 364 | init_declarator_list ',' init_declarator 365 { 366 $$ = decl_AddArg($1, $3); 367 atIDENT = 1; 368 } 369 */ 370 ; 371 372 init_declarator 373 : declarator 374 /* 375 * XXX - Initialization is not supported. 376 377 | declarator '=' initializer 378 */ 379 ; 380 381 382 enum_specifier 383 : ENUM { atIDENT = 1; } IDENTIFIER 384 { 385 $$ = declspec_Init(TS_ENUM, $3); 386 free($3); 387 } 388 /* 389 * XXX - enumerator definition is not supported for the same reasons 390 * struct|union definition is not supported. 391 392 | ENUM IDENTIFIER '{' enumerator_list '}' 393 | ENUM '{' enumerator_list '}' 394 */ 395 ; 396 397 398 declarator 399 : pointer direct_declarator 400 { 401 $$ = decl_addptr($2, $1); 402 } 403 | direct_declarator 404 ; 405 406 direct_declarator 407 : IDENTIFIER 408 { 409 $$ = decl_SetName(decl_Construct(), $1); 410 atIDENT = 0; 411 free($1); 412 } 413 | '(' declarator ')' 414 { 415 $$ = $2; 416 } 417 | direct_declarator '[' constant_expression ']' 418 { 419 $$ = decl_addary($1, $3); 420 free($3); 421 } 422 | direct_declarator '[' ']' 423 { 424 $$ = decl_addary($1, NULL); 425 } 426 | direct_declarator '(' parameter_type_list ')' 427 { 428 $$ = decl_addfun($1, $3); 429 } 430 | direct_declarator '(' ')' 431 { 432 $$ = decl_addfun($1, NULL); 433 } 434 ; 435 436 pointer 437 : '*' type_qualifier_list 438 { 439 $$ = type_SetPtr(type_Construct(), ($2)->ds_stt); 440 declspec_Destroy($2); 441 } 442 | '*' 443 { 444 $$ = type_SetPtr(type_Construct(), TQ_NONE); 445 } 446 | '*' type_qualifier_list pointer 447 { 448 type_t *tp = type_Construct(); 449 450 type_SetPtr(tp, ($2)->ds_stt); 451 declspec_Destroy($2); 452 $$ = type_AddTail($3, tp); 453 } 454 | '*' pointer 455 { 456 type_t *tp = type_Construct(); 457 458 type_SetPtr(tp, TQ_NONE); 459 $$ = type_AddTail($2, tp); 460 } 461 ; 462 463 type_qualifier_list 464 : type_qualifier 465 | type_qualifier_list type_qualifier 466 { 467 const char *ep; 468 469 /* XXX - ignore any error */ 470 $$ = declspec_AddDS($1, $2, &ep); 471 declspec_Destroy($2); 472 } 473 ; 474 475 parameter_type_list 476 : parameter_list 477 | parameter_list ',' ELLIPSIS 478 { 479 $$ = decl_addellipsis($1); 480 } 481 ; 482 483 parameter_list 484 : parameter_declaration 485 { 486 const char *sp = type_Verify($1->d_type); 487 488 if (sp) 489 errstr = sp; 490 491 $$ = $1; 492 atIDENT = 0; 493 } 494 | parameter_list ',' parameter_declaration 495 { 496 const char *sp = type_Verify($3->d_type); 497 498 if (sp) 499 errstr = sp; 500 501 $$ = decl_AddArg($1, $3); 502 atIDENT = 0; 503 } 504 ; 505 506 parameter_declaration 507 : declaration_specifiers declarator 508 { 509 const char *ep; 510 511 $$ = decl_AddDS($2, $1, &ep); 512 declspec_Destroy($1); 513 514 if (errstr == NULL) 515 errstr = ep; 516 } 517 | declaration_specifiers abstract_declarator 518 { 519 const char *ep; 520 521 $$ = decl_AddDS($2, $1, &ep); 522 declspec_Destroy($1); 523 524 if (errstr == NULL) 525 errstr = ep; 526 } 527 | declaration_specifiers 528 { 529 const char *ep; 530 531 $$ = decl_AddDS(decl_Construct(), $1, &ep); 532 declspec_Destroy($1); 533 534 if (errstr == NULL) 535 errstr = ep; 536 } 537 ; 538 539 abstract_declarator 540 : pointer 541 { 542 $$ = decl_addptr(decl_Construct(), $1); 543 } 544 | pointer direct_abstract_declarator 545 { 546 $$ = decl_addptr($2, $1); 547 } 548 | direct_abstract_declarator 549 ; 550 551 direct_abstract_declarator 552 : '(' abstract_declarator ')' 553 { 554 $$ = $2; 555 } 556 | direct_abstract_declarator '[' constant_expression ']' 557 { 558 $$ = decl_addary($1, $3); 559 free($3); 560 } 561 | '[' constant_expression ']' 562 { 563 $$ = decl_addary(decl_Construct(), $2); 564 free($2); 565 } 566 | direct_abstract_declarator '[' ']' 567 { 568 $$ = decl_addary($1, NULL); 569 } 570 | '[' ']' 571 { 572 $$ = decl_addary(decl_Construct(), NULL); 573 } 574 | direct_abstract_declarator '(' parameter_type_list ')' 575 { 576 $$ = decl_addfun($1, $3); 577 } 578 | '(' parameter_type_list ')' 579 { 580 $$ = decl_addfun(decl_Construct(), $2); 581 } 582 | direct_abstract_declarator '(' ')' 583 { 584 $$ = decl_addfun($1, NULL); 585 } 586 | '(' ')' 587 { 588 $$ = decl_addfun(decl_Construct(), NULL); 589 } 590 ; 591 592 /* 593 * XXX - General case constant expressions are not supported. It would 594 * be easy to implement (for the most part), but there are no cases to 595 * date that require such a facility. The grammar does allow an 596 * identifier (or typedef name) to be used since the prototype is not 597 * processed by CPP. The only integer constant that is supported is 598 * decimal. 599 */ 600 601 constant_expression 602 : INTEGER 603 | IDENTIFIER 604 | TYPEDEF_NAME 605 ; 606 607 %% 608 609 /* Data Declarations */ 610 611 typedef struct { 612 char *name; 613 int token; 614 stt_t stt; 615 } keyword_t; 616 617 typedef struct { 618 stt_t s_stt; 619 char *s_str; 620 } sttpair_t; 621 622 /* External Declarations */ 623 624 static const keyword_t *lookup_keyword(const char *); 625 static const char *lookup_sttpair(stt_t); 626 static int getch(void); 627 static void ungetch(int); 628 static void skipwhitespace(void); 629 static int lookahead(int); 630 static void skipcomment(void); 631 632 /* External Definitions */ 633 634 static char *input = NULL; /* current place in the input stream */ 635 /* at point in stream were identifier is expected */ 636 static int atIDENT = 0; 637 static decl_t *protop = NULL; /* pointer to prototype */ 638 static const char *errstr = NULL; /* error message */ 639 640 /* 641 * lookup_keyword - Given a string, return the keyword_t or NULL. 642 */ 643 644 static const keyword_t * 645 lookup_keyword(const char *name) { 646 static const keyword_t keytbl[] = { 647 { "register", REGISTER, SCS_REGISTER }, 648 #if UNSUPPORTED 649 { "typedef", TYPEDEF, SCS_TYPEDEF }, 650 { "auto", AUTO, SCS_AUTO }, 651 { "static", STATIC, SCS_STATIC }, 652 { "extern", EXTERN, SCS_EXTERN }, 653 #endif /* UNSUPPORTED */ 654 { "void", VOID, TS_VOID }, 655 { "char", CHAR, TS_CHAR }, 656 { "short", SHORT, TS_SHORT }, 657 { "int", INT, TS_INT }, 658 { "long", LONG, TS_LONG }, 659 { "float", FLOAT, TS_FLOAT }, 660 { "double", DOUBLE, TS_DOUBLE }, 661 { "signed", SIGNED, TS_SIGNED }, 662 { "unsigned", UNSIGNED, TS_UNSIGNED }, 663 { "struct", STRUCT, TS_STRUCT }, 664 { "union", UNION, TS_UNION }, 665 { "enum", ENUM, TS_ENUM }, 666 667 { "const", CONST, TQ_CONST }, 668 { "volatile", VOLATILE, TQ_VOLATILE }, 669 { "restrict", RESTRICT, TQ_RESTRICT }, 670 { "_RESTRICT_KYWD",RESTRICT_KYWD, TQ_RESTRICT_KYWD}, 671 }; 672 #define NKEYWORD (sizeof (keytbl)/sizeof (keyword_t)) 673 674 int i; 675 676 for (i = 0; i < NKEYWORD; ++i) { 677 char *s = keytbl[i].name; 678 679 if ((*s == *name) && (strcmp(s, name) == 0)) 680 return (&keytbl[i]); 681 } 682 683 return (NULL); 684 } 685 686 /* 687 * lookup_sttpair - Given an stt_t return a string or NULL. 688 * 689 */ 690 691 static const char * 692 lookup_sttpair(stt_t s) { 693 /* valid type specifier combinations */ 694 static const sttpair_t stttbl[] = { 695 { TS_VOID, "void" }, 696 { TS_CHAR, "char" }, 697 { TS_SIGNED | TS_CHAR, "signed char" }, 698 { TS_UNSIGNED | TS_CHAR, "unsigned char" }, 699 { TS_SHORT, "short" }, 700 { TS_SIGNED | TS_SHORT, "signed short" }, 701 { TS_SHORT | TS_INT, "short int" }, 702 { TS_SIGNED | TS_SHORT | TS_INT, 703 "signed short int" }, 704 { TS_UNSIGNED | TS_SHORT, 705 "unsigned short" }, 706 { TS_UNSIGNED | TS_SHORT | TS_INT, 707 "unsigned short int" }, 708 { TS_INT, "int" }, 709 { TS_SIGNED, "signed" }, 710 { TS_SIGNED | TS_INT, "signed int" }, 711 { TS_NO_TS, "" }, 712 { TS_UNSIGNED, "unsigned" }, 713 { TS_UNSIGNED | TS_INT, "unsigned int" }, 714 { TS_LONG, "long" }, 715 { TS_SIGNED | TS_LONG, "signed long" }, 716 { TS_LONG | TS_INT, "long int" }, 717 { TS_SIGNED | TS_LONG | TS_INT, 718 "signed long int" }, 719 { TS_UNSIGNED | TS_LONG, "unsigned long" }, 720 { TS_UNSIGNED | TS_LONG | TS_INT, 721 "unsigned long int" }, 722 { TS_FLOAT, "float" }, 723 { TS_DOUBLE, "double" }, 724 { TS_LONG | TS_DOUBLE, "long double" }, 725 { TS_STRUCT, "struct" }, 726 { TS_UNION, "union" }, 727 { TS_ENUM, "enum" }, 728 { TS_TYPEDEF, "" }, 729 /* non-ANSI type: long long */ 730 { TS_LONGLONG, "long long" }, 731 { TS_LONGLONG | TS_INT, "long long int" }, 732 { TS_SIGNED | TS_LONGLONG, 733 "signed long long" }, 734 { TS_UNSIGNED | TS_LONGLONG, 735 "unsigned long long" }, 736 { TS_SIGNED | TS_LONGLONG | TS_INT, 737 "signed long long int" }, 738 { TS_UNSIGNED | TS_LONGLONG | TS_INT, 739 "unsigned long long int" }, 740 }; 741 742 #define NDECLSPEC (sizeof (stttbl)/sizeof (sttpair_t)) 743 744 int i; 745 746 for (i = 0; i < NDECLSPEC; ++i) 747 if (s == stttbl[i].s_stt) 748 return (stttbl[i].s_str); 749 750 return (NULL); 751 } 752 753 /* 754 * yylex - return next token from the the input stream. 755 * 756 * The lexical analyzer does not recognize all possible C lexical 757 * elements. It only recognizes those associated with function 758 * declarations (read: prototypes) and data definitions. 759 */ 760 761 static int 762 yylex(void) { 763 char buf[BUFSIZ]; /* string version of token */ 764 int c; 765 int i = 0; 766 767 restart: 768 skipwhitespace(); 769 770 switch (c = getch()) { 771 case '/': 772 if (lookahead('*')) { 773 skipcomment(); 774 goto restart; 775 } 776 777 case '.': 778 if (lookahead('.')) { 779 if (lookahead('.')) 780 return (ELLIPSIS); 781 } 782 783 case EOF: 784 case '(': 785 case ')': 786 case ',': 787 case '[': 788 case ']': 789 case ';': 790 case '*': 791 return (c); 792 793 default: 794 if ((c == '_') || isalpha(c)) { 795 const keyword_t *kp; 796 797 do { 798 buf[i++] = c; 799 c = getch(); 800 } while ((c == '_') || isalnum(c)); 801 802 ungetch(c); 803 804 buf[i] = '\0'; 805 806 if ((kp = lookup_keyword(buf)) != NULL) { 807 yylval.stt_val = kp->stt; 808 return (kp->token); 809 } else { 810 yylval.s_val = strdup(buf); 811 812 return ((atIDENT) ? IDENTIFIER : TYPEDEF_NAME); 813 } 814 } else if (isdigit(c)) { 815 do { 816 buf[i++] = c; 817 } while (isdigit(c = getch())); 818 819 ungetch(c); 820 821 buf[i] = '\0'; 822 yylval.s_val = strdup(buf); 823 824 return (INTEGER); 825 } else 826 return (c); 827 } 828 /* NOTREACHED */ 829 } 830 831 /* getch - return the next character from the input stream. */ 832 833 static int 834 getch(void) { 835 int c; 836 837 if ((c = *input) == '\0') 838 c = EOF; 839 else /* only advance on non-NULL */ 840 input++; 841 842 return (c); 843 } 844 845 /* ungetch - return a character to the input stream. */ 846 847 static void 848 ungetch(int c) { 849 *(--input) = c; 850 } 851 852 /* skipwhitespace - skip over whitespace in the input stream. */ 853 854 static void 855 skipwhitespace(void) { 856 int c; 857 858 while (isspace(c = getch())) 859 ; 860 861 ungetch(c); 862 } 863 864 /* skipcomment - scan ahead to the next end of comment. */ 865 866 static void 867 skipcomment(void) { 868 loop { 869 int c; 870 871 switch (c = getch()) { 872 case EOF: 873 return; 874 875 case '*': 876 if (lookahead('/')) 877 return; 878 } 879 } 880 /* NOTREACHED */ 881 } 882 883 /* lookahead - does next character match 'c'? */ 884 885 static int 886 lookahead(int c) { 887 int ch = getch(); 888 int match; 889 890 if (!(match = (ch == c))) 891 ungetch(ch); 892 893 return (match); 894 } 895 896 /* putNtabs - write N '\t' to standard output. */ 897 898 #if defined(DEBUG) 899 900 static void 901 putNTabs(int n) { 902 int i; 903 904 for (i = 0; i < n; ++i) 905 putchar('\t'); 906 } 907 #endif /* DEBUG */ 908 909 /* D E C L A R A T I O N S P E C I F I E R S */ 910 911 /* 912 * Declaration specifiers encode storage class, type specifier and type 913 * qualifier information. This includes any identifiers associated with 914 * struct, union or enum declarations. Typedef names are also encoded 915 * in declaration specifiers. 916 */ 917 918 /* declspec_Construct - allocate and initialize a declspec_t. */ 919 920 static decl_spec_t * 921 declspec_Construct(void) { 922 decl_spec_t *dsp = malloc(sizeof (decl_spec_t)); 923 924 assert(dsp != NULL); 925 dsp->ds_stt = SCS_NONE | TS_NO_TS | TQ_NONE; 926 dsp->ds_id = NULL; 927 #if defined(MEM_DEBUG) 928 ++declspec_Construct_calls; 929 #endif 930 return (dsp); 931 } 932 933 /* declspec_Destroy - free a declspec_t. */ 934 935 static void 936 declspec_Destroy(decl_spec_t *dsp) { 937 free(dsp->ds_id); 938 free(dsp); 939 #if defined(MEM_DEBUG) 940 --declspec_Construct_calls; 941 #endif 942 } 943 944 /* 945 * declspec_Init - allocate and initialize a declspec_t given an 946 * stt_t and identifier. 947 * 948 * Note: 949 * 1) identifier can be NULL. 950 * 2) errors resulting in the stt_t and identifier are ignored. 951 */ 952 953 static decl_spec_t * 954 declspec_Init(stt_t s, char *tagp) { 955 const char *p; 956 decl_spec_t *dsp = declspec_Construct(); 957 decl_spec_t tmp; 958 959 tmp.ds_stt = s; 960 tmp.ds_id = tagp; 961 962 declspec_AddDS(dsp, &tmp, &p); /* XXX ignore any error */ 963 964 return (dsp); 965 } 966 967 /* 968 * declspec_VerifySTT - verify that the two given stt_t can be combined. 969 * 970 * Note: 971 * 1) The return value is a const char *, non-NULL to indicate an error. 972 */ 973 974 static char * 975 declspec_VerifySTT(stt_t s1, stt_t s2) { 976 stt_t result; 977 978 if ((s1 | s2) != (s1 ^ s2)) 979 return ("attempt to add declaration specifier " 980 "that is already present"); 981 982 result = (s1 | s2) & TS_MASK; 983 984 if (lookup_sttpair(result) == NULL) { 985 if (STT_isbasic(result) && STT_isderived(result)) 986 return ("attempt to combine basic and " 987 "derived types"); 988 989 if (STT_isvoid(result) && 990 (STT_isbasic(result) || STT_isderived(result))) 991 return ("attempt to combine void with " 992 "other type specifiers"); 993 994 if (STT_isfloat(result) && STT_isint(result)) 995 return ("attempt to combine floating and " 996 "integer type specifiers"); 997 998 if (STT_ischar(result) && STT_isint(result)) 999 return ("attempt to combine character and " 1000 "integer type specifiers"); 1001 1002 if (STT_has_explicit_sign(result) && 1003 (STT_isfloat(result) || STT_isderived(result))) 1004 return ("attempt to combine signed or " 1005 "unsigned with float or derived type"); 1006 1007 return ("invalid declaration specifier"); 1008 } 1009 1010 return (NULL); 1011 } 1012 1013 /* 1014 * declspec_AddSTT - add an stt_t to a decl_spec_t. 1015 * 1016 * Note: 1017 * 1) The "long long" type is handled here. 1018 * If both stt_t include TS_LONG then this is an attempt to use 1019 * "long long". The TS_LONG is cleared from the s1 and s2 and 1020 * then TS_LONGLONG is added to s2. The resulting s1 and s2 are 1021 * passed to declspec_VerifySTT to determine if the result is valid. 1022 * 1023 * 2) This method of handling "long long" does detect the case of 1024 * "long double long" and all it's variant forms. 1025 */ 1026 1027 static decl_spec_t * 1028 declspec_AddSTT(decl_spec_t *dsp, stt_t s2, const char **err) { 1029 stt_t s1 = dsp->ds_stt; 1030 1031 /* non-ANSI type: long long */ 1032 if ((s1 & TS_LONG) && (s2 & TS_LONG)) { 1033 s1 &= ~(TS_LONG); 1034 dsp->ds_stt = s1; 1035 s2 &= ~(TS_LONG); 1036 s2 |= TS_LONGLONG; 1037 } 1038 1039 if ((*err = declspec_VerifySTT(s1, s2)) == NULL) 1040 dsp->ds_stt |= s2; 1041 1042 return (dsp); 1043 } 1044 1045 /* 1046 * declpec_AddDS - add a decl_spec_t to an existing decl_spec_t. 1047 */ 1048 1049 static decl_spec_t * 1050 declspec_AddDS(decl_spec_t *dsp, decl_spec_t *tsp, const char **err) { 1051 declspec_AddSTT(dsp, tsp->ds_stt, err); 1052 1053 if ((*err == NULL) && tsp->ds_id) { 1054 free(dsp->ds_id); 1055 dsp->ds_id = strdup(tsp->ds_id); 1056 1057 assert(dsp->ds_id != NULL); 1058 } 1059 1060 return (dsp); 1061 } 1062 1063 /* 1064 * declspec_GetSTT - return the stt_t within a decl_spec_t. 1065 */ 1066 1067 static stt_t 1068 declspec_GetSTT(decl_spec_t *dsp) { 1069 return (dsp->ds_stt); 1070 } 1071 1072 /* 1073 * declspec_GetTag - return the identifier within a decl_spec_t. 1074 */ 1075 1076 static char * 1077 declspec_GetTag(decl_spec_t *dsp) { 1078 return (dsp->ds_id); 1079 } 1080 1081 /* 1082 * declspec_ToString - convert a decl_spec_t into a string. 1083 * 1084 * Note: 1085 * 1) The form of the resulting string is always the same, i.e. 1086 * 1087 * [register] [type_specifier] [const] [volatile] 1088 * 1089 * dsp must be correct 1090 * 1091 */ 1092 1093 char * 1094 declspec_ToString(char *bufp, decl_spec_t *dsp) { 1095 const char *s; 1096 int something = 0; 1097 1098 *bufp = '\0'; 1099 1100 /* storage class specifier */ 1101 switch (dsp->ds_stt & SCS_MASK) { 1102 case SCS_REGISTER: 1103 strcat(bufp, "register"); 1104 something = 1; 1105 break; 1106 } 1107 1108 s = lookup_sttpair(dsp->ds_stt & TS_MASK); 1109 1110 /* type specifier */ 1111 switch (dsp->ds_stt & TS_MASK) { 1112 case TS_STRUCT: 1113 case TS_UNION: 1114 case TS_ENUM: 1115 if (something) 1116 strcat(bufp, " "); 1117 1118 strcat(bufp, s); 1119 strcat(bufp, " "); 1120 strcat(bufp, dsp->ds_id); 1121 break; 1122 1123 case TS_TYPEDEF: 1124 if (something) 1125 strcat(bufp, " "); 1126 1127 strcat(bufp, dsp->ds_id); 1128 break; 1129 1130 default: 1131 if (something) 1132 strcat(bufp, " "); 1133 1134 strcat(bufp, s); 1135 break; 1136 } 1137 1138 if (s) 1139 something = 1; 1140 1141 if (something && (dsp->ds_stt & TQ_MASK)) 1142 strcat(bufp, " "); 1143 1144 if (dsp->ds_stt & TQ_CONST) /* type qualifier */ 1145 strcat(bufp, "const"); 1146 1147 if (dsp->ds_stt & TQ_VOLATILE) { 1148 if (dsp->ds_stt & TQ_CONST) 1149 strcat(bufp, " "); 1150 1151 strcat(bufp, "volatile"); 1152 } 1153 1154 /* 1155 * It currently acknowledges and ignores restrict or _RESTRICT_KYWD 1156 * in code generation because of the uncertain behavior of "restrict". 1157 */ 1158 if (dsp->ds_stt & TQ_RESTRICT) 1159 strcat(bufp, ""); 1160 1161 if (dsp->ds_stt & TQ_RESTRICT_KYWD) 1162 strcat(bufp, ""); 1163 1164 return (bufp); 1165 } 1166 1167 /* T Y P E M O D I F I E R S */ 1168 1169 /* 1170 * Type modifiers encode the "array of...", "pointer to ..." and 1171 * "function returning ..." aspects of C types. The modifiers are kept 1172 * as a linked list in precedence order. The grammar encodes the 1173 * precedence order described by the standard. 1174 * 1175 * Type modifiers are always added at the end of list and the list is 1176 * always traversed from head to tail. 1177 */ 1178 1179 /* type_Construct - allocate and initialize a type_t. */ 1180 1181 static type_t * 1182 type_Construct(void) { 1183 type_t *tp = malloc(sizeof (type_t)); 1184 1185 assert(tp != NULL); 1186 1187 tp->t_next = NULL; /* generic */ 1188 tp->t_dt = DD_NONE; 1189 1190 tp->t_nargs = 0; /* DD_FUN */ 1191 tp->t_ellipsis = 0; 1192 tp->t_args = NULL; 1193 /* DD_PTR */ 1194 tp->t_stt = (SCS_NONE | TS_NO_TS | TQ_NONE); 1195 1196 tp->t_sizestr = NULL; /* DD_ARY */ 1197 #if defined(MEM_DEBUG) 1198 ++type_Construct_calls; 1199 #endif 1200 return (tp); 1201 } 1202 1203 /* type_Destroy - free a type_t list. */ 1204 1205 static void 1206 type_Destroy(type_t *tp) { 1207 while (tp) { 1208 type_t *nextp = tp->t_next; 1209 1210 switch (tp->t_dt) { 1211 case DD_FUN: 1212 decl_Destroy(tp->t_args); 1213 break; 1214 1215 case DD_PTR: 1216 break; 1217 1218 case DD_ARY: 1219 free(tp->t_sizestr); 1220 break; 1221 } 1222 1223 free(tp); 1224 1225 tp = nextp; 1226 #if defined(MEM_DEBUG) 1227 --type_Construct_calls; 1228 #endif 1229 } 1230 } 1231 1232 /* 1233 * type_SetPtr - make a type_t into a "pointer to ..." variant. 1234 * 1235 * Note: 1236 * 1) The stt_t will encode any type qualifiers (const, volatile). 1237 */ 1238 1239 static type_t * 1240 type_SetPtr(type_t *tp, stt_t s) { 1241 assert(tp->t_dt == DD_NONE); 1242 1243 tp->t_dt = DD_PTR; 1244 tp->t_stt = s & TQ_MASK; 1245 1246 return (tp); 1247 } 1248 1249 /* 1250 * type_SetAry - make a type_t into an "array of ...", variant. 1251 * 1252 * Note: 1253 * 1) The array dimension can be NULL to indicate undefined, i.e. []. 1254 */ 1255 1256 static type_t * 1257 type_SetAry(type_t *tp, char *dim) { 1258 assert(tp->t_dt == DD_NONE); 1259 assert(tp->t_sizestr == NULL); 1260 1261 tp->t_dt = DD_ARY; 1262 1263 if (dim) { 1264 tp->t_sizestr = strdup(dim); 1265 assert(tp->t_sizestr != NULL); 1266 } else 1267 tp->t_sizestr = NULL; 1268 1269 return (tp); 1270 } 1271 1272 /* 1273 * type_SetFun - make a type_t into a "function returning ..." variant. 1274 * 1275 * Note: 1276 * 1) The argument list can be NULL to indicate undefined, i.e. (). 1277 */ 1278 1279 static type_t * 1280 type_SetFun(type_t *tp, decl_t *arglist) { 1281 assert(tp->t_dt == DD_NONE); 1282 1283 tp->t_dt = DD_FUN; 1284 1285 if (arglist) { 1286 tp->t_nargs = decl_GetArgLength(arglist); 1287 tp->t_args = arglist; 1288 tp->t_ellipsis = arglist->d_ellipsis; 1289 } 1290 1291 return (tp); 1292 } 1293 1294 /* 1295 * type_AddTail - add a type_t to the end of an existing type_t list. 1296 * 1297 * Note: 1298 * 1) The type_t *tp is added to the end of the type_t *dp list. 1299 */ 1300 1301 static type_t * 1302 type_AddTail(type_t *dp, type_t *tp) { 1303 type_t *lastp = dp; 1304 type_t *p; 1305 1306 while (p = lastp->t_next) 1307 lastp = p; 1308 1309 lastp->t_next = tp; 1310 1311 return (dp); 1312 } 1313 1314 #if defined(DEBUG) 1315 1316 /* type_PrintType - print a type_t list onto standard output. */ 1317 1318 static void 1319 type_PrintType(type_t *tp, int lvl) { 1320 decl_spec_t tmp; 1321 char buf[BUFSIZ]; 1322 1323 while (tp) { 1324 putNTabs(lvl); 1325 1326 switch (tp->t_dt) { 1327 case DD_PTR: 1328 tmp.ds_stt = tp->t_stt; 1329 tmp.ds_id = NULL; 1330 1331 printf("[%s] ptr to\n", declspec_ToString(buf, &tmp)); 1332 break; 1333 1334 case DD_FUN: 1335 printf("fun [%d%c] %s\n", 1336 tp->t_nargs, 1337 (tp->t_ellipsis)? '+' : '=', 1338 (tp->t_args)? "with arguments" : 1339 "undefined arguments"); 1340 1341 if (tp->t_args) { 1342 decl_PrintDecl(tp->t_args, lvl + 1); 1343 1344 if (tp->t_ellipsis) { 1345 putNTabs(lvl + 1); 1346 printf("...\n"); 1347 } 1348 } 1349 break; 1350 1351 case DD_ARY: 1352 printf("ary [%s] of\n", 1353 (tp->t_sizestr)? tp->t_sizestr : ""); 1354 break; 1355 } 1356 1357 tp = tp->t_next; 1358 } 1359 } 1360 #endif /* DEBUG */ 1361 1362 /* 1363 * type_Verify - verify a type_t list for semantic correctness. 1364 * 1365 * Note: 1366 * 1) C supports most combinations of type modifiers. 1367 * It does not support three combinations, they are: 1368 * 1369 * function returning array 1370 * array of functions 1371 * function returning function 1372 * 1373 * 2) The enum values associated with type modifiers (i.e. DD_*) 1374 * cannot be modified without changing the table included within the 1375 * function. 1376 * 1377 * 3) The function returns NULL to indicate that the type modifier 1378 * list is valid and non-NULL to indicate an error. 1379 * 1380 * 4) A type_t of NULL is permitted to indicate an empty type_t list. 1381 */ 1382 1383 static const char * 1384 type_Verify(type_t *tp) { 1385 static const char *dttbl[4][4] = { 1386 /* NONE ARY FUN PTR */ 1387 /* NONE */ {NULL, NULL, NULL, NULL}, 1388 /* ARY */ {NULL, NULL, "array of functions", NULL}, 1389 /* FUN */ {NULL, "function returning array", 1390 "function returning function", NULL}, 1391 /* PTR */ {NULL, NULL, NULL, NULL}, 1392 }; 1393 1394 if (tp) { 1395 type_t *nextp; 1396 1397 do { 1398 const char *p; 1399 decl_type_t nt; 1400 1401 nt = (nextp = tp->t_next)? nextp->t_dt : DD_NONE; 1402 1403 if ((p = dttbl[tp->t_dt][nt]) != NULL) 1404 return (p); 1405 1406 } while (tp = nextp); 1407 } 1408 1409 return (NULL); 1410 } 1411 1412 /* type_GetNext - return the next type_t in the list. */ 1413 1414 type_t * 1415 type_GetNext(type_t *tp) { 1416 return (tp->t_next); 1417 } 1418 1419 /* 1420 * The following group of functions return and or 1421 * test various aspects of type modifiers. 1422 * 1423 * 1) The three functions: type_IsPtrTo, type_IsFunction and 1424 * type_IsArray will accept an argument of NULL. 1425 * 1426 * 2) All other functions require one of the above three to be true. 1427 * Various asserts are in place to verify correct usage. 1428 */ 1429 1430 int 1431 type_IsArray(type_t *tp) { 1432 return (tp && (tp->t_dt == DD_ARY)); 1433 } 1434 1435 char * 1436 type_GetArraySize(type_t *tp) { 1437 assert(tp->t_dt == DD_ARY); 1438 1439 return (tp->t_sizestr); 1440 } 1441 1442 int 1443 type_IsPtrTo(type_t *tp) { 1444 return (tp && (tp->t_dt == DD_PTR)); 1445 } 1446 1447 stt_t 1448 type_GetPtrToTypeQual(type_t *tp) { 1449 assert(tp->t_dt == DD_PTR); 1450 1451 return (tp->t_stt); 1452 } 1453 1454 int 1455 type_IsFunction(type_t *tp) { 1456 return (tp && (tp->t_dt == DD_FUN)); 1457 } 1458 1459 int 1460 type_GetArgLength(type_t *tp) { 1461 assert(tp->t_dt == DD_FUN); 1462 1463 return (tp->t_nargs); 1464 } 1465 1466 int 1467 type_IsVarargs(type_t *tp) { 1468 while (tp && tp->t_dt == DD_PTR) 1469 tp = tp->t_next; 1470 1471 assert(tp->t_dt == DD_FUN); 1472 1473 return (tp->t_ellipsis); 1474 } 1475 1476 decl_t * 1477 type_GetArg(type_t *tp) { 1478 assert(tp->t_dt == DD_FUN); 1479 1480 return (tp->t_args); 1481 } 1482 1483 /* 1484 * type_IsPtrFun - determine if the type_t results in a call-able function. 1485 * 1486 * Note: 1487 * 1) The argument can be NULL. 1488 * 1489 * 2) The test is true if the type_t list is number of DD_PTR followed 1490 * by a DD_FUN. 1491 */ 1492 1493 int 1494 type_IsPtrFun(type_t *tp) { 1495 1496 if (! (tp && (tp->t_dt == DD_PTR))) 1497 return (0); 1498 1499 tp = tp->t_next; 1500 1501 while (tp && (tp->t_dt == DD_PTR)) 1502 tp = tp->t_next; 1503 1504 return (tp && (tp->t_dt == DD_FUN)); 1505 } 1506 1507 /* D E C L A R A T O R */ 1508 1509 /* 1510 * A decl_t encodes the name, 1511 * declaration specifiers and type modifiers of an object. 1512 */ 1513 1514 /* decl_Construct - allocate a decl_t. */ 1515 1516 static decl_t * 1517 decl_Construct(void) { 1518 decl_t *dp = malloc(sizeof (decl_t)); 1519 1520 assert(dp != NULL); 1521 1522 dp->d_name = NULL; 1523 dp->d_type = NULL; 1524 dp->d_next = NULL; 1525 dp->d_ds = declspec_Construct(); 1526 dp->d_ellipsis = 0; 1527 #if defined(MEM_DEBUG) 1528 ++decl_Construct_calls; 1529 #endif 1530 return (dp); 1531 } 1532 1533 /* decl_Destroy - free a decl_t list. */ 1534 1535 void 1536 decl_Destroy(decl_t *dp) { 1537 while (dp) { 1538 decl_t *nextp = dp->d_next; 1539 1540 type_Destroy(dp->d_type); 1541 declspec_Destroy(dp->d_ds); 1542 free(dp->d_name); 1543 free(dp); 1544 1545 dp = nextp; 1546 #if defined(MEM_DEBUG) 1547 --decl_Construct_calls; 1548 #endif 1549 } 1550 } 1551 1552 /* 1553 * decl_GetArgLength - return the length of a decl_t list. 1554 * 1555 * Note: 1556 * 1) The argument may be NULL to indicate an empty list, len == 0. 1557 */ 1558 1559 int 1560 decl_GetArgLength(decl_t *dp) { 1561 int len; 1562 1563 for (len = 0; dp; dp = dp->d_next) 1564 ++len; 1565 1566 return (len); 1567 } 1568 1569 /* 1570 * The following group of functions get or test various aspects of a decl_t. 1571 */ 1572 1573 decl_t * 1574 decl_GetNext(decl_t *dp) { 1575 return (dp->d_next); 1576 } 1577 1578 stt_t 1579 decl_GetDeclSpec(decl_t *dp) { 1580 return (declspec_GetSTT(dp->d_ds)); 1581 } 1582 1583 char * 1584 decl_GetDSName(decl_t *dp) { 1585 return (declspec_GetTag(dp->d_ds)); 1586 } 1587 1588 type_t * 1589 decl_GetType(decl_t *dp) { 1590 return (dp->d_type); 1591 } 1592 1593 int 1594 decl_IsVarargs(decl_t *dp) { 1595 return (dp->d_ellipsis); 1596 } 1597 1598 int 1599 decl_IsFunction(decl_t *dp) { 1600 return (type_IsFunction(dp->d_type)); 1601 } 1602 1603 char * 1604 decl_GetName(decl_t *dp) { 1605 return (dp->d_name); 1606 } 1607 1608 /* 1609 * decl_AddArg - add a decl_t to the end of an decl_t list. 1610 */ 1611 1612 static decl_t * 1613 decl_AddArg(decl_t *dp, decl_t *tp) { 1614 decl_t *lastp = dp; 1615 decl_t *p; 1616 1617 while (p = lastp->d_next) 1618 lastp = p; 1619 1620 lastp->d_next = tp; 1621 1622 return (dp); 1623 } 1624 1625 /* 1626 * decl_IsVoid - return true if the decl_t is a "pure" void declaration. 1627 */ 1628 1629 static int 1630 decl_IsVoid(decl_t *dp) { 1631 return ((declspec_GetSTT(dp->d_ds) & TS_VOID) && (dp->d_type == NULL)); 1632 } 1633 1634 /* 1635 * decl_IsVoidArray - return true if the decl_t includes "void []". 1636 */ 1637 1638 static int 1639 decl_IsVoidArray(decl_t *dp) { 1640 int retval = 0; 1641 type_t *tp = dp->d_type; 1642 1643 if (tp) { 1644 type_t *np; 1645 1646 while (np = type_GetNext(tp)) 1647 tp = np; 1648 1649 retval = type_IsArray(tp) && 1650 (declspec_GetSTT(dp->d_ds) & TS_VOID); 1651 } 1652 1653 return (retval); 1654 } 1655 1656 /* 1657 * decl_Verify - verify a decl_t. 1658 */ 1659 1660 static const char * 1661 decl_Verify(decl_t *dp) { 1662 const char *ep = NULL; 1663 1664 if (decl_IsVoid(dp)) 1665 ep = "type is void"; 1666 else if (decl_IsVoidArray(dp)) 1667 ep = "type is void []"; 1668 else 1669 ep = type_Verify(dp->d_type); 1670 1671 return (ep); 1672 } 1673 1674 /* 1675 * decl_VerifyArgs - verify a decl_t list. 1676 */ 1677 1678 static const char * 1679 decl_VerifyArgs(decl_t *dp) { 1680 decl_t *tp = dp; 1681 const char *ep = NULL; 1682 1683 if (dp) { 1684 int nv = 0; 1685 int nargs = decl_GetArgLength(dp); 1686 1687 for (; dp; dp = dp->d_next) 1688 if (decl_IsVoid(dp)) { 1689 ++nv; 1690 1691 if (decl_GetName(dp)) 1692 ep = "argument list includes " 1693 "void with identifier"; 1694 } else if (decl_IsVoidArray(dp)) 1695 ep = "argument list includes void []"; 1696 1697 if (nv) { /* there was some void */ 1698 if (nargs > 1) 1699 ep = "argument list includes void"; 1700 1701 if (tp->d_ellipsis) 1702 ep = "argument list includes void and \"...\""; 1703 } 1704 } 1705 1706 return (ep); 1707 } 1708 1709 /* decl_AddDS - add a decl_spec_t to a decl_t. */ 1710 1711 static decl_t * 1712 decl_AddDS(decl_t *dp, decl_spec_t *dsp, const char **err) { 1713 declspec_AddDS(dp->d_ds, dsp, err); 1714 1715 return (dp); 1716 } 1717 1718 /* 1719 * decl_SetName - set the name associated with a decl_t. 1720 * 1721 * Note: 1722 * 1) Any previously known name is free'd. 1723 */ 1724 1725 decl_t * 1726 decl_SetName(decl_t *dp, char *s) { 1727 free(dp->d_name); 1728 dp->d_name = strdup(s); 1729 assert(dp->d_name != NULL); 1730 1731 return (dp); 1732 } 1733 1734 /* 1735 * decl_AddTypeTail - add a type_t to the end of a decl_t type_t list. 1736 */ 1737 1738 static decl_t * 1739 decl_AddTypeTail(decl_t *dp, type_t *tp) { 1740 if (dp->d_type) 1741 type_AddTail(dp->d_type, tp); 1742 else 1743 dp->d_type = tp; 1744 1745 return (dp); 1746 } 1747 1748 /* 1749 * decl_addptr - add a DD_PTR type_t to the end of a decl_t type_t list. 1750 */ 1751 1752 static decl_t * 1753 decl_addptr(decl_t *dp, type_t *tp) { 1754 decl_AddTypeTail(dp, tp); 1755 1756 return (dp); 1757 } 1758 1759 /* 1760 * decl_addary - allocate and add a DD_ARY type_t to the end of 1761 * a decl_t type_t list. 1762 */ 1763 1764 static decl_t * 1765 decl_addary(decl_t *dp, char *sizep) { 1766 type_t *tp = type_Construct(); 1767 1768 type_SetAry(tp, sizep); 1769 decl_AddTypeTail(dp, tp); 1770 1771 return (dp); 1772 } 1773 1774 /* 1775 * decl_addfun - allocate and add a DD_FUN type_t to the end of a 1776 * decl_t type_t list. 1777 */ 1778 1779 static decl_t * 1780 decl_addfun(decl_t *dp, decl_t *arglist) { 1781 const char *sp; 1782 type_t *tp = type_Construct(); 1783 1784 if (sp = decl_VerifyArgs(arglist)) 1785 yyerror(sp); 1786 1787 type_SetFun(tp, arglist); 1788 decl_AddTypeTail(dp, tp); 1789 1790 return (dp); 1791 } 1792 1793 /* 1794 * decl_addellipsis - set the ellipsis state in a decl_t. 1795 * 1796 * Note: 1797 * 1) This function is only used in the grammar in the 1798 * parameter list parsing. 1799 */ 1800 1801 static decl_t * 1802 decl_addellipsis(decl_t *dp) { 1803 dp->d_ellipsis = 1; 1804 1805 return (dp); 1806 } 1807 1808 #if defined(DEBUG) 1809 1810 static void 1811 decl_PrintDecl(decl_t *dp, int lvl) { 1812 char buf[BUFSIZ]; 1813 1814 while (dp) { 1815 putNTabs(lvl); 1816 1817 printf("name = %s, ds = %s\n", 1818 (dp->d_name)? dp->d_name : "<null>", 1819 declspec_ToString(buf, dp->d_ds)); 1820 1821 if (dp->d_type) 1822 type_PrintType(dp->d_type, lvl + 1); 1823 1824 dp = dp->d_next; 1825 } 1826 } 1827 #endif /* DEBUG */ 1828 1829 static char * 1830 char_getend(char *s) { 1831 while (*s != '\0') 1832 ++s; 1833 1834 return (s); 1835 } 1836 1837 char * 1838 decl_ToString(char *bufp, decl_dts_t out, decl_t *dp, 1839 const char *altname) { 1840 char tmp[BUFSIZ]; 1841 char tmp2[BUFSIZ]; 1842 const char *namep; 1843 char *bend = bufp; 1844 type_t *tp = dp->d_type; 1845 int ffun = 1; 1846 1847 switch (out) { 1848 default: 1849 out = DTS_DECL; 1850 /* FALLTHRU */ 1851 case DTS_DECL: 1852 if (altname == NULL) { 1853 namep = dp->d_name; 1854 } else { 1855 namep = altname; 1856 } 1857 break; 1858 case DTS_CAST: 1859 namep = "(*)"; 1860 break; 1861 case DTS_RET: 1862 if (altname == NULL) { 1863 namep = "_return"; 1864 } else { 1865 namep = altname; 1866 } 1867 break; 1868 } 1869 1870 *bufp = '\0'; 1871 1872 strcpy(tmp, (namep) ? namep : ""); 1873 1874 while (tp) { 1875 switch (tp->t_dt) { 1876 case DD_PTR: 1877 if (tp->t_next && 1878 ((tp->t_next->t_dt == DD_ARY) || 1879 (tp->t_next->t_dt == DD_FUN))) { 1880 if (out == DTS_RET) { 1881 sprintf(bufp, "(*%s)", namep); 1882 } else { 1883 sprintf(bufp, "(*%s)", tmp); 1884 } 1885 } else if (tp->t_stt == TQ_CONST) { 1886 sprintf(bufp, "*const %s", tmp); 1887 } else if (tp->t_stt == TQ_VOLATILE) { 1888 sprintf(bufp, "*volatile %s", tmp); 1889 /* 1890 * It currently acknowledges and ignores restrict 1891 * or _RESTRICT_KYWD in code generation because 1892 * of the uncertain behavior of "restrict". 1893 */ 1894 } else if (tp->t_stt == TQ_RESTRICT) { 1895 sprintf(bufp, "*%s", tmp); 1896 } else if (tp->t_stt == TQ_RESTRICT_KYWD) { 1897 sprintf(bufp, "*%s", tmp); 1898 } else { 1899 sprintf(bufp, "*%s", tmp); 1900 } 1901 1902 break; 1903 1904 case DD_ARY: 1905 sprintf(bufp, "%s[%s]", 1906 tmp, (tp->t_sizestr)? tp->t_sizestr : ""); 1907 break; 1908 1909 case DD_FUN: 1910 if (out == DTS_RET && ffun == 1) { 1911 strcpy(bufp, namep); 1912 ffun = 0; 1913 } else if (tp->t_args == NULL) { 1914 sprintf(bufp, "%s()", tmp); 1915 } else { 1916 char buf2[BUFSIZ]; 1917 decl_t *argp = tp->t_args; 1918 1919 sprintf(bufp, "%s(", tmp); 1920 bend = char_getend(bufp); 1921 1922 for (argp = tp->t_args; argp; /* noinc */) { 1923 decl_ToString(buf2, DTS_DECL, argp, 1924 NULL); 1925 sprintf(bend, " %s", buf2); 1926 1927 bend = char_getend(bend); 1928 1929 if (argp = argp->d_next) { 1930 sprintf(bend, ","); 1931 bend = char_getend(bend); 1932 } 1933 } 1934 1935 if (tp->t_ellipsis) { 1936 sprintf(bend, ", ..."); 1937 bend = char_getend(bend); 1938 } 1939 1940 sprintf(bend, ")"); 1941 } 1942 break; 1943 } 1944 1945 tp = tp->t_next; 1946 1947 strcpy(tmp, bufp); 1948 } 1949 1950 if (out == DTS_CAST) { 1951 sprintf(bufp, "(%s %s)", 1952 declspec_ToString(tmp2, dp->d_ds), tmp); 1953 } else { 1954 sprintf(bufp, "%s %s", 1955 declspec_ToString(tmp2, dp->d_ds), tmp); 1956 } 1957 1958 return (bufp); 1959 } 1960 1961 decl_t * 1962 decl_AddArgNames(decl_t *dp) { 1963 int argno = 0; 1964 decl_t *p = dp; 1965 1966 if (decl_IsFunction(dp)) { 1967 int argno = 0; 1968 decl_t *p = dp->d_type->t_args; 1969 1970 while (p) { 1971 char *s = decl_GetName(p); 1972 1973 if ((s == NULL) && !decl_IsVoid(p)) { 1974 char buf[BUFSIZ]; 1975 1976 sprintf(buf, "arg%d", argno); 1977 s = strdup(buf); 1978 decl_SetName(p, s); 1979 } 1980 1981 p = p->d_next; 1982 ++argno; 1983 } 1984 } 1985 return (dp); 1986 } 1987 1988 const char * 1989 decl_Parse(char *str, decl_t **dpp) { 1990 errstr = NULL; /* setup the (static) globals */ 1991 input = str; 1992 atIDENT = 0; 1993 protop = NULL; 1994 1995 yyparse(); /* parse the prototype */ 1996 1997 if (errstr == NULL) { /* success */ 1998 *dpp = protop; 1999 decl_AddArgNames(protop); 2000 } else { /* failure */ 2001 *dpp = NULL; 2002 decl_Destroy(protop); 2003 } 2004 2005 return (errstr); 2006 } 2007 2008 static void 2009 yyerror(const char *err) { 2010 errstr = err; 2011 } 2012 2013 #if defined(DEBUG) 2014 2015 /* main */ 2016 2017 static int yydebug = 1; 2018 2019 int 2020 main(int argc, char *argv[]) { 2021 int i; 2022 2023 yydebug = 1; 2024 2025 for (i = 1; i < argc; ++i) { 2026 const char *es; 2027 char buf[BUFSIZ]; 2028 decl_t *pp; 2029 2030 if (es = decl_Parse(argv[i], &pp)) 2031 printf("parse failure: %s\n", es); 2032 else { 2033 #if GR_DEBUG 2034 decl_PrintDecl(pp, 0); 2035 decl_AddArgNames(pp); 2036 #endif 2037 printf("---\n%s;\n", 2038 decl_ToString(buf, DTS_DECL, pp, NULL)); 2039 printf("%s\n", 2040 decl_ToString(buf, DTS_CAST, pp, NULL)); 2041 printf("%s;\n", 2042 decl_ToString(buf, DTS_RET, pp, "%s")); 2043 2044 #ifdef TRACE 2045 printf("\n\nTrace Info\n"); 2046 decl_PrintTraceInfo(pp); 2047 #endif 2048 } 2049 2050 decl_Destroy(pp); 2051 2052 #if defined(MEM_DEBUG) 2053 printf("declspec : %d\n", declspec_Construct_calls); 2054 printf("type : %d\n", type_Construct_calls); 2055 printf("decl : %d\n", decl_Construct_calls); 2056 #endif 2057 } 2058 2059 return (0); 2060 } 2061 2062 #ifdef TRACE 2063 void 2064 decl_PrintTraceInfo(decl_t *dp) { 2065 char buf[BUFSIZ]; 2066 char f_type[BUFSIZ]; 2067 char f_print[BUFSIZ]; 2068 char a_name[BUFSIZ]; 2069 char a_type[BUFSIZ]; 2070 char a_print[BUFSIZ]; 2071 decl_t *funargs; 2072 type_t *tp; 2073 int isptrfun; 2074 2075 if (dp == NULL) 2076 return; 2077 2078 fprintf(stderr, "interface = %s\n", 2079 (dp->d_name) ? dp->d_name : "<null>"); 2080 2081 isptrfun = type_IsPtrFun(dp->d_type); 2082 if (type_IsFunction(dp->d_type) || isptrfun) 2083 decl_GetTraceInfo(dp, f_type, f_print, &funargs); 2084 else 2085 return; 2086 2087 fprintf(stderr, "return type = %s\n", f_type); 2088 fprintf(stderr, "print function = %s\n", f_print); 2089 2090 if (isptrfun) 2091 fprintf(stderr, "function is function pointer\n"); 2092 2093 if (type_IsVarargs(dp->d_type)) 2094 fprintf(stderr, "function is varargs\n"); 2095 2096 while (funargs) { 2097 snprintf(a_type, BUFSIZ, "%s ", 2098 declspec_ToString(buf, funargs->d_ds)); 2099 snprintf(a_print, BUFSIZ, "%s", 2100 de_const(declspec_ToString(buf, funargs->d_ds))); 2101 2102 tp = funargs->d_type; 2103 2104 while (tp) { 2105 if (tp->t_dt == DD_PTR || tp->t_dt == DD_ARY) { 2106 strcat(a_type, "*"); 2107 strcat(a_print, "_P"); 2108 } 2109 tp = tp->t_next; 2110 } 2111 2112 if (funargs->d_name) { 2113 snprintf(a_name, BUFSIZ, "%s", 2114 funargs->d_name ? funargs->d_name : "<nil>"); 2115 fprintf(stderr, "arg name = %s\n", a_name); 2116 fprintf(stderr, "arg type = %s\n", a_type); 2117 fprintf(stderr, "print function = %s\n", a_print); 2118 } else { 2119 strcpy(a_name, ""); 2120 strcpy(a_print, ""); 2121 fprintf(stderr, "arg type = %s\n", a_type); 2122 } 2123 2124 funargs = funargs->d_next; 2125 } 2126 } 2127 #endif /* TRACE */ 2128 #endif /* DEBUG */ 2129 2130 static char * 2131 de_const(char *str) 2132 { 2133 return (str); 2134 } 2135 2136 2137 void 2138 decl_GetTraceInfo(decl_t *dp, char *f_type, char *f_print, decl_t **funargs) 2139 { 2140 char buf[BUFSIZ]; 2141 type_t *tp; 2142 2143 if (dp == NULL) 2144 return; 2145 2146 snprintf(f_type, BUFSIZ, "%s ", 2147 declspec_ToString(buf, dp->d_ds)); 2148 snprintf(f_print, BUFSIZ, "%s", 2149 de_const(declspec_ToString(buf, dp->d_ds))); 2150 tp = dp->d_type; 2151 while (tp) { 2152 if (tp->t_dt == DD_PTR) { 2153 strcat(f_type, "*"); 2154 strcat(f_print, "*"); 2155 } 2156 tp = tp->t_next; 2157 } 2158 2159 strcat(f_type, "%s"); 2160 2161 tp = decl_GetType(dp); 2162 if (type_IsPtrFun(tp)) { 2163 while (tp->t_dt != DD_FUN) 2164 tp = tp->t_next; 2165 *funargs = tp->t_args; 2166 } else { 2167 *funargs = dp->d_type->t_args; 2168 } 2169 } 2170 2171 char * 2172 decl_ToFormal(decl_t *dp) 2173 { 2174 char tmp[BUFSIZ]; 2175 static char bufp[BUFSIZ]; 2176 char *bend; 2177 type_t *tp = dp->d_type; 2178 2179 tmp[0] = 0; 2180 bufp[0] = 0; 2181 bend = bufp; 2182 2183 while (tp) { 2184 switch (tp->t_dt) { 2185 case DD_ARY: 2186 sprintf(bufp, "%s[%s]", tmp, 2187 (tp->t_sizestr)? tp->t_sizestr : ""); 2188 break; 2189 2190 case DD_FUN: 2191 if (tp->t_args != NULL) { 2192 char buf2[BUFSIZ]; 2193 decl_t *argp = tp->t_args; 2194 2195 bend = char_getend(bufp); 2196 2197 for (argp = tp->t_args; argp; /* noinc */) { 2198 decl_ToString(buf2, DTS_DECL, argp, 2199 NULL); 2200 sprintf(bend, " %s", buf2); 2201 2202 bend = char_getend(bend); 2203 2204 if (argp = argp->d_next) { 2205 sprintf(bend, ","); 2206 bend = char_getend(bend); 2207 } 2208 } 2209 if (tp->t_ellipsis) { 2210 sprintf(bend, ", ..."); 2211 bend = char_getend(bend); 2212 } 2213 2214 sprintf(bend, ""); 2215 } 2216 break; 2217 } 2218 2219 tp = tp->t_next; 2220 2221 strcpy(tmp, bufp); 2222 } 2223 2224 sprintf(bufp, "%s", tmp); 2225 2226 return (bufp); 2227 } 2228