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