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