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