1 /* $OpenBSD: rpc_parse.c,v 1.11 2002/07/05 05:39:42 deraadt Exp $ */ 2 /* $NetBSD: rpc_parse.c,v 1.5 1995/08/29 23:05:55 cgd Exp $ */ 3 /* 4 * Sun RPC is a product of Sun Microsystems, Inc. and is provided for 5 * unrestricted use provided that this legend is included on all tape 6 * media and as a part of the software program in whole or part. Users 7 * may copy or modify Sun RPC without charge, but are not authorized 8 * to license or distribute it to anyone else except as part of a product or 9 * program developed by the user or with the express written consent of 10 * Sun Microsystems, Inc. 11 * 12 * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE 13 * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR 14 * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. 15 * 16 * Sun RPC is provided with no support and without any obligation on the 17 * part of Sun Microsystems, Inc. to assist in its use, correction, 18 * modification or enhancement. 19 * 20 * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE 21 * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC 22 * OR ANY PART THEREOF. 23 * 24 * In no event will Sun Microsystems, Inc. be liable for any lost revenue 25 * or profits or other special, indirect and consequential damages, even if 26 * Sun has been advised of the possibility of such damages. 27 * 28 * Sun Microsystems, Inc. 29 * 2550 Garcia Avenue 30 * Mountain View, California 94043 31 */ 32 33 #ifndef lint 34 static char sccsid[] = "@(#)rpc_parse.c 1.8 89/02/22 (C) 1987 SMI"; 35 #endif 36 37 /* 38 * rpc_parse.c, Parser for the RPC protocol compiler 39 * Copyright (C) 1987 Sun Microsystems, Inc. 40 */ 41 #include <stdio.h> 42 #include <stdlib.h> 43 #include <string.h> 44 #include "rpc/types.h" 45 #include "rpc_scan.h" 46 #include "rpc_parse.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(char **, char **, defkind); 61 static void unsigned_dec(char **); 62 63 /* 64 * return the next definition you see 65 */ 66 definition * 67 get_definition() 68 { 69 definition *defp; 70 token tok; 71 72 defp = ALLOC(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 return (NULL); 95 default: 96 error("definition keyword expected"); 97 } 98 scan(TOK_SEMICOLON, &tok); 99 isdefined(defp); 100 return (defp); 101 } 102 103 static void 104 isdefined(defp) 105 definition *defp; 106 { 107 STOREVAL(&defined, defp); 108 } 109 110 static void 111 def_struct(defp) 112 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 = ALLOC(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(defp) 140 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 = ALLOC(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 = ALLOC(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 /* 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 = ALLOC(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 = ALLOC(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(defp) 246 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 = ALLOC(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(defp) 276 definition *defp; 277 { 278 token tok; 279 280 defp->def_kind = DEF_CONST; 281 scan(TOK_IDENT, &tok); 282 defp->def_name = tok.str; 283 scan(TOK_EQUAL, &tok); 284 scan2(TOK_IDENT, TOK_STRCONST, &tok); 285 defp->def.co = tok.str; 286 } 287 288 static void 289 def_union(defp) 290 definition *defp; 291 { 292 token tok; 293 declaration dec; 294 case_list *cases; 295 case_list **tailp; 296 int flag; 297 298 defp->def_kind = DEF_UNION; 299 scan(TOK_IDENT, &tok); 300 defp->def_name = tok.str; 301 scan(TOK_SWITCH, &tok); 302 scan(TOK_LPAREN, &tok); 303 get_declaration(&dec, DEF_UNION); 304 defp->def.un.enum_decl = dec; 305 tailp = &defp->def.un.cases; 306 scan(TOK_RPAREN, &tok); 307 scan(TOK_LBRACE, &tok); 308 scan(TOK_CASE, &tok); 309 while (tok.kind == TOK_CASE) { 310 scan2(TOK_IDENT, TOK_CHARCONST, &tok); 311 cases = ALLOC(case_list); 312 cases->case_name = tok.str; 313 scan(TOK_COLON, &tok); 314 /* now peek at next token */ 315 flag=0; 316 if (peekscan(TOK_CASE,&tok)) { 317 do { 318 scan2(TOK_IDENT, TOK_CHARCONST, &tok); 319 cases->contflag=1; /* continued case statement */ 320 *tailp = cases; 321 tailp = &cases->next; 322 cases = ALLOC(case_list); 323 cases->case_name = tok.str; 324 scan(TOK_COLON, &tok); 325 } while (peekscan(TOK_CASE,&tok)); 326 } else if (flag) { 327 *tailp = cases; 328 tailp = &cases->next; 329 cases = ALLOC(case_list); 330 } 331 get_declaration(&dec, DEF_UNION); 332 cases->case_decl = dec; 333 cases->contflag=0; /* no continued case statement */ 334 *tailp = cases; 335 tailp = &cases->next; 336 scan(TOK_SEMICOLON, &tok); 337 338 scan3(TOK_CASE, TOK_DEFAULT, TOK_RBRACE, &tok); 339 } 340 *tailp = NULL; 341 342 if (tok.kind == TOK_DEFAULT) { 343 scan(TOK_COLON, &tok); 344 get_declaration(&dec, DEF_UNION); 345 defp->def.un.default_decl = ALLOC(declaration); 346 *defp->def.un.default_decl = dec; 347 scan(TOK_SEMICOLON, &tok); 348 scan(TOK_RBRACE, &tok); 349 } else { 350 defp->def.un.default_decl = NULL; 351 } 352 } 353 354 static char *reserved_words[] = { 355 "array", 356 "bytes", 357 "destroy", 358 "free", 359 "getpos", 360 "inline", 361 "pointer", 362 "reference", 363 "setpos", 364 "sizeof", 365 "union", 366 "vector", 367 NULL 368 }; 369 370 static char *reserved_types[] = { 371 "opaque", 372 "string", 373 NULL 374 }; 375 376 /* check that the given name is not one that would eventually result in 377 xdr routines that would conflict with internal XDR routines. */ 378 static void 379 check_type_name(name, new_type) 380 int new_type; 381 char *name; 382 { 383 int i; 384 char tmp[100]; 385 386 for (i = 0; reserved_words[i] != NULL; i++) { 387 if (strcmp(name, reserved_words[i]) == 0) { 388 snprintf(tmp, sizeof tmp, 389 "illegal (reserved) name :\'%s\' in type definition", name); 390 error(tmp); 391 } 392 } 393 if (new_type) { 394 for (i = 0; reserved_types[i] != NULL; i++) { 395 if (strcmp(name, reserved_types[i]) == 0) { 396 snprintf(tmp, sizeof tmp, 397 "illegal (reserved) name :\'%s\' in" 398 " type definition", name); 399 error(tmp); 400 } 401 } 402 } 403 } 404 405 static void 406 def_typedef(defp) 407 definition *defp; 408 { 409 declaration dec; 410 411 defp->def_kind = DEF_TYPEDEF; 412 get_declaration(&dec, DEF_TYPEDEF); 413 defp->def_name = dec.name; 414 check_type_name(dec.name, 1); 415 defp->def.ty.old_prefix = dec.prefix; 416 defp->def.ty.old_type = dec.type; 417 defp->def.ty.rel = dec.rel; 418 defp->def.ty.array_max = dec.array_max; 419 } 420 421 static void 422 get_declaration(dec, dkind) 423 declaration *dec; 424 defkind dkind; 425 { 426 token tok; 427 428 get_type(&dec->prefix, &dec->type, dkind); 429 dec->rel = REL_ALIAS; 430 if (streq(dec->type, "void")) { 431 return; 432 } 433 434 check_type_name(dec->type, 0); 435 436 scan2(TOK_STAR, TOK_IDENT, &tok); 437 if (tok.kind == TOK_STAR) { 438 dec->rel = REL_POINTER; 439 scan(TOK_IDENT, &tok); 440 } 441 dec->name = tok.str; 442 if (peekscan(TOK_LBRACKET, &tok)) { 443 if (dec->rel == REL_POINTER) { 444 error("no array-of-pointer declarations -- use typedef"); 445 } 446 dec->rel = REL_VECTOR; 447 scan_num(&tok); 448 dec->array_max = tok.str; 449 scan(TOK_RBRACKET, &tok); 450 } else if (peekscan(TOK_LANGLE, &tok)) { 451 if (dec->rel == REL_POINTER) { 452 error("no array-of-pointer declarations -- use typedef"); 453 } 454 dec->rel = REL_ARRAY; 455 if (peekscan(TOK_RANGLE, &tok)) { 456 dec->array_max = "~0"; /* unspecified size, use max */ 457 } else { 458 scan_num(&tok); 459 dec->array_max = tok.str; 460 scan(TOK_RANGLE, &tok); 461 } 462 } 463 if (streq(dec->type, "opaque")) { 464 if (dec->rel != REL_ARRAY && dec->rel != REL_VECTOR) { 465 error("array declaration expected"); 466 } 467 } else if (streq(dec->type, "string")) { 468 if (dec->rel != REL_ARRAY) { 469 error("variable-length array declaration expected"); 470 } 471 } 472 } 473 474 static void 475 get_prog_declaration(dec, dkind, num) 476 declaration *dec; 477 defkind dkind; 478 int num; /* arg number */ 479 { 480 token tok; 481 char name[10]; /* argument name */ 482 483 if (dkind == DEF_PROGRAM) { 484 peek(&tok); 485 if (tok.kind == TOK_RPAREN) { /* no arguments */ 486 dec->rel = REL_ALIAS; 487 dec->type = "void"; 488 dec->prefix = NULL; 489 dec->name = NULL; 490 return; 491 } 492 } 493 get_type(&dec->prefix, &dec->type, dkind); 494 dec->rel = REL_ALIAS; 495 if (peekscan(TOK_IDENT, &tok)) /* optional name of argument */ 496 strlcpy(name, tok.str, sizeof name); 497 else { 498 /* default name of argument */ 499 snprintf(name, sizeof name, "%s%d", ARGNAME, num); 500 } 501 502 dec->name = (char *)strdup(name); 503 if (dec->name == NULL) 504 error("out of memory"); 505 506 if (streq(dec->type, "void")) 507 return; 508 509 if (streq(dec->type, "opaque")) 510 error("opaque -- illegal argument type"); 511 512 if (peekscan(TOK_STAR, &tok)) { 513 if (streq(dec->type, "string")) 514 error("pointer to string not allowed in program arguments\n"); 515 516 dec->rel = REL_POINTER; 517 if (peekscan(TOK_IDENT, &tok)) { /* optional name of argument */ 518 dec->name = (char *)strdup(tok.str); 519 if (dec->name == NULL) 520 error("out of memory"); 521 } 522 } 523 if (peekscan(TOK_LANGLE, &tok)) { 524 if (!streq(dec->type, "string")) 525 error("arrays cannot be declared as arguments to " 526 "procedures -- use typedef"); 527 dec->rel = REL_ARRAY; 528 if (peekscan(TOK_RANGLE, &tok)) { 529 dec->array_max = "~0";/* unspecified size, use max */ 530 } else { 531 scan_num(&tok); 532 dec->array_max = tok.str; 533 scan(TOK_RANGLE, &tok); 534 } 535 } 536 if (streq(dec->type, "string")) { 537 /* .x specifies just string as 538 * type of argument 539 * - make it string<> 540 */ 541 if (dec->rel != REL_ARRAY) { 542 dec->rel = REL_ARRAY; 543 dec->array_max = "~0";/* unspecified size, use max */ 544 } 545 } 546 } 547 548 static void 549 get_type(prefixp, typep, dkind) 550 char **prefixp; 551 char **typep; 552 defkind dkind; 553 { 554 token tok; 555 556 *prefixp = NULL; 557 get_token(&tok); 558 switch (tok.kind) { 559 case TOK_IDENT: 560 *typep = tok.str; 561 break; 562 case TOK_STRUCT: 563 case TOK_ENUM: 564 case TOK_UNION: 565 *prefixp = tok.str; 566 scan(TOK_IDENT, &tok); 567 *typep = tok.str; 568 break; 569 case TOK_UNSIGNED: 570 unsigned_dec(typep); 571 break; 572 case TOK_SHORT: 573 *typep = "short"; 574 (void) peekscan(TOK_INT, &tok); 575 break; 576 case TOK_LONG: 577 *typep = "long"; 578 (void) peekscan(TOK_INT, &tok); 579 break; 580 case TOK_VOID: 581 if (dkind != DEF_UNION && dkind != DEF_PROGRAM) { 582 error("voids allowed only inside union and program definitions with one argument"); 583 } 584 *typep = tok.str; 585 break; 586 case TOK_STRING: 587 case TOK_OPAQUE: 588 case TOK_CHAR: 589 case TOK_INT: 590 case TOK_FLOAT: 591 case TOK_DOUBLE: 592 case TOK_BOOL: 593 *typep = tok.str; 594 break; 595 default: 596 error("expected type specifier"); 597 } 598 } 599 600 static void 601 unsigned_dec(typep) 602 char **typep; 603 { 604 token tok; 605 606 peek(&tok); 607 switch (tok.kind) { 608 case TOK_CHAR: 609 get_token(&tok); 610 *typep = "u_char"; 611 break; 612 case TOK_SHORT: 613 get_token(&tok); 614 *typep = "u_short"; 615 (void) peekscan(TOK_INT, &tok); 616 break; 617 case TOK_LONG: 618 get_token(&tok); 619 *typep = "u_long"; 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