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