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 #ident "@(#)rpc_parse.c 1.12 93/07/05 SMI" 31 32 #ifndef lint 33 static char sccsid[] = "@(#)rpc_parse.c 1.8 89/02/22 (C) 1987 SMI"; 34 #endif 35 36 /* 37 * rpc_parse.c, Parser for the RPC protocol compiler 38 * Copyright (C) 1987 Sun Microsystems, Inc. 39 */ 40 #include <stdio.h> 41 #include <string.h> 42 #include "rpc/types.h" 43 #include "rpc_scan.h" 44 #include "rpc_parse.h" 45 #include "rpc_util.h" 46 47 #define ARGNAME "arg" 48 49 extern char *make_argname __P(( char *, char * )); 50 static int isdefined __P(( definition * )); 51 static int def_struct __P(( definition * )); 52 static int def_program __P(( definition * )); 53 static int def_enum __P(( definition * )); 54 static int def_const __P(( definition * )); 55 static int def_union __P(( definition * )); 56 static int def_typedef __P(( definition * )); 57 static int get_declaration __P(( declaration *, defkind )); 58 static int get_prog_declaration __P(( declaration *, defkind, int )); 59 static int get_type __P(( char **, char **, defkind )); 60 static int unsigned_dec __P(( char ** )); 61 62 #ifndef __FreeBSD__ 63 extern char *strdup(); 64 #endif 65 66 /* 67 * return the next definition you see 68 */ 69 definition * 70 get_definition() 71 { 72 definition *defp; 73 token tok; 74 75 defp = ALLOC(definition); 76 get_token(&tok); 77 switch (tok.kind) { 78 case TOK_STRUCT: 79 def_struct(defp); 80 break; 81 case TOK_UNION: 82 def_union(defp); 83 break; 84 case TOK_TYPEDEF: 85 def_typedef(defp); 86 break; 87 case TOK_ENUM: 88 def_enum(defp); 89 break; 90 case TOK_PROGRAM: 91 def_program(defp); 92 break; 93 case TOK_CONST: 94 def_const(defp); 95 break; 96 case TOK_EOF: 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 107 isdefined(defp) 108 definition *defp; 109 { 110 STOREVAL(&defined, defp); 111 } 112 113 static 114 def_struct(defp) 115 definition *defp; 116 { 117 token tok; 118 declaration dec; 119 decl_list *decls; 120 decl_list **tailp; 121 122 defp->def_kind = DEF_STRUCT; 123 124 scan(TOK_IDENT, &tok); 125 defp->def_name = tok.str; 126 scan(TOK_LBRACE, &tok); 127 tailp = &defp->def.st.decls; 128 do { 129 get_declaration(&dec, DEF_STRUCT); 130 decls = ALLOC(decl_list); 131 decls->decl = dec; 132 *tailp = decls; 133 tailp = &decls->next; 134 scan(TOK_SEMICOLON, &tok); 135 peek(&tok); 136 } while (tok.kind != TOK_RBRACE); 137 get_token(&tok); 138 *tailp = NULL; 139 } 140 141 static 142 def_program(defp) 143 definition *defp; 144 { 145 token tok; 146 declaration dec; 147 decl_list *decls; 148 decl_list **tailp; 149 version_list *vlist; 150 version_list **vtailp; 151 proc_list *plist; 152 proc_list **ptailp; 153 int num_args; 154 bool_t isvoid = FALSE; /* whether first argument is void */ 155 defp->def_kind = DEF_PROGRAM; 156 scan(TOK_IDENT, &tok); 157 defp->def_name = tok.str; 158 scan(TOK_LBRACE, &tok); 159 vtailp = &defp->def.pr.versions; 160 tailp = &defp->def.st.decls; 161 scan(TOK_VERSION, &tok); 162 do { 163 scan(TOK_IDENT, &tok); 164 vlist = ALLOC(version_list); 165 vlist->vers_name = tok.str; 166 scan(TOK_LBRACE, &tok); 167 ptailp = &vlist->procs; 168 do { 169 /* get result type */ 170 plist = ALLOC(proc_list); 171 get_type(&plist->res_prefix, &plist->res_type, 172 DEF_PROGRAM); 173 if (streq(plist->res_type, "opaque")) { 174 error("illegal result type"); 175 } 176 scan(TOK_IDENT, &tok); 177 plist->proc_name = tok.str; 178 scan(TOK_LPAREN, &tok); 179 /* get args - first one */ 180 num_args = 1; 181 isvoid = FALSE; 182 /* 183 * type of DEF_PROGRAM in the first 184 * get_prog_declaration and DEF_STURCT in the next 185 * allows void as argument if it is the only argument 186 */ 187 get_prog_declaration(&dec, DEF_PROGRAM, num_args); 188 if (streq(dec.type, "void")) 189 isvoid = TRUE; 190 decls = ALLOC(decl_list); 191 plist->args.decls = decls; 192 decls->decl = dec; 193 tailp = &decls->next; 194 /* get args */ 195 while (peekscan(TOK_COMMA, &tok)) { 196 num_args++; 197 get_prog_declaration(&dec, DEF_STRUCT, 198 num_args); 199 decls = ALLOC(decl_list); 200 decls->decl = dec; 201 *tailp = decls; 202 if (streq(dec.type, "void")) 203 isvoid = TRUE; 204 tailp = &decls->next; 205 } 206 /* multiple arguments are only allowed in newstyle */ 207 if (!newstyle && num_args > 1) { 208 error("only one argument is allowed"); 209 } 210 if (isvoid && num_args > 1) { 211 error("illegal use of void in program definition"); 212 } 213 *tailp = NULL; 214 scan(TOK_RPAREN, &tok); 215 scan(TOK_EQUAL, &tok); 216 scan_num(&tok); 217 scan(TOK_SEMICOLON, &tok); 218 plist->proc_num = tok.str; 219 plist->arg_num = num_args; 220 *ptailp = plist; 221 ptailp = &plist->next; 222 peek(&tok); 223 } while (tok.kind != TOK_RBRACE); 224 *ptailp = NULL; 225 *vtailp = vlist; 226 vtailp = &vlist->next; 227 scan(TOK_RBRACE, &tok); 228 scan(TOK_EQUAL, &tok); 229 scan_num(&tok); 230 vlist->vers_num = tok.str; 231 /* make the argument structure name for each arg */ 232 for (plist = vlist->procs; plist != NULL; 233 plist = plist->next) { 234 plist->args.argname = make_argname(plist->proc_name, 235 vlist->vers_num); 236 /* free the memory ?? */ 237 } 238 scan(TOK_SEMICOLON, &tok); 239 scan2(TOK_VERSION, TOK_RBRACE, &tok); 240 } while (tok.kind == TOK_VERSION); 241 scan(TOK_EQUAL, &tok); 242 scan_num(&tok); 243 defp->def.pr.prog_num = tok.str; 244 *vtailp = NULL; 245 } 246 247 248 static 249 def_enum(defp) 250 definition *defp; 251 { 252 token tok; 253 enumval_list *elist; 254 enumval_list **tailp; 255 256 defp->def_kind = DEF_ENUM; 257 scan(TOK_IDENT, &tok); 258 defp->def_name = tok.str; 259 scan(TOK_LBRACE, &tok); 260 tailp = &defp->def.en.vals; 261 do { 262 scan(TOK_IDENT, &tok); 263 elist = ALLOC(enumval_list); 264 elist->name = tok.str; 265 elist->assignment = NULL; 266 scan3(TOK_COMMA, TOK_RBRACE, TOK_EQUAL, &tok); 267 if (tok.kind == TOK_EQUAL) { 268 scan_num(&tok); 269 elist->assignment = tok.str; 270 scan2(TOK_COMMA, TOK_RBRACE, &tok); 271 } 272 *tailp = elist; 273 tailp = &elist->next; 274 } while (tok.kind != TOK_RBRACE); 275 *tailp = NULL; 276 } 277 278 static 279 def_const(defp) 280 definition *defp; 281 { 282 token tok; 283 284 defp->def_kind = DEF_CONST; 285 scan(TOK_IDENT, &tok); 286 defp->def_name = tok.str; 287 scan(TOK_EQUAL, &tok); 288 scan2(TOK_IDENT, TOK_STRCONST, &tok); 289 defp->def.co = tok.str; 290 } 291 292 static 293 def_union(defp) 294 definition *defp; 295 { 296 token tok; 297 declaration dec; 298 case_list *cases, *tcase; 299 case_list **tailp; 300 int flag; 301 302 defp->def_kind = DEF_UNION; 303 scan(TOK_IDENT, &tok); 304 defp->def_name = tok.str; 305 scan(TOK_SWITCH, &tok); 306 scan(TOK_LPAREN, &tok); 307 get_declaration(&dec, DEF_UNION); 308 defp->def.un.enum_decl = dec; 309 tailp = &defp->def.un.cases; 310 scan(TOK_RPAREN, &tok); 311 scan(TOK_LBRACE, &tok); 312 scan(TOK_CASE, &tok); 313 while (tok.kind == TOK_CASE) { 314 scan2(TOK_IDENT, TOK_CHARCONST, &tok); 315 cases = ALLOC(case_list); 316 cases->case_name = tok.str; 317 scan(TOK_COLON, &tok); 318 /* now peek at next token */ 319 flag = 0; 320 if (peekscan(TOK_CASE, &tok)){ 321 do { 322 scan2(TOK_IDENT, TOK_CHARCONST, &tok); 323 cases->contflag = 1; 324 /* continued case statement */ 325 *tailp = cases; 326 tailp = &cases->next; 327 cases = ALLOC(case_list); 328 cases->case_name = tok.str; 329 scan(TOK_COLON, &tok); 330 } while (peekscan(TOK_CASE, &tok)); 331 } 332 else 333 if (flag) 334 { 335 336 *tailp = cases; 337 tailp = &cases->next; 338 cases = ALLOC(case_list); 339 }; 340 341 get_declaration(&dec, DEF_UNION); 342 cases->case_decl = dec; 343 cases->contflag = 0; /* no continued case statement */ 344 *tailp = cases; 345 tailp = &cases->next; 346 scan(TOK_SEMICOLON, &tok); 347 348 scan3(TOK_CASE, TOK_DEFAULT, TOK_RBRACE, &tok); 349 } 350 *tailp = NULL; 351 if (tok.kind == TOK_DEFAULT) { 352 scan(TOK_COLON, &tok); 353 get_declaration(&dec, DEF_UNION); 354 defp->def.un.default_decl = ALLOC(declaration); 355 *defp->def.un.default_decl = dec; 356 scan(TOK_SEMICOLON, &tok); 357 scan(TOK_RBRACE, &tok); 358 } else { 359 defp->def.un.default_decl = NULL; 360 } 361 } 362 363 static char* reserved_words[] = 364 { 365 "array", 366 "bytes", 367 "destroy", 368 "free", 369 "getpos", 370 "inline", 371 "pointer", 372 "reference", 373 "setpos", 374 "sizeof", 375 "union", 376 "vector", 377 NULL 378 }; 379 380 static char* reserved_types[] = 381 { 382 "opaque", 383 "string", 384 NULL 385 }; 386 387 /* 388 * check that the given name is not one that would eventually result in 389 * xdr routines that would conflict with internal XDR routines. 390 */ 391 static 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 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 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 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 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 = "longlong_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 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 = "ulonglong_t"; 645 (void) peekscan(TOK_INT, &tok); 646 break; 647 case TOK_INT: 648 get_token(&tok); 649 *typep = "u_int"; 650 break; 651 default: 652 *typep = "u_int"; 653 break; 654 } 655 } 656