1 /* $OpenBSD: rpc_parse.c,v 1.20 2016/01/15 10:14:32 jasper Exp $ */ 2 /* $NetBSD: rpc_parse.c,v 1.5 1995/08/29 23:05:55 cgd Exp $ */ 3 4 /* 5 * Copyright (c) 2010, Oracle America, Inc. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions are 9 * met: 10 * 11 * * Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * * Redistributions in binary form must reproduce the above 14 * copyright notice, this list of conditions and the following 15 * disclaimer in the documentation and/or other materials 16 * provided with the distribution. 17 * * Neither the name of the "Oracle America, Inc." nor the names of its 18 * contributors may be used to endorse or promote products derived 19 * from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 24 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 25 * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 26 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 28 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 29 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 30 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 31 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 32 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33 */ 34 35 /* 36 * rpc_parse.c, Parser for the RPC protocol compiler 37 */ 38 #include <stdio.h> 39 #include <stdlib.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 static void isdefined(definition *); 49 static void def_struct(definition *); 50 static void def_program(definition *); 51 static void def_enum(definition *); 52 static void def_const(definition *); 53 static void def_union(definition *); 54 static void def_typedef(definition *); 55 static void get_declaration(declaration *, defkind); 56 static void get_prog_declaration(declaration *, defkind, int); 57 static void get_type(char **, char **, defkind); 58 static void unsigned_dec(char **); 59 60 /* 61 * return the next definition you see 62 */ 63 definition * 64 get_definition(void) 65 { 66 definition *defp; 67 token tok; 68 69 defp = malloc(sizeof(definition)); 70 get_token(&tok); 71 switch (tok.kind) { 72 case TOK_STRUCT: 73 def_struct(defp); 74 break; 75 case TOK_UNION: 76 def_union(defp); 77 break; 78 case TOK_TYPEDEF: 79 def_typedef(defp); 80 break; 81 case TOK_ENUM: 82 def_enum(defp); 83 break; 84 case TOK_PROGRAM: 85 def_program(defp); 86 break; 87 case TOK_CONST: 88 def_const(defp); 89 break; 90 case TOK_EOF: 91 free(defp); 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(defp) 103 definition *defp; 104 { 105 STOREVAL(&defined, defp); 106 } 107 108 static void 109 def_struct(defp) 110 definition *defp; 111 { 112 token tok; 113 declaration dec; 114 decl_list *decls; 115 decl_list **tailp; 116 117 defp->def_kind = DEF_STRUCT; 118 119 scan(TOK_IDENT, &tok); 120 defp->def_name = tok.str; 121 scan(TOK_LBRACE, &tok); 122 tailp = &defp->def.st.decls; 123 do { 124 get_declaration(&dec, DEF_STRUCT); 125 decls = malloc(sizeof(decl_list)); 126 decls->decl = dec; 127 *tailp = decls; 128 tailp = &decls->next; 129 scan(TOK_SEMICOLON, &tok); 130 peek(&tok); 131 } while (tok.kind != TOK_RBRACE); 132 get_token(&tok); 133 *tailp = NULL; 134 } 135 136 static void 137 def_program(defp) 138 definition *defp; 139 { 140 token tok; 141 declaration dec; 142 decl_list *decls; 143 decl_list **tailp; 144 version_list *vlist; 145 version_list **vtailp; 146 proc_list *plist; 147 proc_list **ptailp; 148 int num_args; 149 bool_t isvoid = FALSE; /* whether first argument is void */ 150 defp->def_kind = DEF_PROGRAM; 151 scan(TOK_IDENT, &tok); 152 defp->def_name = tok.str; 153 scan(TOK_LBRACE, &tok); 154 vtailp = &defp->def.pr.versions; 155 tailp = &defp->def.st.decls; 156 scan(TOK_VERSION, &tok); 157 do { 158 scan(TOK_IDENT, &tok); 159 vlist = malloc(sizeof(version_list)); 160 vlist->vers_name = tok.str; 161 scan(TOK_LBRACE, &tok); 162 ptailp = &vlist->procs; 163 do { 164 /* get result type */ 165 plist = malloc(sizeof(proc_list)); 166 get_type(&plist->res_prefix, &plist->res_type, 167 DEF_PROGRAM); 168 if (streq(plist->res_type, "opaque")) { 169 error("illegal result type"); 170 } 171 scan(TOK_IDENT, &tok); 172 plist->proc_name = tok.str; 173 scan(TOK_LPAREN, &tok); 174 /* get args - first one*/ 175 num_args = 1; 176 isvoid = FALSE; 177 /* type of DEF_PROGRAM in the first 178 * get_prog_declaration and DEF_STURCT in the next 179 * allows void as argument if it is the only argument 180 */ 181 get_prog_declaration(&dec, DEF_PROGRAM, num_args); 182 if (streq(dec.type, "void")) 183 isvoid = TRUE; 184 decls = malloc(sizeof(decl_list)); 185 plist->args.decls = decls; 186 decls->decl = dec; 187 tailp = &decls->next; 188 /* get args */ 189 while (peekscan(TOK_COMMA, &tok)) { 190 num_args++; 191 get_prog_declaration(&dec, DEF_STRUCT, 192 num_args); 193 decls = malloc(sizeof(decl_list)); 194 decls->decl = dec; 195 *tailp = decls; 196 if (streq(dec.type, "void")) 197 isvoid = TRUE; 198 tailp = &decls->next; 199 } 200 /* multiple arguments are only allowed in newstyle */ 201 if (!newstyle && num_args > 1) { 202 error("only one argument is allowed"); 203 } 204 if (isvoid && num_args > 1) { 205 error("illegal use of void in program definition"); 206 } 207 *tailp = NULL; 208 scan(TOK_RPAREN, &tok); 209 scan(TOK_EQUAL, &tok); 210 scan_num(&tok); 211 scan(TOK_SEMICOLON, &tok); 212 plist->proc_num = tok.str; 213 plist->arg_num = num_args; 214 *ptailp = plist; 215 ptailp = &plist->next; 216 peek(&tok); 217 } while (tok.kind != TOK_RBRACE); 218 *ptailp = NULL; 219 *vtailp = vlist; 220 vtailp = &vlist->next; 221 scan(TOK_RBRACE, &tok); 222 scan(TOK_EQUAL, &tok); 223 scan_num(&tok); 224 vlist->vers_num = tok.str; 225 /* make the argument structure name for each arg*/ 226 for (plist = vlist->procs; plist != NULL; 227 plist = plist->next) { 228 plist->args.argname = make_argname(plist->proc_name, 229 vlist->vers_num); 230 /* free the memory ??*/ 231 } 232 scan(TOK_SEMICOLON, &tok); 233 scan2(TOK_VERSION, TOK_RBRACE, &tok); 234 } while (tok.kind == TOK_VERSION); 235 scan(TOK_EQUAL, &tok); 236 scan_num(&tok); 237 defp->def.pr.prog_num = tok.str; 238 *vtailp = NULL; 239 } 240 241 242 static void 243 def_enum(defp) 244 definition *defp; 245 { 246 token tok; 247 enumval_list *elist; 248 enumval_list **tailp; 249 250 defp->def_kind = DEF_ENUM; 251 scan(TOK_IDENT, &tok); 252 defp->def_name = tok.str; 253 scan(TOK_LBRACE, &tok); 254 tailp = &defp->def.en.vals; 255 do { 256 scan(TOK_IDENT, &tok); 257 elist = malloc(sizeof(enumval_list)); 258 elist->name = tok.str; 259 elist->assignment = NULL; 260 scan3(TOK_COMMA, TOK_RBRACE, TOK_EQUAL, &tok); 261 if (tok.kind == TOK_EQUAL) { 262 scan_num(&tok); 263 elist->assignment = tok.str; 264 scan2(TOK_COMMA, TOK_RBRACE, &tok); 265 } 266 *tailp = elist; 267 tailp = &elist->next; 268 } while (tok.kind != TOK_RBRACE); 269 *tailp = NULL; 270 } 271 272 static void 273 def_const(defp) 274 definition *defp; 275 { 276 token tok; 277 278 defp->def_kind = DEF_CONST; 279 scan(TOK_IDENT, &tok); 280 defp->def_name = tok.str; 281 scan(TOK_EQUAL, &tok); 282 scan2(TOK_IDENT, TOK_STRCONST, &tok); 283 defp->def.co = tok.str; 284 } 285 286 static void 287 def_union(defp) 288 definition *defp; 289 { 290 token tok; 291 declaration dec; 292 case_list *cases; 293 case_list **tailp; 294 int flag; 295 296 defp->def_kind = DEF_UNION; 297 scan(TOK_IDENT, &tok); 298 defp->def_name = tok.str; 299 scan(TOK_SWITCH, &tok); 300 scan(TOK_LPAREN, &tok); 301 get_declaration(&dec, DEF_UNION); 302 defp->def.un.enum_decl = dec; 303 tailp = &defp->def.un.cases; 304 scan(TOK_RPAREN, &tok); 305 scan(TOK_LBRACE, &tok); 306 scan(TOK_CASE, &tok); 307 while (tok.kind == TOK_CASE) { 308 scan2(TOK_IDENT, TOK_CHARCONST, &tok); 309 cases = malloc(sizeof(case_list)); 310 cases->case_name = tok.str; 311 scan(TOK_COLON, &tok); 312 /* now peek at next token */ 313 flag=0; 314 if (peekscan(TOK_CASE,&tok)) { 315 do { 316 scan2(TOK_IDENT, TOK_CHARCONST, &tok); 317 cases->contflag=1; /* continued case statement */ 318 *tailp = cases; 319 tailp = &cases->next; 320 cases = malloc(sizeof(case_list)); 321 cases->case_name = tok.str; 322 scan(TOK_COLON, &tok); 323 } while (peekscan(TOK_CASE,&tok)); 324 } else if (flag) { 325 *tailp = cases; 326 tailp = &cases->next; 327 cases = malloc(sizeof(case_list)); 328 } 329 get_declaration(&dec, DEF_UNION); 330 cases->case_decl = dec; 331 cases->contflag=0; /* no continued case statement */ 332 *tailp = cases; 333 tailp = &cases->next; 334 scan(TOK_SEMICOLON, &tok); 335 336 scan3(TOK_CASE, TOK_DEFAULT, TOK_RBRACE, &tok); 337 } 338 *tailp = NULL; 339 340 if (tok.kind == TOK_DEFAULT) { 341 scan(TOK_COLON, &tok); 342 get_declaration(&dec, DEF_UNION); 343 defp->def.un.default_decl = malloc(sizeof(declaration)); 344 *defp->def.un.default_decl = dec; 345 scan(TOK_SEMICOLON, &tok); 346 scan(TOK_RBRACE, &tok); 347 } else { 348 defp->def.un.default_decl = NULL; 349 } 350 } 351 352 static char *reserved_words[] = { 353 "array", 354 "bytes", 355 "destroy", 356 "free", 357 "getpos", 358 "inline", 359 "pointer", 360 "reference", 361 "setpos", 362 "sizeof", 363 "union", 364 "vector", 365 NULL 366 }; 367 368 static char *reserved_types[] = { 369 "opaque", 370 "string", 371 NULL 372 }; 373 374 /* check that the given name is not one that would eventually result in 375 xdr routines that would conflict with internal XDR routines. */ 376 static void 377 check_type_name(char *name, int new_type) 378 { 379 int i; 380 char tmp[100]; 381 382 for (i = 0; reserved_words[i] != NULL; i++) { 383 if (strcmp(name, reserved_words[i]) == 0) { 384 snprintf(tmp, sizeof tmp, 385 "illegal (reserved) name :\'%s\' in type definition", name); 386 error(tmp); 387 } 388 } 389 if (new_type) { 390 for (i = 0; reserved_types[i] != NULL; i++) { 391 if (strcmp(name, reserved_types[i]) == 0) { 392 snprintf(tmp, sizeof tmp, 393 "illegal (reserved) name :\'%s\' in" 394 " type definition", name); 395 error(tmp); 396 } 397 } 398 } 399 } 400 401 static void 402 def_typedef(defp) 403 definition *defp; 404 { 405 declaration dec; 406 407 defp->def_kind = DEF_TYPEDEF; 408 get_declaration(&dec, DEF_TYPEDEF); 409 defp->def_name = dec.name; 410 check_type_name(dec.name, 1); 411 defp->def.ty.old_prefix = dec.prefix; 412 defp->def.ty.old_type = dec.type; 413 defp->def.ty.rel = dec.rel; 414 defp->def.ty.array_max = dec.array_max; 415 } 416 417 static void 418 get_declaration(dec, dkind) 419 declaration *dec; 420 defkind dkind; 421 { 422 token tok; 423 424 get_type(&dec->prefix, &dec->type, dkind); 425 dec->rel = REL_ALIAS; 426 if (streq(dec->type, "void")) { 427 return; 428 } 429 430 check_type_name(dec->type, 0); 431 432 scan2(TOK_STAR, TOK_IDENT, &tok); 433 if (tok.kind == TOK_STAR) { 434 dec->rel = REL_POINTER; 435 scan(TOK_IDENT, &tok); 436 } 437 dec->name = tok.str; 438 if (peekscan(TOK_LBRACKET, &tok)) { 439 if (dec->rel == REL_POINTER) { 440 error("no array-of-pointer declarations -- use typedef"); 441 } 442 dec->rel = REL_VECTOR; 443 scan_num(&tok); 444 dec->array_max = tok.str; 445 scan(TOK_RBRACKET, &tok); 446 } else if (peekscan(TOK_LANGLE, &tok)) { 447 if (dec->rel == REL_POINTER) { 448 error("no array-of-pointer declarations -- use typedef"); 449 } 450 dec->rel = REL_ARRAY; 451 if (peekscan(TOK_RANGLE, &tok)) { 452 dec->array_max = "~0"; /* unspecified size, use max */ 453 } else { 454 scan_num(&tok); 455 dec->array_max = tok.str; 456 scan(TOK_RANGLE, &tok); 457 } 458 } 459 if (streq(dec->type, "opaque")) { 460 if (dec->rel != REL_ARRAY && dec->rel != REL_VECTOR) { 461 error("array declaration expected"); 462 } 463 } else if (streq(dec->type, "string")) { 464 if (dec->rel != REL_ARRAY) { 465 error("variable-length array declaration expected"); 466 } 467 } 468 } 469 470 static void 471 get_prog_declaration(dec, dkind, num) 472 declaration *dec; 473 defkind dkind; 474 int num; /* arg number */ 475 { 476 token tok; 477 478 if (dkind == DEF_PROGRAM) { 479 peek(&tok); 480 if (tok.kind == TOK_RPAREN) { /* no arguments */ 481 dec->rel = REL_ALIAS; 482 dec->type = "void"; 483 dec->prefix = NULL; 484 dec->name = NULL; 485 return; 486 } 487 } 488 get_type(&dec->prefix, &dec->type, dkind); 489 dec->rel = REL_ALIAS; 490 if (peekscan(TOK_IDENT, &tok)) { /* optional name of argument */ 491 dec->name = (char *)strdup(tok.str); 492 if (dec->name == NULL) 493 error("out of memory"); 494 } else { 495 /* default name of argument */ 496 if (asprintf(&dec->name, "%s%d", ARGNAME, num) == -1) 497 error("out of memory"); 498 } 499 500 if (streq(dec->type, "void")) 501 return; 502 503 if (streq(dec->type, "opaque")) 504 error("opaque -- illegal argument type"); 505 506 if (peekscan(TOK_STAR, &tok)) { 507 if (streq(dec->type, "string")) 508 error("pointer to string not allowed in program arguments\n"); 509 510 dec->rel = REL_POINTER; 511 if (peekscan(TOK_IDENT, &tok)) { /* optional name of argument */ 512 dec->name = (char *)strdup(tok.str); 513 if (dec->name == NULL) 514 error("out of memory"); 515 } 516 } 517 if (peekscan(TOK_LANGLE, &tok)) { 518 if (!streq(dec->type, "string")) 519 error("arrays cannot be declared as arguments to " 520 "procedures -- use typedef"); 521 dec->rel = REL_ARRAY; 522 if (peekscan(TOK_RANGLE, &tok)) { 523 dec->array_max = "~0";/* unspecified size, use max */ 524 } else { 525 scan_num(&tok); 526 dec->array_max = tok.str; 527 scan(TOK_RANGLE, &tok); 528 } 529 } 530 if (streq(dec->type, "string")) { 531 /* .x specifies just string as 532 * type of argument 533 * - make it string<> 534 */ 535 if (dec->rel != REL_ARRAY) { 536 dec->rel = REL_ARRAY; 537 dec->array_max = "~0";/* unspecified size, use max */ 538 } 539 } 540 } 541 542 static void 543 get_type(prefixp, typep, dkind) 544 char **prefixp; 545 char **typep; 546 defkind dkind; 547 { 548 token tok; 549 550 *prefixp = NULL; 551 get_token(&tok); 552 switch (tok.kind) { 553 case TOK_IDENT: 554 *typep = tok.str; 555 break; 556 case TOK_STRUCT: 557 case TOK_ENUM: 558 case TOK_UNION: 559 *prefixp = tok.str; 560 scan(TOK_IDENT, &tok); 561 *typep = tok.str; 562 break; 563 case TOK_UNSIGNED: 564 unsigned_dec(typep); 565 break; 566 case TOK_SHORT: 567 *typep = "short"; 568 (void) peekscan(TOK_INT, &tok); 569 break; 570 case TOK_LONG: 571 *typep = "long"; 572 (void) peekscan(TOK_INT, &tok); 573 break; 574 case TOK_HYPER: 575 *typep = "int64_t"; 576 (void) peekscan(TOK_INT, &tok); 577 break; 578 case TOK_VOID: 579 if (dkind != DEF_UNION && dkind != DEF_PROGRAM) { 580 error("voids allowed only inside union and program definitions with one argument"); 581 } 582 *typep = tok.str; 583 break; 584 case TOK_STRING: 585 case TOK_OPAQUE: 586 case TOK_CHAR: 587 case TOK_INT: 588 case TOK_FLOAT: 589 case TOK_DOUBLE: 590 case TOK_QUAD: 591 case TOK_BOOL: 592 *typep = tok.str; 593 break; 594 default: 595 error("expected type specifier"); 596 } 597 } 598 599 static void 600 unsigned_dec(typep) 601 char **typep; 602 { 603 token tok; 604 605 peek(&tok); 606 switch (tok.kind) { 607 case TOK_CHAR: 608 get_token(&tok); 609 *typep = "u_char"; 610 break; 611 case TOK_SHORT: 612 get_token(&tok); 613 *typep = "u_short"; 614 (void) peekscan(TOK_INT, &tok); 615 break; 616 case TOK_LONG: 617 get_token(&tok); 618 *typep = "u_long"; 619 (void) peekscan(TOK_INT, &tok); 620 break; 621 case TOK_HYPER: 622 get_token(&tok); 623 *typep = "u_int64_t"; 624 (void) peekscan(TOK_INT, &tok); 625 break; 626 case TOK_INT: 627 get_token(&tok); 628 *typep = "u_int"; 629 break; 630 default: 631 *typep = "u_int"; 632 break; 633 } 634 } 635