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 294 defp->def_kind = DEF_UNION; 295 scan(TOK_IDENT, &tok); 296 defp->def_name = tok.str; 297 scan(TOK_SWITCH, &tok); 298 scan(TOK_LPAREN, &tok); 299 get_declaration(&dec, DEF_UNION); 300 defp->def.un.enum_decl = dec; 301 tailp = &defp->def.un.cases; 302 scan(TOK_RPAREN, &tok); 303 scan(TOK_LBRACE, &tok); 304 scan(TOK_CASE, &tok); 305 while (tok.kind == TOK_CASE) { 306 scan2(TOK_IDENT, TOK_CHARCONST, &tok); 307 cases = XALLOC(case_list); 308 cases->case_name = tok.str; 309 scan(TOK_COLON, &tok); 310 /* now peek at next token */ 311 if (peekscan(TOK_CASE, &tok)){ 312 do { 313 scan2(TOK_IDENT, TOK_CHARCONST, &tok); 314 cases->contflag = 1; 315 /* continued case statement */ 316 *tailp = cases; 317 tailp = &cases->next; 318 cases = XALLOC(case_list); 319 cases->case_name = tok.str; 320 scan(TOK_COLON, &tok); 321 } while (peekscan(TOK_CASE, &tok)); 322 } 323 324 get_declaration(&dec, DEF_UNION); 325 cases->case_decl = dec; 326 cases->contflag = 0; /* no continued case statement */ 327 *tailp = cases; 328 tailp = &cases->next; 329 scan(TOK_SEMICOLON, &tok); 330 331 scan3(TOK_CASE, TOK_DEFAULT, TOK_RBRACE, &tok); 332 } 333 *tailp = NULL; 334 if (tok.kind == TOK_DEFAULT) { 335 scan(TOK_COLON, &tok); 336 get_declaration(&dec, DEF_UNION); 337 defp->def.un.default_decl = XALLOC(declaration); 338 *defp->def.un.default_decl = dec; 339 scan(TOK_SEMICOLON, &tok); 340 scan(TOK_RBRACE, &tok); 341 } else { 342 defp->def.un.default_decl = NULL; 343 } 344 } 345 346 static const char *reserved_words[] = 347 { 348 "array", 349 "bytes", 350 "destroy", 351 "free", 352 "getpos", 353 "inline", 354 "pointer", 355 "reference", 356 "setpos", 357 "sizeof", 358 "union", 359 "vector", 360 NULL 361 }; 362 363 static const char *reserved_types[] = 364 { 365 "opaque", 366 "string", 367 NULL 368 }; 369 370 /* 371 * check that the given name is not one that would eventually result in 372 * xdr routines that would conflict with internal XDR routines. 373 */ 374 static void 375 check_type_name(const char *name, int new_type) 376 { 377 int i; 378 char tmp[100]; 379 380 for (i = 0; reserved_words[i] != NULL; i++) { 381 if (strcmp(name, reserved_words[i]) == 0) { 382 sprintf(tmp, 383 "illegal (reserved) name :\'%s\' in type definition", 384 name); 385 error(tmp); 386 } 387 } 388 if (new_type) { 389 for (i = 0; reserved_types[i] != NULL; i++) { 390 if (strcmp(name, reserved_types[i]) == 0) { 391 sprintf(tmp, 392 "illegal (reserved) name :\'%s\' in type definition", 393 name); 394 error(tmp); 395 } 396 } 397 } 398 } 399 400 401 402 static void 403 def_typedef(definition *defp) 404 { 405 declaration dec; 406 407 defp->def_kind = DEF_TYPEDEF; 408 get_declaration(&dec, DEF_TYPEDEF); 409 defp->def_name = dec.name; 410 check_type_name(dec.name, 1); 411 defp->def.ty.old_prefix = dec.prefix; 412 defp->def.ty.old_type = dec.type; 413 defp->def.ty.rel = dec.rel; 414 defp->def.ty.array_max = dec.array_max; 415 } 416 417 static void 418 get_declaration(declaration *dec, defkind dkind) 419 { 420 token tok; 421 422 get_type(&dec->prefix, &dec->type, dkind); 423 dec->rel = REL_ALIAS; 424 if (streq(dec->type, "void")) { 425 return; 426 } 427 428 check_type_name(dec->type, 0); 429 scan2(TOK_STAR, TOK_IDENT, &tok); 430 if (tok.kind == TOK_STAR) { 431 dec->rel = REL_POINTER; 432 scan(TOK_IDENT, &tok); 433 } 434 dec->name = tok.str; 435 if (peekscan(TOK_LBRACKET, &tok)) { 436 if (dec->rel == REL_POINTER) { 437 error("no array-of-pointer declarations -- use typedef"); 438 } 439 dec->rel = REL_VECTOR; 440 scan_num(&tok); 441 dec->array_max = tok.str; 442 scan(TOK_RBRACKET, &tok); 443 } else if (peekscan(TOK_LANGLE, &tok)) { 444 if (dec->rel == REL_POINTER) { 445 error("no array-of-pointer declarations -- use typedef"); 446 } 447 dec->rel = REL_ARRAY; 448 if (peekscan(TOK_RANGLE, &tok)) { 449 dec->array_max = "~0"; /* unspecified size, use max */ 450 } else { 451 scan_num(&tok); 452 dec->array_max = tok.str; 453 scan(TOK_RANGLE, &tok); 454 } 455 } 456 if (streq(dec->type, "opaque")) { 457 if (dec->rel != REL_ARRAY && dec->rel != REL_VECTOR) { 458 error("array declaration expected"); 459 } 460 } else if (streq(dec->type, "string")) { 461 if (dec->rel != REL_ARRAY) { 462 error("variable-length array declaration expected"); 463 } 464 } 465 } 466 467 468 static void 469 get_prog_declaration(declaration *dec, defkind dkind, int num) 470 { 471 token tok; 472 char name[10]; /* argument name */ 473 474 if (dkind == DEF_PROGRAM) { 475 peek(&tok); 476 if (tok.kind == TOK_RPAREN) { /* no arguments */ 477 dec->rel = REL_ALIAS; 478 dec->type = "void"; 479 dec->prefix = NULL; 480 dec->name = NULL; 481 return; 482 } 483 } 484 get_type(&dec->prefix, &dec->type, dkind); 485 dec->rel = REL_ALIAS; 486 if (peekscan(TOK_IDENT, &tok)) /* optional name of argument */ 487 strcpy(name, tok.str); 488 else 489 sprintf(name, "%s%d", ARGNAME, num); 490 /* default name of argument */ 491 492 dec->name = (char *) xstrdup(name); 493 if (streq(dec->type, "void")) { 494 return; 495 } 496 497 if (streq(dec->type, "opaque")) { 498 error("opaque -- illegal argument type"); 499 } 500 if (peekscan(TOK_STAR, &tok)) { 501 if (streq(dec->type, "string")) { 502 error("pointer to string not allowed in program arguments"); 503 } 504 dec->rel = REL_POINTER; 505 if (peekscan(TOK_IDENT, &tok)) { 506 /* optional name of argument */ 507 dec->name = xstrdup(tok.str); 508 } 509 } 510 if (peekscan(TOK_LANGLE, &tok)) { 511 if (!streq(dec->type, "string")) { 512 error("arrays cannot be declared as arguments to procedures -- use typedef"); 513 } 514 dec->rel = REL_ARRAY; 515 if (peekscan(TOK_RANGLE, &tok)) { 516 dec->array_max = "~0"; 517 /* unspecified size, use max */ 518 } else { 519 scan_num(&tok); 520 dec->array_max = tok.str; 521 scan(TOK_RANGLE, &tok); 522 } 523 } 524 if (streq(dec->type, "string")) { 525 if (dec->rel != REL_ARRAY) { 526 /* 527 * .x specifies just string as 528 * type of argument 529 * - make it string<> 530 */ 531 dec->rel = REL_ARRAY; 532 dec->array_max = "~0"; /* unspecified size, use max */ 533 } 534 } 535 } 536 537 538 539 static void 540 get_type(const char **prefixp, const char **typep, defkind dkind) 541 { 542 token tok; 543 544 *prefixp = NULL; 545 get_token(&tok); 546 switch (tok.kind) { 547 case TOK_IDENT: 548 *typep = tok.str; 549 break; 550 case TOK_STRUCT: 551 case TOK_ENUM: 552 case TOK_UNION: 553 *prefixp = tok.str; 554 scan(TOK_IDENT, &tok); 555 *typep = tok.str; 556 break; 557 case TOK_UNSIGNED: 558 unsigned_dec(typep); 559 break; 560 case TOK_SHORT: 561 *typep = "short"; 562 (void) peekscan(TOK_INT, &tok); 563 break; 564 case TOK_LONG: 565 *typep = "long"; 566 (void) peekscan(TOK_INT, &tok); 567 break; 568 case TOK_HYPER: 569 *typep = "int64_t"; 570 (void) peekscan(TOK_INT, &tok); 571 break; 572 573 case TOK_VOID: 574 if (dkind != DEF_UNION && dkind != DEF_PROGRAM) { 575 error("voids allowed only inside union and program definitions with one argument"); 576 } 577 *typep = tok.str; 578 break; 579 case TOK_STRING: 580 case TOK_OPAQUE: 581 case TOK_CHAR: 582 case TOK_INT: 583 case TOK_FLOAT: 584 case TOK_DOUBLE: 585 case TOK_BOOL: 586 case TOK_QUAD: 587 *typep = tok.str; 588 break; 589 default: 590 error("expected type specifier"); 591 } 592 } 593 594 static void 595 unsigned_dec(const char **typep) 596 { 597 token tok; 598 599 peek(&tok); 600 switch (tok.kind) { 601 case TOK_CHAR: 602 get_token(&tok); 603 *typep = "u_char"; 604 break; 605 case TOK_SHORT: 606 get_token(&tok); 607 *typep = "u_short"; 608 (void) peekscan(TOK_INT, &tok); 609 break; 610 case TOK_LONG: 611 get_token(&tok); 612 *typep = "u_long"; 613 (void) peekscan(TOK_INT, &tok); 614 break; 615 case TOK_HYPER: 616 get_token(&tok); 617 *typep = "u_int64_t"; 618 619 (void) peekscan(TOK_INT, &tok); 620 break; 621 case TOK_INT: 622 get_token(&tok); 623 *typep = "u_int"; 624 break; 625 default: 626 *typep = "u_int"; 627 break; 628 } 629 } 630