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