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 #include "parseproto.h" 30 #include <assert.h> 31 32 static decl_spec_t *declspec_Construct(void); 33 static void declspec_Destroy(decl_spec_t *); 34 static decl_spec_t *declspec_Init(stt_t, char *); 35 static char *declspec_VerifySTT(stt_t, stt_t); 36 static decl_spec_t *declspec_AddSTT(decl_spec_t *, stt_t, const char **); 37 static decl_spec_t *declspec_AddDS(decl_spec_t *, 38 decl_spec_t *, const char **); 39 static stt_t declspec_GetSTT(decl_spec_t *); 40 static char *declspec_GetTag(decl_spec_t *); 41 static type_t *type_Construct(void); 42 static void type_Destroy(type_t *); 43 static type_t *type_SetPtr(type_t *, stt_t); 44 static type_t *type_SetFun(type_t *, decl_t *); 45 static type_t *type_AddTail(type_t *, type_t *); 46 static const char *type_Verify(type_t *); 47 48 static decl_t *decl_Construct(void); 49 static decl_t *decl_AddArg(decl_t *, decl_t *); 50 static int decl_IsVoid(decl_t *); 51 static int decl_IsVoidArray(decl_t *); 52 static const char *decl_VerifyArgs(decl_t *); 53 static decl_t *decl_AddDS(decl_t *, decl_spec_t *, const char **); 54 static decl_t *decl_AddTypeTail(decl_t *, type_t *); 55 static decl_t *decl_addptr(decl_t *, type_t *); 56 static decl_t *decl_addary(decl_t *, char *); 57 static decl_t *decl_addfun(decl_t *, decl_t *); 58 static decl_t *decl_addellipsis(decl_t *); 59 60 #if defined(DEBUG) 61 static void type_PrintType(type_t *, int); 62 static void decl_PrintDecl(decl_t *, int); 63 static void decl_PrintTraceInfo(decl_t *); 64 static char *de_const(char *); 65 #endif 66 67 68 69 static int yylex(void); 70 static void yyerror(const char *); 71 static int yyparse(void); 72 73 #if defined(MEM_DEBUG) 74 static int declspec_Construct_calls; 75 static int type_Construct_calls; 76 static int decl_Construct_calls; 77 #endif 78 79 #if defined(DEBUG) 80 static char *de_const(char *); 81 #endif 82 %} 83 84 %union { 85 char *s_val; 86 int i_val; 87 stt_t stt_val; 88 decl_spec_t *ds_val; 89 type_t *t_val; 90 decl_t *d_val; 91 } 92 93 %token <i_val> ELLIPSIS 94 95 %token <s_val> INTEGER 96 %token <s_val> IDENTIFIER 97 %token <s_val> TYPEDEF_NAME 98 %type <s_val> constant_expression 99 100 %token <stt_val> REGISTER 101 %token <stt_val> TYPEDEF EXTERN AUTO STATIC 102 %token <stt_val> VOID CHAR SHORT INT LONG 103 %token <stt_val> FLOAT DOUBLE SIGNED UNSIGNED 104 %token <stt_val> CONST VOLATILE RESTRICT RESTRICT_KYWD 105 %type <stt_val> struct_or_union 106 %type <ds_val> storage_class_specifier 107 %type <ds_val> type_qualifier 108 %type <ds_val> type_qualifier_list 109 110 %token <ds_val> STRUCT UNION 111 %token <ds_val> ENUM 112 %type <ds_val> declaration_specifiers 113 %type <ds_val> type_specifier 114 %type <ds_val> struct_or_union_specifier enum_specifier 115 %type <ds_val> typedef_name 116 117 %type <t_val> pointer 118 119 %type <d_val> declaration 120 %type <d_val> init_declarator_list init_declarator 121 %type <d_val> declarator 122 %type <d_val> direct_declarator 123 %type <d_val> parameter_type_list parameter_list 124 %type <d_val> parameter_declaration 125 %type <d_val> abstract_declarator 126 %type <d_val> direct_abstract_declarator 127 128 %start declaration 129 130 %% 131 132 /* 133 * The grammar is derived from ANSI/ISO 9899-1990. 134 */ 135 136 declaration 137 : declaration_specifiers init_declarator_list ';' 138 { 139 decl_t *dp; 140 141 protop = $$ = $2; 142 143 /* only one declaration allowed */ 144 assert(protop->d_next == NULL); 145 146 for (dp = $2; dp && (errstr == NULL); 147 dp = dp->d_next) { 148 const char *sp; 149 150 decl_AddDS(dp, $1, &errstr); 151 if (sp = decl_Verify(dp)) 152 errstr = sp; 153 } 154 declspec_Destroy($1); 155 } 156 | error ';' 157 { 158 protop = $$ = NULL; 159 errstr = "function prototype syntax error"; 160 } 161 /* 162 * XXX - Does not support a "stand-alone" declaration specifier. It is 163 * essentially a type declaration, for example: 164 * 165 * typedef enum { FALSE = 0, TRUE = 1 } boolean_t; 166 * or 167 * struct _name { char *first; char *last }; 168 */ 169 170 /* XXX | declaration_specifiers */ 171 ; 172 173 declaration_specifiers 174 : storage_class_specifier declaration_specifiers 175 { 176 char const *ep; 177 178 $$ = declspec_AddDS($2, $1, &ep); 179 declspec_Destroy($1); 180 181 if (errstr == NULL) 182 errstr = ep; 183 } 184 | storage_class_specifier 185 | type_specifier declaration_specifiers 186 { 187 const char *ep; 188 189 $$ = declspec_AddDS($2, $1, &ep); 190 declspec_Destroy($1); 191 192 if (errstr == NULL) 193 errstr = ep; 194 } 195 | type_specifier 196 | type_qualifier declaration_specifiers 197 { 198 const char *ep; 199 200 $$ = declspec_AddDS($2, $1, &ep); 201 declspec_Destroy($1); 202 203 if (errstr == NULL) 204 errstr = ep; 205 } 206 | type_qualifier 207 ; 208 209 storage_class_specifier 210 : REGISTER 211 { 212 $$ = declspec_Init(SCS_REGISTER, NULL); 213 } 214 /* 215 * XXX - Does not support any storage class specifier other than 216 * register, and then only for function arguments. 217 * 218 | TYPEDEF 219 { 220 $$ = declspec_Init(SCS_TYPEDEF, NULL); 221 } 222 | EXTERN 223 { 224 $$ = declspec_Init(SCS_EXTERN, NULL); 225 } 226 | STATIC 227 { 228 $$ = declspec_Init(SCS_STATIC, NULL); 229 } 230 | AUTO 231 { 232 $$ = declspec_Init(SCS_AUTO, NULL); 233 } 234 */ 235 ; 236 237 type_specifier 238 : VOID 239 { 240 $$ = declspec_Init(TS_VOID, NULL); 241 atIDENT = 1; 242 } 243 | CHAR 244 { 245 $$ = declspec_Init(TS_CHAR, NULL); 246 atIDENT = 1; 247 } 248 | SHORT 249 { 250 $$ = declspec_Init(TS_SHORT, NULL); 251 atIDENT = 1; 252 } 253 | INT 254 { 255 $$ = declspec_Init(TS_INT, NULL); 256 atIDENT = 1; 257 } 258 | LONG 259 { 260 $$ = declspec_Init(TS_LONG, NULL); 261 atIDENT = 1; 262 } 263 | FLOAT 264 { 265 $$ = declspec_Init(TS_FLOAT, NULL); 266 atIDENT = 1; 267 } 268 | DOUBLE 269 { 270 $$ = declspec_Init(TS_DOUBLE, NULL); 271 atIDENT = 1; 272 } 273 | SIGNED 274 { 275 $$ = declspec_Init(TS_SIGNED, NULL); 276 atIDENT = 1; 277 } 278 | UNSIGNED 279 { 280 $$ = declspec_Init(TS_UNSIGNED, NULL); 281 atIDENT = 1; 282 } 283 | struct_or_union_specifier 284 | enum_specifier 285 | typedef_name 286 ; 287 288 typedef_name 289 : TYPEDEF_NAME 290 { 291 $$ = declspec_Init(TS_TYPEDEF, $1); 292 atIDENT = 1; 293 free($1); 294 } 295 ; 296 297 /* 298 * The "restrict" keyword is new in the C99 standard. 299 * It is type qualifier like const and volatile. 300 * We are using "_RESTRICT_KYWD" in headers and source code so 301 * it is easily turned on and off by various macros at compile time. 302 * In order for the "restrict" keyword to be recognized you must 303 * be using a C99 compliant compiler in its native mode. 304 */ 305 type_qualifier 306 : CONST 307 { 308 $$ = declspec_Init(TQ_CONST, NULL); 309 } 310 | VOLATILE 311 { 312 $$ = declspec_Init(TQ_VOLATILE, NULL); 313 } 314 | RESTRICT 315 { 316 $$ = declspec_Init(TQ_RESTRICT, NULL); 317 } 318 | RESTRICT_KYWD 319 { 320 $$ = declspec_Init(TQ_RESTRICT_KYWD, NULL); 321 } 322 ; 323 324 struct_or_union_specifier 325 : struct_or_union { atIDENT = 1; } IDENTIFIER 326 { 327 $$ = declspec_Init($1, $3); 328 free($3); 329 } 330 /* 331 * XXX - struct or union definitions are not supported. It is generally 332 * not done within the context of a function declaration (prototype) or 333 * variable definition. 334 335 | struct_or_union IDENTIFIER '{' struct_declaration_list '}' 336 | struct_or_union '{' struct_declaration_list '}' 337 */ 338 ; 339 340 struct_or_union 341 : STRUCT 342 { 343 $$ = TS_STRUCT; 344 } 345 | UNION 346 { 347 $$ = TS_UNION; 348 } 349 ; 350 351 init_declarator_list 352 : init_declarator 353 { 354 $$ = $1; 355 atIDENT = 1; 356 } 357 /* 358 * XXX - Does not support a comma separated list of declarations or 359 * definitions. Function prototypes or variable definitions must be 360 * given as one per C statement. 361 362 | init_declarator_list ',' init_declarator 363 { 364 $$ = decl_AddArg($1, $3); 365 atIDENT = 1; 366 } 367 */ 368 ; 369 370 init_declarator 371 : declarator 372 /* 373 * XXX - Initialization is not supported. 374 375 | declarator '=' initializer 376 */ 377 ; 378 379 380 enum_specifier 381 : ENUM { atIDENT = 1; } IDENTIFIER 382 { 383 $$ = declspec_Init(TS_ENUM, $3); 384 free($3); 385 } 386 /* 387 * XXX - enumerator definition is not supported for the same reasons 388 * struct|union definition is not supported. 389 390 | ENUM IDENTIFIER '{' enumerator_list '}' 391 | ENUM '{' enumerator_list '}' 392 */ 393 ; 394 395 396 declarator 397 : pointer direct_declarator 398 { 399 $$ = decl_addptr($2, $1); 400 } 401 | direct_declarator 402 ; 403 404 direct_declarator 405 : IDENTIFIER 406 { 407 $$ = decl_SetName(decl_Construct(), $1); 408 atIDENT = 0; 409 free($1); 410 } 411 | '(' declarator ')' 412 { 413 $$ = $2; 414 } 415 | direct_declarator '[' constant_expression ']' 416 { 417 $$ = decl_addary($1, $3); 418 free($3); 419 } 420 | direct_declarator '[' ']' 421 { 422 $$ = decl_addary($1, NULL); 423 } 424 | direct_declarator '(' parameter_type_list ')' 425 { 426 $$ = decl_addfun($1, $3); 427 } 428 | direct_declarator '(' ')' 429 { 430 $$ = decl_addfun($1, NULL); 431 } 432 ; 433 434 pointer 435 : '*' type_qualifier_list 436 { 437 $$ = type_SetPtr(type_Construct(), ($2)->ds_stt); 438 declspec_Destroy($2); 439 } 440 | '*' 441 { 442 $$ = type_SetPtr(type_Construct(), TQ_NONE); 443 } 444 | '*' type_qualifier_list pointer 445 { 446 type_t *tp = type_Construct(); 447 448 type_SetPtr(tp, ($2)->ds_stt); 449 declspec_Destroy($2); 450 $$ = type_AddTail($3, tp); 451 } 452 | '*' pointer 453 { 454 type_t *tp = type_Construct(); 455 456 type_SetPtr(tp, TQ_NONE); 457 $$ = type_AddTail($2, tp); 458 } 459 ; 460 461 type_qualifier_list 462 : type_qualifier 463 | type_qualifier_list type_qualifier 464 { 465 const char *ep; 466 467 /* XXX - ignore any error */ 468 $$ = declspec_AddDS($1, $2, &ep); 469 declspec_Destroy($2); 470 } 471 ; 472 473 parameter_type_list 474 : parameter_list 475 | parameter_list ',' ELLIPSIS 476 { 477 $$ = decl_addellipsis($1); 478 } 479 ; 480 481 parameter_list 482 : parameter_declaration 483 { 484 const char *sp = type_Verify($1->d_type); 485 486 if (sp) 487 errstr = sp; 488 489 $$ = $1; 490 atIDENT = 0; 491 } 492 | parameter_list ',' parameter_declaration 493 { 494 const char *sp = type_Verify($3->d_type); 495 496 if (sp) 497 errstr = sp; 498 499 $$ = decl_AddArg($1, $3); 500 atIDENT = 0; 501 } 502 ; 503 504 parameter_declaration 505 : declaration_specifiers declarator 506 { 507 const char *ep; 508 509 $$ = decl_AddDS($2, $1, &ep); 510 declspec_Destroy($1); 511 512 if (errstr == NULL) 513 errstr = ep; 514 } 515 | declaration_specifiers abstract_declarator 516 { 517 const char *ep; 518 519 $$ = decl_AddDS($2, $1, &ep); 520 declspec_Destroy($1); 521 522 if (errstr == NULL) 523 errstr = ep; 524 } 525 | declaration_specifiers 526 { 527 const char *ep; 528 529 $$ = decl_AddDS(decl_Construct(), $1, &ep); 530 declspec_Destroy($1); 531 532 if (errstr == NULL) 533 errstr = ep; 534 } 535 ; 536 537 abstract_declarator 538 : pointer 539 { 540 $$ = decl_addptr(decl_Construct(), $1); 541 } 542 | pointer direct_abstract_declarator 543 { 544 $$ = decl_addptr($2, $1); 545 } 546 | direct_abstract_declarator 547 ; 548 549 direct_abstract_declarator 550 : '(' abstract_declarator ')' 551 { 552 $$ = $2; 553 } 554 | direct_abstract_declarator '[' constant_expression ']' 555 { 556 $$ = decl_addary($1, $3); 557 free($3); 558 } 559 | '[' constant_expression ']' 560 { 561 $$ = decl_addary(decl_Construct(), $2); 562 free($2); 563 } 564 | direct_abstract_declarator '[' ']' 565 { 566 $$ = decl_addary($1, NULL); 567 } 568 | '[' ']' 569 { 570 $$ = decl_addary(decl_Construct(), NULL); 571 } 572 | direct_abstract_declarator '(' parameter_type_list ')' 573 { 574 $$ = decl_addfun($1, $3); 575 } 576 | '(' parameter_type_list ')' 577 { 578 $$ = decl_addfun(decl_Construct(), $2); 579 } 580 | direct_abstract_declarator '(' ')' 581 { 582 $$ = decl_addfun($1, NULL); 583 } 584 | '(' ')' 585 { 586 $$ = decl_addfun(decl_Construct(), NULL); 587 } 588 ; 589 590 /* 591 * XXX - General case constant expressions are not supported. It would 592 * be easy to implement (for the most part), but there are no cases to 593 * date that require such a facility. The grammar does allow an 594 * identifier (or typedef name) to be used since the prototype is not 595 * processed by CPP. The only integer constant that is supported is 596 * decimal. 597 */ 598 599 constant_expression 600 : INTEGER 601 | IDENTIFIER 602 | TYPEDEF_NAME 603 ; 604 605 %% 606 607 /* Data Declarations */ 608 609 typedef struct { 610 char *name; 611 int token; 612 stt_t stt; 613 } keyword_t; 614 615 typedef struct { 616 stt_t s_stt; 617 char *s_str; 618 } sttpair_t; 619 620 /* External Declarations */ 621 622 static const keyword_t *lookup_keyword(const char *); 623 static const char *lookup_sttpair(stt_t); 624 static int getch(void); 625 static void ungetch(int); 626 static void skipwhitespace(void); 627 static int lookahead(int); 628 static void skipcomment(void); 629 630 /* External Definitions */ 631 632 static char *input = NULL; /* current place in the input stream */ 633 /* at point in stream were identifier is expected */ 634 static int atIDENT = 0; 635 static decl_t *protop = NULL; /* pointer to prototype */ 636 static const char *errstr = NULL; /* error message */ 637 638 /* 639 * lookup_keyword - Given a string, return the keyword_t or NULL. 640 */ 641 642 static const keyword_t * 643 lookup_keyword(const char *name) { 644 static const keyword_t keytbl[] = { 645 { "register", REGISTER, SCS_REGISTER }, 646 #if UNSUPPORTED 647 { "typedef", TYPEDEF, SCS_TYPEDEF }, 648 { "auto", AUTO, SCS_AUTO }, 649 { "static", STATIC, SCS_STATIC }, 650 { "extern", EXTERN, SCS_EXTERN }, 651 #endif /* UNSUPPORTED */ 652 { "void", VOID, TS_VOID }, 653 { "char", CHAR, TS_CHAR }, 654 { "short", SHORT, TS_SHORT }, 655 { "int", INT, TS_INT }, 656 { "long", LONG, TS_LONG }, 657 { "float", FLOAT, TS_FLOAT }, 658 { "double", DOUBLE, TS_DOUBLE }, 659 { "signed", SIGNED, TS_SIGNED }, 660 { "unsigned", UNSIGNED, TS_UNSIGNED }, 661 { "struct", STRUCT, TS_STRUCT }, 662 { "union", UNION, TS_UNION }, 663 { "enum", ENUM, TS_ENUM }, 664 665 { "const", CONST, TQ_CONST }, 666 { "volatile", VOLATILE, TQ_VOLATILE }, 667 { "restrict", RESTRICT, TQ_RESTRICT }, 668 { "_RESTRICT_KYWD",RESTRICT_KYWD, TQ_RESTRICT_KYWD}, 669 }; 670 #define NKEYWORD (sizeof (keytbl)/sizeof (keyword_t)) 671 672 int i; 673 674 for (i = 0; i < NKEYWORD; ++i) { 675 char *s = keytbl[i].name; 676 677 if ((*s == *name) && (strcmp(s, name) == 0)) 678 return (&keytbl[i]); 679 } 680 681 return (NULL); 682 } 683 684 /* 685 * lookup_sttpair - Given an stt_t return a string or NULL. 686 * 687 */ 688 689 static const char * 690 lookup_sttpair(stt_t s) { 691 /* valid type specifier combinations */ 692 static const sttpair_t stttbl[] = { 693 { TS_VOID, "void" }, 694 { TS_CHAR, "char" }, 695 { TS_SIGNED | TS_CHAR, "signed char" }, 696 { TS_UNSIGNED | TS_CHAR, "unsigned char" }, 697 { TS_SHORT, "short" }, 698 { TS_SIGNED | TS_SHORT, "signed short" }, 699 { TS_SHORT | TS_INT, "short int" }, 700 { TS_SIGNED | TS_SHORT | TS_INT, 701 "signed short int" }, 702 { TS_UNSIGNED | TS_SHORT, 703 "unsigned short" }, 704 { TS_UNSIGNED | TS_SHORT | TS_INT, 705 "unsigned short int" }, 706 { TS_INT, "int" }, 707 { TS_SIGNED, "signed" }, 708 { TS_SIGNED | TS_INT, "signed int" }, 709 { TS_NO_TS, "" }, 710 { TS_UNSIGNED, "unsigned" }, 711 { TS_UNSIGNED | TS_INT, "unsigned int" }, 712 { TS_LONG, "long" }, 713 { TS_SIGNED | TS_LONG, "signed long" }, 714 { TS_LONG | TS_INT, "long int" }, 715 { TS_SIGNED | TS_LONG | TS_INT, 716 "signed long int" }, 717 { TS_UNSIGNED | TS_LONG, "unsigned long" }, 718 { TS_UNSIGNED | TS_LONG | TS_INT, 719 "unsigned long int" }, 720 { TS_FLOAT, "float" }, 721 { TS_DOUBLE, "double" }, 722 { TS_LONG | TS_DOUBLE, "long double" }, 723 { TS_STRUCT, "struct" }, 724 { TS_UNION, "union" }, 725 { TS_ENUM, "enum" }, 726 { TS_TYPEDEF, "" }, 727 /* non-ANSI type: long long */ 728 { TS_LONGLONG, "long long" }, 729 { TS_LONGLONG | TS_INT, "long long int" }, 730 { TS_SIGNED | TS_LONGLONG, 731 "signed long long" }, 732 { TS_UNSIGNED | TS_LONGLONG, 733 "unsigned long long" }, 734 { TS_SIGNED | TS_LONGLONG | TS_INT, 735 "signed long long int" }, 736 { TS_UNSIGNED | TS_LONGLONG | TS_INT, 737 "unsigned long long int" }, 738 }; 739 740 #define NDECLSPEC (sizeof (stttbl)/sizeof (sttpair_t)) 741 742 int i; 743 744 for (i = 0; i < NDECLSPEC; ++i) 745 if (s == stttbl[i].s_stt) 746 return (stttbl[i].s_str); 747 748 return (NULL); 749 } 750 751 /* 752 * yylex - return next token from the the input stream. 753 * 754 * The lexical analyzer does not recognize all possible C lexical 755 * elements. It only recognizes those associated with function 756 * declarations (read: prototypes) and data definitions. 757 */ 758 759 static int 760 yylex(void) { 761 char buf[BUFSIZ]; /* string version of token */ 762 int c; 763 int i = 0; 764 765 restart: 766 skipwhitespace(); 767 768 switch (c = getch()) { 769 case '/': 770 if (lookahead('*')) { 771 skipcomment(); 772 goto restart; 773 } 774 return (c); 775 776 case '.': 777 if (lookahead('.')) { 778 if (lookahead('.')) 779 return (ELLIPSIS); 780 } 781 return (c); 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