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