rpc_parse.c revision 1.6
1/* $OpenBSD: rpc_parse.c,v 1.6 2001/11/24 19:17:47 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 34static 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 51static isdefined __P((definition *)); 52static def_struct __P((definition *)); 53static def_program __P((definition *)); 54static def_enum __P((definition *)); 55static def_const __P((definition *)); 56static def_union __P((definition *)); 57static def_typedef __P((definition *)); 58static get_declaration __P((declaration *, defkind)); 59static get_prog_declaration __P((declaration *, defkind, int)); 60static get_type __P((char **, char **, defkind)); 61static unsigned_dec __P((char **)); 62 63/* 64 * return the next definition you see 65 */ 66definition * 67get_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 103static 104isdefined(defp) 105 definition *defp; 106{ 107 STOREVAL(&defined, defp); 108} 109 110static 111def_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 138static 139def_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 244static 245def_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 274static 275def_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 288static 289def_union(defp) 290 definition *defp; 291{ 292 token tok; 293 declaration dec; 294 case_list *cases,*tcase; 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 { 318 319 do 320 { 321 scan2(TOK_IDENT, TOK_CHARCONST, &tok); 322 cases->contflag=1; /* continued case statement */ 323 *tailp = cases; 324 tailp = &cases->next; 325 cases = ALLOC(case_list); 326 cases->case_name = tok.str; 327 scan(TOK_COLON, &tok); 328 329 } while (peekscan(TOK_CASE,&tok)); 330 } 331 else 332 if(flag) 333 { 334 335 *tailp = cases; 336 tailp = &cases->next; 337 cases = ALLOC(case_list); 338 } 339 340 get_declaration(&dec, DEF_UNION); 341 cases->case_decl = dec; 342 cases->contflag=0; /* no continued case statement */ 343 *tailp = cases; 344 tailp = &cases->next; 345 scan(TOK_SEMICOLON, &tok); 346 347 scan3(TOK_CASE, TOK_DEFAULT, TOK_RBRACE, &tok); 348 } 349 *tailp = NULL; 350 if (tok.kind == TOK_DEFAULT) { 351 scan(TOK_COLON, &tok); 352 get_declaration(&dec, DEF_UNION); 353 defp->def.un.default_decl = ALLOC(declaration); 354 *defp->def.un.default_decl = dec; 355 scan(TOK_SEMICOLON, &tok); 356 scan(TOK_RBRACE, &tok); 357 } else { 358 defp->def.un.default_decl = NULL; 359 } 360} 361 362static char *reserved_words[] = { 363 "array", 364 "bytes", 365 "destroy", 366 "free", 367 "getpos", 368 "inline", 369 "pointer", 370 "reference", 371 "setpos", 372 "sizeof", 373 "union", 374 "vector", 375 NULL 376}; 377 378static char *reserved_types[] = { 379 "opaque", 380 "string", 381 NULL 382}; 383 384/* check that the given name is not one that would eventually result in 385 xdr routines that would conflict with internal XDR routines. */ 386static check_type_name( name, new_type ) 387int new_type; 388char *name; 389{ 390 int i; 391 char tmp[100]; 392 393 for( i = 0; reserved_words[i] != NULL; i++ ) { 394 if( strcmp( name, reserved_words[i] ) == 0 ) { 395 sprintf(tmp, 396 "illegal (reserved) name :\'%s\' in type definition", name ); 397 error(tmp); 398 } 399 } 400 if( new_type ) { 401 for( i = 0; reserved_types[i] != NULL; i++ ) { 402 if( strcmp( name, reserved_types[i] ) == 0 ) { 403 sprintf(tmp, 404 "illegal (reserved) name :\'%s\' in type definition", name ); 405 error(tmp); 406 } 407 } 408 } 409} 410 411static 412def_typedef(defp) 413 definition *defp; 414{ 415 declaration dec; 416 417 defp->def_kind = DEF_TYPEDEF; 418 get_declaration(&dec, DEF_TYPEDEF); 419 defp->def_name = dec.name; 420 check_type_name( dec.name, 1 ); 421 defp->def.ty.old_prefix = dec.prefix; 422 defp->def.ty.old_type = dec.type; 423 defp->def.ty.rel = dec.rel; 424 defp->def.ty.array_max = dec.array_max; 425} 426 427static 428get_declaration(dec, dkind) 429 declaration *dec; 430 defkind dkind; 431{ 432 token tok; 433 434 get_type(&dec->prefix, &dec->type, dkind); 435 dec->rel = REL_ALIAS; 436 if (streq(dec->type, "void")) { 437 return; 438 } 439 440 check_type_name( dec->type, 0 ); 441 442 scan2(TOK_STAR, TOK_IDENT, &tok); 443 if (tok.kind == TOK_STAR) { 444 dec->rel = REL_POINTER; 445 scan(TOK_IDENT, &tok); 446 } 447 dec->name = tok.str; 448 if (peekscan(TOK_LBRACKET, &tok)) { 449 if (dec->rel == REL_POINTER) { 450 error("no array-of-pointer declarations -- use typedef"); 451 } 452 dec->rel = REL_VECTOR; 453 scan_num(&tok); 454 dec->array_max = tok.str; 455 scan(TOK_RBRACKET, &tok); 456 } else if (peekscan(TOK_LANGLE, &tok)) { 457 if (dec->rel == REL_POINTER) { 458 error("no array-of-pointer declarations -- use typedef"); 459 } 460 dec->rel = REL_ARRAY; 461 if (peekscan(TOK_RANGLE, &tok)) { 462 dec->array_max = "~0"; /* unspecified size, use max */ 463 } else { 464 scan_num(&tok); 465 dec->array_max = tok.str; 466 scan(TOK_RANGLE, &tok); 467 } 468 } 469 if (streq(dec->type, "opaque")) { 470 if (dec->rel != REL_ARRAY && dec->rel != REL_VECTOR) { 471 error("array declaration expected"); 472 } 473 } else if (streq(dec->type, "string")) { 474 if (dec->rel != REL_ARRAY) { 475 error("variable-length array declaration expected"); 476 } 477 } 478} 479 480static 481get_prog_declaration(dec, dkind, num) 482 declaration *dec; 483 defkind dkind; 484 int num; /* arg number */ 485{ 486 token tok; 487 char name[10]; /* argument name */ 488 489 if (dkind == DEF_PROGRAM) { 490 peek(&tok); 491 if (tok.kind == TOK_RPAREN) { /* no arguments */ 492 dec->rel = REL_ALIAS; 493 dec->type = "void"; 494 dec->prefix = NULL; 495 dec->name = NULL; 496 return; 497 } 498 } 499 get_type(&dec->prefix, &dec->type, dkind); 500 dec->rel = REL_ALIAS; 501 if (peekscan(TOK_IDENT, &tok)) /* optional name of argument */ 502 strcpy(name, tok.str); 503 else 504 sprintf(name, "%s%d", ARGNAME, num); /* default name of argument */ 505 506 dec->name = (char *)strdup(name); 507 508 if (streq(dec->type, "void")) { 509 return; 510 } 511 512 if (streq(dec->type, "opaque")) { 513 error("opaque -- illegal argument type"); 514 } 515 if (peekscan(TOK_STAR, &tok)) { 516 if (streq(dec->type, "string")) { 517 error("pointer to string not allowed in program arguments\n"); 518 } 519 dec->rel = REL_POINTER; 520 if (peekscan(TOK_IDENT, &tok)) /* optional name of argument */ 521 dec->name = (char *)strdup(tok.str); 522 } 523 if (peekscan(TOK_LANGLE, &tok)) { 524 if (!streq(dec->type, "string")) { 525 error("arrays cannot be declared as arguments to procedures -- use typedef"); 526 } 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 if (dec->rel != REL_ARRAY) { /* .x specifies just string as 538 * type of argument 539 * - make it string<> 540 */ 541 dec->rel = REL_ARRAY; 542 dec->array_max = "~0";/* unspecified size, use max */ 543 } 544 } 545} 546 547 548 549static 550get_type(prefixp, typep, dkind) 551 char **prefixp; 552 char **typep; 553 defkind dkind; 554{ 555 token tok; 556 557 *prefixp = NULL; 558 get_token(&tok); 559 switch (tok.kind) { 560 case TOK_IDENT: 561 *typep = tok.str; 562 break; 563 case TOK_STRUCT: 564 case TOK_ENUM: 565 case TOK_UNION: 566 *prefixp = tok.str; 567 scan(TOK_IDENT, &tok); 568 *typep = tok.str; 569 break; 570 case TOK_UNSIGNED: 571 unsigned_dec(typep); 572 break; 573 case TOK_SHORT: 574 *typep = "short"; 575 (void) peekscan(TOK_INT, &tok); 576 break; 577 case TOK_LONG: 578 *typep = "long"; 579 (void) peekscan(TOK_INT, &tok); 580 break; 581 case TOK_VOID: 582 if (dkind != DEF_UNION && dkind != DEF_PROGRAM) { 583 error("voids allowed only inside union and program definitions with one argument"); 584 } 585 *typep = tok.str; 586 break; 587 case TOK_STRING: 588 case TOK_OPAQUE: 589 case TOK_CHAR: 590 case TOK_INT: 591 case TOK_FLOAT: 592 case TOK_DOUBLE: 593 case TOK_BOOL: 594 *typep = tok.str; 595 break; 596 default: 597 error("expected type specifier"); 598 } 599} 600 601static 602unsigned_dec(typep) 603 char **typep; 604{ 605 token tok; 606 607 peek(&tok); 608 switch (tok.kind) { 609 case TOK_CHAR: 610 get_token(&tok); 611 *typep = "u_char"; 612 break; 613 case TOK_SHORT: 614 get_token(&tok); 615 *typep = "u_short"; 616 (void) peekscan(TOK_INT, &tok); 617 break; 618 case TOK_LONG: 619 get_token(&tok); 620 *typep = "u_long"; 621 (void) peekscan(TOK_INT, &tok); 622 break; 623 case TOK_INT: 624 get_token(&tok); 625 *typep = "u_int"; 626 break; 627 default: 628 *typep = "u_int"; 629 break; 630 } 631} 632