1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ 27 /* All Rights Reserved */ 28 /* 29 * University Copyright- Copyright (c) 1982, 1986, 1988 30 * The Regents of the University of California 31 * All Rights Reserved 32 * 33 * University Acknowledgment- Portions of this document are derived from 34 * software developed by the University of California, Berkeley, and its 35 * contributors. 36 */ 37 38 #pragma ident "%Z%%M% %I% %E% SMI" 39 40 /* 41 * rpc_parse.c, Parser for the RPC protocol compiler 42 */ 43 #include <stdio.h> 44 #include <string.h> 45 #include "rpc/types.h" 46 #include "rpc_scan.h" 47 #include "rpc_parse.h" 48 #include "rpc_util.h" 49 50 #define ARGNAME "arg" 51 52 extern char *make_argname(); 53 extern char *strdup(); 54 55 /* 56 * return the next definition you see 57 */ 58 definition * 59 get_definition() 60 { 61 definition *defp; 62 token tok; 63 64 defp = ALLOC(definition); 65 get_token(&tok); 66 switch (tok.kind) { 67 case TOK_STRUCT: 68 def_struct(defp); 69 break; 70 case TOK_UNION: 71 def_union(defp); 72 break; 73 case TOK_TYPEDEF: 74 def_typedef(defp); 75 break; 76 case TOK_ENUM: 77 def_enum(defp); 78 break; 79 case TOK_PROGRAM: 80 def_program(defp); 81 break; 82 case TOK_CONST: 83 def_const(defp); 84 break; 85 case TOK_EOF: 86 return (NULL); 87 default: 88 error("definition keyword expected"); 89 } 90 scan(TOK_SEMICOLON, &tok); 91 isdefined(defp); 92 return (defp); 93 } 94 95 static 96 isdefined(defp) 97 definition *defp; 98 { 99 STOREVAL(&defined, defp); 100 } 101 102 /* 103 * We treat s == NULL the same as *s == '\0' 104 */ 105 streqn(const char *s1, const char *s2) 106 { 107 if (s1 == NULL) 108 s1 = ""; 109 if (s2 == NULL) 110 s2 = ""; 111 if (s1 == s2) 112 return (1); 113 114 return (strcmp(s1, s2) == 0); 115 } 116 117 static int 118 cmptype(definition *defp, char *type) 119 { 120 /* We only want typedef definitions */ 121 if (streq(defp->def_name, type) && defp->def_kind == DEF_TYPEDEF) 122 return (1); 123 124 return (0); 125 } 126 127 static int 128 check_self_reference(const char *name, const declaration *decp, int first) 129 { 130 /* 131 * Now check for the following special case if first is true: 132 * 133 * struct foo { 134 * ... 135 * foo *next; 136 * }; 137 * 138 * 139 * In the above cases foo has not yet been entered in the type list, 140 * defined. So there is no typedef entry. The prefix in that case 141 * could be empty. 142 */ 143 if (decp->rel == REL_POINTER && 144 (streqn(decp->prefix, "struct") || 145 (first && streqn(decp->prefix, ""))) && 146 streqn(name, decp->type)) 147 return (1); 148 return (0); 149 } 150 151 static int 152 is_self_reference(definition *defp, declaration *decp) 153 { 154 declaration current; 155 definition *dp; 156 157 if (check_self_reference(defp->def_name, decp, 1)) 158 return (1); 159 160 /* 161 * Check for valid declaration: 162 * Only prefixes allowed are none and struct. 163 * Only relations allowed are pointer or alias. 164 */ 165 if (!streqn(decp->prefix, "struct") && !streqn(decp->prefix, "")) 166 return (0); 167 if (decp->rel != REL_POINTER && decp->rel != REL_ALIAS) 168 return (0); 169 170 current.rel = decp->rel; 171 current.prefix = decp->prefix; 172 current.type = decp->type; 173 current.name = decp->name; 174 decp = ¤t; 175 while (!check_self_reference(defp->def_name, decp, 0)) { 176 dp = FINDVAL(defined, decp->type, cmptype); 177 178 /* 179 * Check if we found a definition. 180 */ 181 if (dp == NULL) 182 return (0); 183 184 /* 185 * Check for valid prefix. We eventually need to see one 186 * and only one struct. 187 */ 188 if (streqn(decp->prefix, "")) { 189 /* 190 * If the current declaration prefix in empty 191 * then the definition found must have an empty 192 * prefix or a struct prefix 193 */ 194 if (!streqn(dp->def.ty.old_prefix, "") && 195 !streqn(dp->def.ty.old_prefix, "struct")) 196 return (0); 197 } else if (streqn(decp->prefix, "struct") && 198 !streqn(dp->def.ty.old_prefix, "")) 199 /* 200 * if the current prefix is struct tne new prefix 201 * must be empty 202 */ 203 return (0); 204 else if (!streqn(decp->prefix, "struct")) 205 /* Should never get here */ 206 return (0); 207 208 /* 209 * Check for valid relation. We need to see one and 210 * only one REL_POINTER. The only valid relation types 211 * are REL_POINTER and REL_ALIAS. 212 */ 213 if (decp->rel == REL_POINTER && dp->def.ty.rel != REL_ALIAS) 214 return (0); 215 else if (decp->rel == REL_ALIAS && 216 (dp->def.ty.rel != REL_ALIAS && 217 dp->def.ty.rel != REL_POINTER)) 218 return (0); 219 else if (decp->rel != REL_ALIAS && decp->rel != REL_POINTER) 220 /* Should never get here */ 221 return (0); 222 223 /* Set up the current declaration */ 224 if (streqn(decp->prefix, "")) 225 decp->prefix = dp->def.ty.old_prefix; 226 decp->type = dp->def.ty.old_type; 227 if (decp->rel == REL_ALIAS) 228 decp->rel = dp->def.ty.rel; 229 } 230 231 /* We have a self reference type */ 232 return (1); 233 } 234 235 static 236 def_struct(defp) 237 definition *defp; 238 { 239 token tok; 240 declaration dec; 241 decl_list *decls; 242 decl_list **tailp, *endp; 243 244 defp->def_kind = DEF_STRUCT; 245 246 scan(TOK_IDENT, &tok); 247 defp->def_name = tok.str; 248 scan(TOK_LBRACE, &tok); 249 tailp = &defp->def.st.decls; 250 defp->def.st.tail = NULL; 251 do { 252 get_declaration(&dec, DEF_STRUCT); 253 decls = ALLOC(decl_list); 254 decls->decl = dec; 255 /* 256 * Keep a referenct to the last declaration to check for 257 * tail recurrsion. 258 */ 259 endp = *tailp = decls; 260 tailp = &decls->next; 261 scan(TOK_SEMICOLON, &tok); 262 peek(&tok); 263 } while (tok.kind != TOK_RBRACE); 264 *tailp = NULL; 265 /* 266 * Check for tail recurse. If the last declaration refers to this 267 * structure then mark this stucture to convert the tail recursion 268 * to itteration. 269 */ 270 defp->def.st.self_pointer = is_self_reference(defp, &endp->decl); 271 get_token(&tok); 272 defp->def.st.tail = endp; 273 } 274 275 static 276 def_program(defp) 277 definition *defp; 278 { 279 token tok; 280 declaration dec; 281 decl_list *decls; 282 decl_list **tailp; 283 version_list *vlist; 284 version_list **vtailp; 285 proc_list *plist; 286 proc_list **ptailp; 287 int num_args; 288 bool_t isvoid = FALSE; /* whether first argument is void */ 289 defp->def_kind = DEF_PROGRAM; 290 scan(TOK_IDENT, &tok); 291 defp->def_name = tok.str; 292 scan(TOK_LBRACE, &tok); 293 vtailp = &defp->def.pr.versions; 294 tailp = &defp->def.st.decls; 295 scan(TOK_VERSION, &tok); 296 do { 297 scan(TOK_IDENT, &tok); 298 vlist = ALLOC(version_list); 299 vlist->vers_name = tok.str; 300 scan(TOK_LBRACE, &tok); 301 ptailp = &vlist->procs; 302 do { 303 /* get result type */ 304 plist = ALLOC(proc_list); 305 get_type(&plist->res_prefix, &plist->res_type, 306 DEF_RESULT); 307 if (streq(plist->res_type, "opaque")) { 308 error("illegal result type"); 309 } 310 scan(TOK_IDENT, &tok); 311 plist->proc_name = tok.str; 312 scan(TOK_LPAREN, &tok); 313 /* get args - first one */ 314 num_args = 1; 315 isvoid = FALSE; 316 /* 317 * type of DEF_PROGRAM in the first 318 * get_prog_declaration and DEF_STURCT in the next 319 * allows void as argument if it is the only argument 320 */ 321 get_prog_declaration(&dec, DEF_PROGRAM, num_args); 322 if (streq(dec.type, "void")) 323 isvoid = TRUE; 324 decls = ALLOC(decl_list); 325 plist->args.decls = decls; 326 decls->decl = dec; 327 tailp = &decls->next; 328 /* get args */ 329 while (peekscan(TOK_COMMA, &tok)) { 330 num_args++; 331 get_prog_declaration(&dec, DEF_STRUCT, 332 num_args); 333 decls = ALLOC(decl_list); 334 decls->decl = dec; 335 *tailp = decls; 336 if (streq(dec.type, "void")) 337 isvoid = TRUE; 338 tailp = &decls->next; 339 } 340 /* multiple arguments are only allowed in newstyle */ 341 if (!newstyle && num_args > 1) { 342 error("only one argument is allowed"); 343 } 344 if (isvoid && num_args > 1) { 345 error("illegal use of void " 346 "in program definition"); 347 } 348 *tailp = NULL; 349 scan(TOK_RPAREN, &tok); 350 scan(TOK_EQUAL, &tok); 351 scan_num(&tok); 352 scan(TOK_SEMICOLON, &tok); 353 plist->proc_num = tok.str; 354 plist->arg_num = num_args; 355 *ptailp = plist; 356 ptailp = &plist->next; 357 peek(&tok); 358 } while (tok.kind != TOK_RBRACE); 359 *ptailp = NULL; 360 *vtailp = vlist; 361 vtailp = &vlist->next; 362 scan(TOK_RBRACE, &tok); 363 scan(TOK_EQUAL, &tok); 364 scan_num(&tok); 365 vlist->vers_num = tok.str; 366 /* make the argument structure name for each arg */ 367 for (plist = vlist->procs; plist != NULL; 368 plist = plist->next) { 369 plist->args.argname = make_argname(plist->proc_name, 370 vlist->vers_num); 371 /* free the memory ?? */ 372 } 373 scan(TOK_SEMICOLON, &tok); 374 scan2(TOK_VERSION, TOK_RBRACE, &tok); 375 } while (tok.kind == TOK_VERSION); 376 scan(TOK_EQUAL, &tok); 377 scan_num(&tok); 378 defp->def.pr.prog_num = tok.str; 379 *vtailp = NULL; 380 } 381 382 383 static 384 def_enum(defp) 385 definition *defp; 386 { 387 token tok; 388 enumval_list *elist; 389 enumval_list **tailp; 390 391 defp->def_kind = DEF_ENUM; 392 scan(TOK_IDENT, &tok); 393 defp->def_name = tok.str; 394 scan(TOK_LBRACE, &tok); 395 tailp = &defp->def.en.vals; 396 do { 397 scan(TOK_IDENT, &tok); 398 elist = ALLOC(enumval_list); 399 elist->name = tok.str; 400 elist->assignment = NULL; 401 scan3(TOK_COMMA, TOK_RBRACE, TOK_EQUAL, &tok); 402 if (tok.kind == TOK_EQUAL) { 403 scan_num(&tok); 404 elist->assignment = tok.str; 405 scan2(TOK_COMMA, TOK_RBRACE, &tok); 406 } 407 *tailp = elist; 408 tailp = &elist->next; 409 } while (tok.kind != TOK_RBRACE); 410 *tailp = NULL; 411 } 412 413 static 414 def_const(defp) 415 definition *defp; 416 { 417 token tok; 418 419 defp->def_kind = DEF_CONST; 420 scan(TOK_IDENT, &tok); 421 defp->def_name = tok.str; 422 scan(TOK_EQUAL, &tok); 423 scan2(TOK_IDENT, TOK_STRCONST, &tok); 424 defp->def.co = tok.str; 425 } 426 427 static 428 def_union(defp) 429 definition *defp; 430 { 431 token tok; 432 declaration dec; 433 case_list *cases, *tcase; 434 case_list **tailp; 435 int flag; 436 437 defp->def_kind = DEF_UNION; 438 scan(TOK_IDENT, &tok); 439 defp->def_name = tok.str; 440 scan(TOK_SWITCH, &tok); 441 scan(TOK_LPAREN, &tok); 442 get_declaration(&dec, DEF_UNION); 443 defp->def.un.enum_decl = dec; 444 tailp = &defp->def.un.cases; 445 scan(TOK_RPAREN, &tok); 446 scan(TOK_LBRACE, &tok); 447 scan(TOK_CASE, &tok); 448 while (tok.kind == TOK_CASE) { 449 scan2(TOK_IDENT, TOK_CHARCONST, &tok); 450 cases = ALLOC(case_list); 451 cases->case_name = tok.str; 452 scan(TOK_COLON, &tok); 453 /* now peek at next token */ 454 flag = 0; 455 if (peekscan(TOK_CASE, &tok)) { 456 do { 457 scan2(TOK_IDENT, TOK_CHARCONST, &tok); 458 cases->contflag = 1; 459 /* continued case statement */ 460 *tailp = cases; 461 tailp = &cases->next; 462 cases = ALLOC(case_list); 463 cases->case_name = tok.str; 464 scan(TOK_COLON, &tok); 465 } while (peekscan(TOK_CASE, &tok)); 466 } 467 else 468 if (flag) 469 { 470 471 *tailp = cases; 472 tailp = &cases->next; 473 cases = ALLOC(case_list); 474 }; 475 476 get_declaration(&dec, DEF_UNION); 477 cases->case_decl = dec; 478 cases->contflag = 0; /* no continued case statement */ 479 *tailp = cases; 480 tailp = &cases->next; 481 scan(TOK_SEMICOLON, &tok); 482 483 scan3(TOK_CASE, TOK_DEFAULT, TOK_RBRACE, &tok); 484 } 485 *tailp = NULL; 486 if (tok.kind == TOK_DEFAULT) { 487 scan(TOK_COLON, &tok); 488 get_declaration(&dec, DEF_UNION); 489 defp->def.un.default_decl = ALLOC(declaration); 490 *defp->def.un.default_decl = dec; 491 scan(TOK_SEMICOLON, &tok); 492 scan(TOK_RBRACE, &tok); 493 } else { 494 defp->def.un.default_decl = NULL; 495 } 496 } 497 498 static char *reserved_words[] = 499 { 500 "array", 501 "bytes", 502 "destroy", 503 "free", 504 "getpos", 505 "inline", 506 "pointer", 507 "reference", 508 "setpos", 509 "sizeof", 510 "union", 511 "vector", 512 NULL 513 }; 514 515 static char *reserved_types[] = 516 { 517 "opaque", 518 "string", 519 NULL 520 }; 521 522 /* 523 * check that the given name is not one that would eventually result in 524 * xdr routines that would conflict with internal XDR routines. 525 */ 526 static check_type_name(name, new_type) 527 int new_type; 528 char *name; 529 { 530 int i; 531 char tmp[100]; 532 533 for (i = 0; reserved_words[i] != NULL; i++) { 534 if (strcmp(name, reserved_words[i]) == 0) { 535 snprintf(tmp, sizeof (tmp), 536 "illegal (reserved) name :\'%s\' " 537 "in type definition", 538 name); 539 error(tmp); 540 } 541 } 542 if (new_type) { 543 for (i = 0; reserved_types[i] != NULL; i++) { 544 if (strcmp(name, reserved_types[i]) == 0) { 545 snprintf(tmp, sizeof (tmp), 546 "illegal (reserved) name :\'%s\' " 547 "in type definition", 548 name); 549 error(tmp); 550 } 551 } 552 } 553 } 554 555 556 557 static 558 def_typedef(defp) 559 definition *defp; 560 { 561 declaration dec; 562 563 defp->def_kind = DEF_TYPEDEF; 564 get_declaration(&dec, DEF_TYPEDEF); 565 defp->def_name = dec.name; 566 check_type_name(dec.name, 1); 567 defp->def.ty.old_prefix = dec.prefix; 568 defp->def.ty.old_type = dec.type; 569 defp->def.ty.rel = dec.rel; 570 defp->def.ty.array_max = dec.array_max; 571 } 572 573 static 574 get_declaration(dec, dkind) 575 declaration *dec; 576 defkind dkind; 577 { 578 token tok; 579 580 get_type(&dec->prefix, &dec->type, dkind); 581 dec->rel = REL_ALIAS; 582 if (streq(dec->type, "void")) { 583 return; 584 } 585 586 check_type_name(dec->type, 0); 587 scan2(TOK_STAR, TOK_IDENT, &tok); 588 if (tok.kind == TOK_STAR) { 589 dec->rel = REL_POINTER; 590 scan(TOK_IDENT, &tok); 591 } 592 dec->name = tok.str; 593 if (peekscan(TOK_LBRACKET, &tok)) { 594 if (dec->rel == REL_POINTER) { 595 error("no array-of-pointer declarations " 596 "-- use typedef"); 597 } 598 dec->rel = REL_VECTOR; 599 scan_num(&tok); 600 dec->array_max = tok.str; 601 scan(TOK_RBRACKET, &tok); 602 } else if (peekscan(TOK_LANGLE, &tok)) { 603 if (dec->rel == REL_POINTER) { 604 error("no array-of-pointer declarations " 605 "-- use typedef"); 606 } 607 dec->rel = REL_ARRAY; 608 if (peekscan(TOK_RANGLE, &tok)) { 609 dec->array_max = "~0"; /* unspecified size, use max */ 610 } else { 611 scan_num(&tok); 612 dec->array_max = tok.str; 613 scan(TOK_RANGLE, &tok); 614 } 615 } 616 if (streq(dec->type, "opaque")) { 617 if (dec->rel != REL_ARRAY && dec->rel != REL_VECTOR) { 618 error("array declaration expected"); 619 } 620 } else if (streq(dec->type, "string")) { 621 if (dec->rel != REL_ARRAY) { 622 error("variable-length array declaration expected"); 623 } 624 } 625 } 626 627 628 static 629 get_prog_declaration(dec, dkind, num) 630 declaration *dec; 631 defkind dkind; 632 int num; /* arg number */ 633 { 634 token tok; 635 char name[sizeof (ARGNAME) + 10]; 636 637 if (dkind == DEF_PROGRAM) { 638 peek(&tok); 639 if (tok.kind == TOK_RPAREN) { /* no arguments */ 640 dec->rel = REL_ALIAS; 641 dec->type = "void"; 642 dec->prefix = NULL; 643 dec->name = NULL; 644 return; 645 } 646 } 647 get_type(&dec->prefix, &dec->type, dkind); 648 dec->rel = REL_ALIAS; 649 if (peekscan(TOK_IDENT, &tok)) /* optional name of argument */ 650 dec->name = strdup(tok.str); 651 else { 652 /* default name of argument */ 653 snprintf(name, sizeof (name), "%s%d", ARGNAME, num); 654 dec->name = strdup(name); 655 } 656 if (dec->name == NULL) 657 error("internal error -- out of memory"); 658 659 if (streq(dec->type, "void")) { 660 return; 661 } 662 663 if (streq(dec->type, "opaque")) { 664 error("opaque -- illegal argument type"); 665 } 666 if (peekscan(TOK_STAR, &tok)) { 667 if (streq(dec->type, "string")) { 668 error("pointer to string not allowed " 669 "in program arguments\n"); 670 } 671 dec->rel = REL_POINTER; 672 if (peekscan(TOK_IDENT, &tok)) 673 /* optional name of argument */ 674 dec->name = strdup(tok.str); 675 } 676 if (peekscan(TOK_LANGLE, &tok)) { 677 if (!streq(dec->type, "string")) { 678 error("arrays cannot be declared as arguments " 679 "to procedures -- use typedef"); 680 } 681 dec->rel = REL_ARRAY; 682 if (peekscan(TOK_RANGLE, &tok)) { 683 dec->array_max = "~0"; 684 /* unspecified size, use max */ 685 } else { 686 scan_num(&tok); 687 dec->array_max = tok.str; 688 scan(TOK_RANGLE, &tok); 689 } 690 } 691 if (streq(dec->type, "string")) { 692 if (dec->rel != REL_ARRAY) { 693 /* 694 * .x specifies just string as 695 * type of argument 696 * - make it string<> 697 */ 698 dec->rel = REL_ARRAY; 699 dec->array_max = "~0"; /* unspecified size, use max */ 700 } 701 } 702 } 703 704 705 706 static 707 get_type(prefixp, typep, dkind) 708 char **prefixp; 709 char **typep; 710 defkind dkind; 711 { 712 token tok; 713 714 *prefixp = NULL; 715 get_token(&tok); 716 switch (tok.kind) { 717 case TOK_IDENT: 718 *typep = tok.str; 719 break; 720 case TOK_STRUCT: 721 case TOK_ENUM: 722 case TOK_UNION: 723 *prefixp = tok.str; 724 scan(TOK_IDENT, &tok); 725 *typep = tok.str; 726 break; 727 case TOK_UNSIGNED: 728 unsigned_dec(typep); 729 break; 730 case TOK_SHORT: 731 *typep = "short"; 732 (void) peekscan(TOK_INT, &tok); 733 break; 734 case TOK_LONG: 735 *typep = "long"; 736 (void) peekscan(TOK_INT, &tok); 737 break; 738 case TOK_HYPER: 739 *typep = "longlong_t"; 740 (void) peekscan(TOK_INT, &tok); 741 break; 742 743 case TOK_VOID: 744 if (dkind != DEF_UNION && dkind != DEF_PROGRAM && 745 dkind != DEF_RESULT) { 746 error("voids allowed only inside union and " 747 "program definitions with one argument"); 748 } 749 *typep = tok.str; 750 break; 751 case TOK_ONEWAY: 752 if (dkind != DEF_RESULT) { 753 error("oneways allowed only inside result definitions"); 754 } 755 *typep = tok.str; 756 break; 757 case TOK_STRING: 758 case TOK_OPAQUE: 759 case TOK_CHAR: 760 case TOK_INT: 761 case TOK_FLOAT: 762 case TOK_DOUBLE: 763 case TOK_BOOL: 764 case TOK_QUAD: 765 *typep = tok.str; 766 break; 767 default: 768 error("expected type specifier"); 769 } 770 } 771 772 static 773 unsigned_dec(typep) 774 char **typep; 775 { 776 token tok; 777 778 peek(&tok); 779 switch (tok.kind) { 780 case TOK_CHAR: 781 get_token(&tok); 782 *typep = "u_char"; 783 break; 784 case TOK_SHORT: 785 get_token(&tok); 786 *typep = "u_short"; 787 (void) peekscan(TOK_INT, &tok); 788 break; 789 case TOK_LONG: 790 get_token(&tok); 791 *typep = "u_long"; 792 (void) peekscan(TOK_INT, &tok); 793 break; 794 case TOK_HYPER: 795 get_token(&tok); 796 *typep = "u_longlong_t"; 797 (void) peekscan(TOK_INT, &tok); 798 break; 799 case TOK_INT: 800 get_token(&tok); 801 *typep = "u_int"; 802 break; 803 default: 804 *typep = "u_int"; 805 break; 806 } 807 } 808