1 /* 2 * Sun RPC is a product of Sun Microsystems, Inc. and is provided for 3 * unrestricted use provided that this legend is included on all tape 4 * media and as a part of the software program in whole or part. Users 5 * may copy or modify Sun RPC without charge, but are not authorized 6 * to license or distribute it to anyone else except as part of a product or 7 * program developed by the user. 8 * 9 * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE 10 * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR 11 * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. 12 * 13 * Sun RPC is provided with no support and without any obligation on the 14 * part of Sun Microsystems, Inc. to assist in its use, correction, 15 * modification or enhancement. 16 * 17 * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE 18 * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC 19 * OR ANY PART THEREOF. 20 * 21 * In no event will Sun Microsystems, Inc. be liable for any lost revenue 22 * or profits or other special, indirect and consequential damages, even if 23 * Sun has been advised of the possibility of such damages. 24 * 25 * Sun Microsystems, Inc. 26 * 2550 Garcia Avenue 27 * Mountain View, California 94043 28 * 29 * @(#)rpc_parse.c 1.8 89/02/22 (C) 1987 SMI 30 */ 31 32 #ident "@(#)rpc_parse.c 1.12 93/07/05 SMI" 33 34 /* 35 * rpc_parse.c, Parser for the RPC protocol compiler 36 * Copyright (C) 1987 Sun Microsystems, Inc. 37 */ 38 #include <stdio.h> 39 #include <string.h> 40 #include "rpc/types.h" 41 #include "rpc_scan.h" 42 #include "rpc_parse.h" 43 #include "rpc_util.h" 44 45 #define ARGNAME "arg" 46 47 extern char *make_argname __P(( char *, char * )); 48 static void isdefined __P(( definition * )); 49 static void def_struct __P(( definition * )); 50 static void def_program __P(( definition * )); 51 static void def_enum __P(( definition * )); 52 static void def_const __P(( definition * )); 53 static void def_union __P(( definition * )); 54 static void def_typedef __P(( definition * )); 55 static void get_declaration __P(( declaration *, defkind )); 56 static void get_prog_declaration __P(( declaration *, defkind, int )); 57 static void get_type __P(( char **, char **, defkind )); 58 static void unsigned_dec __P(( char ** )); 59 60 #ifndef __FreeBSD__ 61 extern char *strdup(); 62 #endif 63 64 /* 65 * return the next definition you see 66 */ 67 definition * 68 get_definition() 69 { 70 definition *defp; 71 token tok; 72 73 defp = ALLOC(definition); 74 get_token(&tok); 75 switch (tok.kind) { 76 case TOK_STRUCT: 77 def_struct(defp); 78 break; 79 case TOK_UNION: 80 def_union(defp); 81 break; 82 case TOK_TYPEDEF: 83 def_typedef(defp); 84 break; 85 case TOK_ENUM: 86 def_enum(defp); 87 break; 88 case TOK_PROGRAM: 89 def_program(defp); 90 break; 91 case TOK_CONST: 92 def_const(defp); 93 break; 94 case TOK_EOF: 95 return (NULL); 96 default: 97 error("definition keyword expected"); 98 } 99 scan(TOK_SEMICOLON, &tok); 100 isdefined(defp); 101 return (defp); 102 } 103 104 static void 105 isdefined(defp) 106 definition *defp; 107 { 108 STOREVAL(&defined, defp); 109 } 110 111 static void 112 def_struct(defp) 113 definition *defp; 114 { 115 token tok; 116 declaration dec; 117 decl_list *decls; 118 decl_list **tailp; 119 120 defp->def_kind = DEF_STRUCT; 121 122 scan(TOK_IDENT, &tok); 123 defp->def_name = tok.str; 124 scan(TOK_LBRACE, &tok); 125 tailp = &defp->def.st.decls; 126 do { 127 get_declaration(&dec, DEF_STRUCT); 128 decls = ALLOC(decl_list); 129 decls->decl = dec; 130 *tailp = decls; 131 tailp = &decls->next; 132 scan(TOK_SEMICOLON, &tok); 133 peek(&tok); 134 } while (tok.kind != TOK_RBRACE); 135 get_token(&tok); 136 *tailp = NULL; 137 } 138 139 static void 140 def_program(defp) 141 definition *defp; 142 { 143 token tok; 144 declaration dec; 145 decl_list *decls; 146 decl_list **tailp; 147 version_list *vlist; 148 version_list **vtailp; 149 proc_list *plist; 150 proc_list **ptailp; 151 int num_args; 152 bool_t isvoid = FALSE; /* whether first argument is void */ 153 defp->def_kind = DEF_PROGRAM; 154 scan(TOK_IDENT, &tok); 155 defp->def_name = tok.str; 156 scan(TOK_LBRACE, &tok); 157 vtailp = &defp->def.pr.versions; 158 tailp = &defp->def.st.decls; 159 scan(TOK_VERSION, &tok); 160 do { 161 scan(TOK_IDENT, &tok); 162 vlist = ALLOC(version_list); 163 vlist->vers_name = tok.str; 164 scan(TOK_LBRACE, &tok); 165 ptailp = &vlist->procs; 166 do { 167 /* get result type */ 168 plist = ALLOC(proc_list); 169 get_type(&plist->res_prefix, &plist->res_type, 170 DEF_PROGRAM); 171 if (streq(plist->res_type, "opaque")) { 172 error("illegal result type"); 173 } 174 scan(TOK_IDENT, &tok); 175 plist->proc_name = tok.str; 176 scan(TOK_LPAREN, &tok); 177 /* get args - first one */ 178 num_args = 1; 179 isvoid = FALSE; 180 /* 181 * type of DEF_PROGRAM in the first 182 * get_prog_declaration and DEF_STURCT in the next 183 * allows void as argument if it is the only argument 184 */ 185 get_prog_declaration(&dec, DEF_PROGRAM, num_args); 186 if (streq(dec.type, "void")) 187 isvoid = TRUE; 188 decls = ALLOC(decl_list); 189 plist->args.decls = decls; 190 decls->decl = dec; 191 tailp = &decls->next; 192 /* get args */ 193 while (peekscan(TOK_COMMA, &tok)) { 194 num_args++; 195 get_prog_declaration(&dec, DEF_STRUCT, 196 num_args); 197 decls = ALLOC(decl_list); 198 decls->decl = dec; 199 *tailp = decls; 200 if (streq(dec.type, "void")) 201 isvoid = TRUE; 202 tailp = &decls->next; 203 } 204 /* multiple arguments are only allowed in newstyle */ 205 if (!newstyle && num_args > 1) { 206 error("only one argument is allowed"); 207 } 208 if (isvoid && num_args > 1) { 209 error("illegal use of void in program definition"); 210 } 211 *tailp = NULL; 212 scan(TOK_RPAREN, &tok); 213 scan(TOK_EQUAL, &tok); 214 scan_num(&tok); 215 scan(TOK_SEMICOLON, &tok); 216 plist->proc_num = tok.str; 217 plist->arg_num = num_args; 218 *ptailp = plist; 219 ptailp = &plist->next; 220 peek(&tok); 221 } while (tok.kind != TOK_RBRACE); 222 *ptailp = NULL; 223 *vtailp = vlist; 224 vtailp = &vlist->next; 225 scan(TOK_RBRACE, &tok); 226 scan(TOK_EQUAL, &tok); 227 scan_num(&tok); 228 vlist->vers_num = tok.str; 229 /* make the argument structure name for each arg */ 230 for (plist = vlist->procs; plist != NULL; 231 plist = plist->next) { 232 plist->args.argname = make_argname(plist->proc_name, 233 vlist->vers_num); 234 /* free the memory ?? */ 235 } 236 scan(TOK_SEMICOLON, &tok); 237 scan2(TOK_VERSION, TOK_RBRACE, &tok); 238 } while (tok.kind == TOK_VERSION); 239 scan(TOK_EQUAL, &tok); 240 scan_num(&tok); 241 defp->def.pr.prog_num = tok.str; 242 *vtailp = NULL; 243 } 244 245 246 static void 247 def_enum(defp) 248 definition *defp; 249 { 250 token tok; 251 enumval_list *elist; 252 enumval_list **tailp; 253 254 defp->def_kind = DEF_ENUM; 255 scan(TOK_IDENT, &tok); 256 defp->def_name = tok.str; 257 scan(TOK_LBRACE, &tok); 258 tailp = &defp->def.en.vals; 259 do { 260 scan(TOK_IDENT, &tok); 261 elist = ALLOC(enumval_list); 262 elist->name = tok.str; 263 elist->assignment = NULL; 264 scan3(TOK_COMMA, TOK_RBRACE, TOK_EQUAL, &tok); 265 if (tok.kind == TOK_EQUAL) { 266 scan_num(&tok); 267 elist->assignment = tok.str; 268 scan2(TOK_COMMA, TOK_RBRACE, &tok); 269 } 270 *tailp = elist; 271 tailp = &elist->next; 272 } while (tok.kind != TOK_RBRACE); 273 *tailp = NULL; 274 } 275 276 static void 277 def_const(defp) 278 definition *defp; 279 { 280 token tok; 281 282 defp->def_kind = DEF_CONST; 283 scan(TOK_IDENT, &tok); 284 defp->def_name = tok.str; 285 scan(TOK_EQUAL, &tok); 286 scan2(TOK_IDENT, TOK_STRCONST, &tok); 287 defp->def.co = tok.str; 288 } 289 290 static void 291 def_union(defp) 292 definition *defp; 293 { 294 token tok; 295 declaration dec; 296 case_list *cases; 297 case_list **tailp; 298 int flag; 299 300 defp->def_kind = DEF_UNION; 301 scan(TOK_IDENT, &tok); 302 defp->def_name = tok.str; 303 scan(TOK_SWITCH, &tok); 304 scan(TOK_LPAREN, &tok); 305 get_declaration(&dec, DEF_UNION); 306 defp->def.un.enum_decl = dec; 307 tailp = &defp->def.un.cases; 308 scan(TOK_RPAREN, &tok); 309 scan(TOK_LBRACE, &tok); 310 scan(TOK_CASE, &tok); 311 while (tok.kind == TOK_CASE) { 312 scan2(TOK_IDENT, TOK_CHARCONST, &tok); 313 cases = ALLOC(case_list); 314 cases->case_name = tok.str; 315 scan(TOK_COLON, &tok); 316 /* now peek at next token */ 317 flag = 0; 318 if (peekscan(TOK_CASE, &tok)){ 319 do { 320 scan2(TOK_IDENT, TOK_CHARCONST, &tok); 321 cases->contflag = 1; 322 /* continued case statement */ 323 *tailp = cases; 324 tailp = &cases->next; 325 cases = ALLOC(case_list); 326 cases->case_name = tok.str; 327 scan(TOK_COLON, &tok); 328 } while (peekscan(TOK_CASE, &tok)); 329 } 330 else 331 if (flag) 332 { 333 334 *tailp = cases; 335 tailp = &cases->next; 336 cases = ALLOC(case_list); 337 }; 338 339 get_declaration(&dec, DEF_UNION); 340 cases->case_decl = dec; 341 cases->contflag = 0; /* no continued case statement */ 342 *tailp = cases; 343 tailp = &cases->next; 344 scan(TOK_SEMICOLON, &tok); 345 346 scan3(TOK_CASE, TOK_DEFAULT, TOK_RBRACE, &tok); 347 } 348 *tailp = NULL; 349 if (tok.kind == TOK_DEFAULT) { 350 scan(TOK_COLON, &tok); 351 get_declaration(&dec, DEF_UNION); 352 defp->def.un.default_decl = ALLOC(declaration); 353 *defp->def.un.default_decl = dec; 354 scan(TOK_SEMICOLON, &tok); 355 scan(TOK_RBRACE, &tok); 356 } else { 357 defp->def.un.default_decl = NULL; 358 } 359 } 360 361 static char* reserved_words[] = 362 { 363 "array", 364 "bytes", 365 "destroy", 366 "free", 367 "getpos", 368 "inline", 369 "pointer", 370 "reference", 371 "setpos", 372 "sizeof", 373 "union", 374 "vector", 375 NULL 376 }; 377 378 static char* reserved_types[] = 379 { 380 "opaque", 381 "string", 382 NULL 383 }; 384 385 /* 386 * check that the given name is not one that would eventually result in 387 * xdr routines that would conflict with internal XDR routines. 388 */ 389 static void 390 check_type_name(name, new_type) 391 int new_type; 392 char* name; 393 { 394 int i; 395 char tmp[100]; 396 397 for (i = 0; reserved_words[i] != NULL; i++) { 398 if (strcmp(name, reserved_words[i]) == 0) { 399 sprintf(tmp, 400 "illegal (reserved) name :\'%s\' in type definition", 401 name); 402 error(tmp); 403 } 404 } 405 if (new_type) { 406 for (i = 0; reserved_types[i] != NULL; i++) { 407 if (strcmp(name, reserved_types[i]) == 0) { 408 sprintf(tmp, 409 "illegal (reserved) name :\'%s\' in type definition", 410 name); 411 error(tmp); 412 } 413 } 414 } 415 } 416 417 418 419 static void 420 def_typedef(defp) 421 definition *defp; 422 { 423 declaration dec; 424 425 defp->def_kind = DEF_TYPEDEF; 426 get_declaration(&dec, DEF_TYPEDEF); 427 defp->def_name = dec.name; 428 check_type_name(dec.name, 1); 429 defp->def.ty.old_prefix = dec.prefix; 430 defp->def.ty.old_type = dec.type; 431 defp->def.ty.rel = dec.rel; 432 defp->def.ty.array_max = dec.array_max; 433 } 434 435 static void 436 get_declaration(dec, dkind) 437 declaration *dec; 438 defkind dkind; 439 { 440 token tok; 441 442 get_type(&dec->prefix, &dec->type, dkind); 443 dec->rel = REL_ALIAS; 444 if (streq(dec->type, "void")) { 445 return; 446 } 447 448 check_type_name(dec->type, 0); 449 scan2(TOK_STAR, TOK_IDENT, &tok); 450 if (tok.kind == TOK_STAR) { 451 dec->rel = REL_POINTER; 452 scan(TOK_IDENT, &tok); 453 } 454 dec->name = tok.str; 455 if (peekscan(TOK_LBRACKET, &tok)) { 456 if (dec->rel == REL_POINTER) { 457 error("no array-of-pointer declarations -- use typedef"); 458 } 459 dec->rel = REL_VECTOR; 460 scan_num(&tok); 461 dec->array_max = tok.str; 462 scan(TOK_RBRACKET, &tok); 463 } else if (peekscan(TOK_LANGLE, &tok)) { 464 if (dec->rel == REL_POINTER) { 465 error("no array-of-pointer declarations -- use typedef"); 466 } 467 dec->rel = REL_ARRAY; 468 if (peekscan(TOK_RANGLE, &tok)) { 469 dec->array_max = "~0"; /* unspecified size, use max */ 470 } else { 471 scan_num(&tok); 472 dec->array_max = tok.str; 473 scan(TOK_RANGLE, &tok); 474 } 475 } 476 if (streq(dec->type, "opaque")) { 477 if (dec->rel != REL_ARRAY && dec->rel != REL_VECTOR) { 478 error("array declaration expected"); 479 } 480 } else if (streq(dec->type, "string")) { 481 if (dec->rel != REL_ARRAY) { 482 error("variable-length array declaration expected"); 483 } 484 } 485 } 486 487 488 static void 489 get_prog_declaration(dec, dkind, num) 490 declaration *dec; 491 defkind dkind; 492 int num; /* arg number */ 493 { 494 token tok; 495 char name[10]; /* argument name */ 496 497 if (dkind == DEF_PROGRAM) { 498 peek(&tok); 499 if (tok.kind == TOK_RPAREN) { /* no arguments */ 500 dec->rel = REL_ALIAS; 501 dec->type = "void"; 502 dec->prefix = NULL; 503 dec->name = NULL; 504 return; 505 } 506 } 507 get_type(&dec->prefix, &dec->type, dkind); 508 dec->rel = REL_ALIAS; 509 if (peekscan(TOK_IDENT, &tok)) /* optional name of argument */ 510 strcpy(name, tok.str); 511 else 512 sprintf(name, "%s%d", ARGNAME, num); 513 /* default name of argument */ 514 515 dec->name = (char *) strdup(name); 516 if (streq(dec->type, "void")) { 517 return; 518 } 519 520 if (streq(dec->type, "opaque")) { 521 error("opaque -- illegal argument type"); 522 } 523 if (peekscan(TOK_STAR, &tok)) { 524 if (streq(dec->type, "string")) { 525 error("pointer to string not allowed in program arguments\n"); 526 } 527 dec->rel = REL_POINTER; 528 if (peekscan(TOK_IDENT, &tok)) 529 /* optional name of argument */ 530 dec->name = strdup(tok.str); 531 } 532 if (peekscan(TOK_LANGLE, &tok)) { 533 if (!streq(dec->type, "string")) { 534 error("arrays cannot be declared as arguments to procedures -- use typedef"); 535 } 536 dec->rel = REL_ARRAY; 537 if (peekscan(TOK_RANGLE, &tok)) { 538 dec->array_max = "~0"; 539 /* unspecified size, use max */ 540 } else { 541 scan_num(&tok); 542 dec->array_max = tok.str; 543 scan(TOK_RANGLE, &tok); 544 } 545 } 546 if (streq(dec->type, "string")) { 547 if (dec->rel != REL_ARRAY) { 548 /* 549 * .x specifies just string as 550 * type of argument 551 * - make it string<> 552 */ 553 dec->rel = REL_ARRAY; 554 dec->array_max = "~0"; /* unspecified size, use max */ 555 } 556 } 557 } 558 559 560 561 static void 562 get_type(prefixp, typep, dkind) 563 char **prefixp; 564 char **typep; 565 defkind dkind; 566 { 567 token tok; 568 569 *prefixp = NULL; 570 get_token(&tok); 571 switch (tok.kind) { 572 case TOK_IDENT: 573 *typep = tok.str; 574 break; 575 case TOK_STRUCT: 576 case TOK_ENUM: 577 case TOK_UNION: 578 *prefixp = tok.str; 579 scan(TOK_IDENT, &tok); 580 *typep = tok.str; 581 break; 582 case TOK_UNSIGNED: 583 unsigned_dec(typep); 584 break; 585 case TOK_SHORT: 586 *typep = "short"; 587 (void) peekscan(TOK_INT, &tok); 588 break; 589 case TOK_LONG: 590 *typep = "long"; 591 (void) peekscan(TOK_INT, &tok); 592 break; 593 case TOK_HYPER: 594 *typep = "int64_t"; 595 (void) peekscan(TOK_INT, &tok); 596 break; 597 598 case TOK_VOID: 599 if (dkind != DEF_UNION && dkind != DEF_PROGRAM) { 600 error("voids allowed only inside union and program definitions with one argument"); 601 } 602 *typep = tok.str; 603 break; 604 case TOK_STRING: 605 case TOK_OPAQUE: 606 case TOK_CHAR: 607 case TOK_INT: 608 case TOK_FLOAT: 609 case TOK_DOUBLE: 610 case TOK_BOOL: 611 case TOK_QUAD: 612 *typep = tok.str; 613 break; 614 default: 615 error("expected type specifier"); 616 } 617 } 618 619 static void 620 unsigned_dec(typep) 621 char **typep; 622 { 623 token tok; 624 625 peek(&tok); 626 switch (tok.kind) { 627 case TOK_CHAR: 628 get_token(&tok); 629 *typep = "u_char"; 630 break; 631 case TOK_SHORT: 632 get_token(&tok); 633 *typep = "u_short"; 634 (void) peekscan(TOK_INT, &tok); 635 break; 636 case TOK_LONG: 637 get_token(&tok); 638 *typep = "u_long"; 639 (void) peekscan(TOK_INT, &tok); 640 break; 641 case TOK_HYPER: 642 get_token(&tok); 643 *typep = "u_int64_t"; 644 (void) peekscan(TOK_INT, &tok); 645 break; 646 case TOK_INT: 647 get_token(&tok); 648 *typep = "u_int"; 649 break; 650 default: 651 *typep = "u_int"; 652 break; 653 } 654 } 655