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