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