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