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