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