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