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