1 /* $OpenBSD: rpc_cout.c,v 1.6 2001/07/18 22:26:00 deraadt Exp $ */ 2 /* $NetBSD: rpc_cout.c,v 1.6 1996/10/01 04:13:53 cgd Exp $ */ 3 /* 4 * Sun RPC is a product of Sun Microsystems, Inc. and is provided for 5 * unrestricted use provided that this legend is included on all tape 6 * media and as a part of the software program in whole or part. Users 7 * may copy or modify Sun RPC without charge, but are not authorized 8 * to license or distribute it to anyone else except as part of a product or 9 * program developed by the user or with the express written consent of 10 * Sun Microsystems, Inc. 11 * 12 * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE 13 * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR 14 * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. 15 * 16 * Sun RPC is provided with no support and without any obligation on the 17 * part of Sun Microsystems, Inc. to assist in its use, correction, 18 * modification or enhancement. 19 * 20 * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE 21 * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC 22 * OR ANY PART THEREOF. 23 * 24 * In no event will Sun Microsystems, Inc. be liable for any lost revenue 25 * or profits or other special, indirect and consequential damages, even if 26 * Sun has been advised of the possibility of such damages. 27 * 28 * Sun Microsystems, Inc. 29 * 2550 Garcia Avenue 30 * Mountain View, California 94043 31 */ 32 33 #ifndef lint 34 static char sccsid[] = "@(#)rpc_cout.c 1.13 89/02/22 (C) 1987 SMI"; 35 #endif 36 37 /* 38 * rpc_cout.c, XDR routine outputter for the RPC protocol compiler 39 */ 40 #include <sys/cdefs.h> 41 #include <stdio.h> 42 #include <stdlib.h> 43 #include <string.h> 44 #include "rpc_parse.h" 45 #include "rpc_util.h" 46 47 static findtype __P((definition *, char *)); 48 static undefined __P((char *)); 49 static print_generic_header __P((char *, int)); 50 static print_header __P((definition *)); 51 static print_prog_header __P((proc_list *)); 52 static print_trailer __P((void)); 53 static print_ifopen __P((int, char *)); 54 static print_ifarg __P((char *)); 55 static print_ifsizeof __P((char *, char *)); 56 static print_ifclose __P((int)); 57 static print_ifstat __P((int, char *, char *, relation, char *, char *, char *)); 58 static emit_num __P((definition *)); 59 static emit_program __P((definition *)); 60 static emit_enum __P((definition *)); 61 static emit_union __P((definition *)); 62 static emit_struct __P((definition *)); 63 static emit_typedef __P((definition *)); 64 static print_stat __P((int, declaration *)); 65 66 67 /* 68 * Emit the C-routine for the given definition 69 */ 70 void 71 emit(def) 72 definition *def; 73 { 74 if (def->def_kind == DEF_CONST) { 75 return; 76 } 77 if (def->def_kind == DEF_PROGRAM) { 78 emit_program(def); 79 return; 80 } 81 if (def->def_kind == DEF_TYPEDEF) { 82 /* now we need to handle declarations like struct typedef foo 83 * foo; since we dont want this to be expanded into 2 calls to 84 * xdr_foo */ 85 86 if (strcmp(def->def.ty.old_type, def->def_name) == 0) 87 return; 88 }; 89 90 print_header(def); 91 switch (def->def_kind) { 92 case DEF_UNION: 93 emit_union(def); 94 break; 95 case DEF_ENUM: 96 emit_enum(def); 97 break; 98 case DEF_STRUCT: 99 emit_struct(def); 100 break; 101 case DEF_TYPEDEF: 102 emit_typedef(def); 103 break; 104 } 105 print_trailer(); 106 } 107 108 static 109 findtype(def, type) 110 definition *def; 111 char *type; 112 { 113 114 if (def->def_kind == DEF_PROGRAM || def->def_kind == DEF_CONST) { 115 return (0); 116 } else { 117 return (streq(def->def_name, type)); 118 } 119 } 120 121 static 122 undefined(type) 123 char *type; 124 { 125 definition *def; 126 127 def = (definition *) FINDVAL(defined, type, findtype); 128 129 130 return (def == NULL); 131 } 132 133 static 134 print_generic_header(procname, pointerp) 135 char *procname; 136 int pointerp; 137 { 138 f_print(fout, "\n"); 139 f_print(fout, "bool_t\n"); 140 if (Cflag) { 141 f_print(fout, "xdr_%s(", procname); 142 f_print(fout, "XDR *xdrs, "); 143 f_print(fout, "%s ", procname); 144 if (pointerp) 145 f_print(fout, "*"); 146 f_print(fout, "objp)\n{\n\n"); 147 } else { 148 f_print(fout, "xdr_%s(xdrs, objp)\n", procname); 149 f_print(fout, "\tXDR *xdrs;\n"); 150 f_print(fout, "\t%s ", procname); 151 if (pointerp) 152 f_print(fout, "*"); 153 f_print(fout, "objp;\n{\n\n"); 154 } 155 } 156 157 static 158 print_header(def) 159 definition *def; 160 { 161 162 decl_list *dl; 163 bas_type *ptr; 164 int i; 165 166 167 print_generic_header(def->def_name, 168 def->def_kind != DEF_TYPEDEF || 169 !isvectordef(def->def.ty.old_type, def->def.ty.rel)); 170 171 /* Now add Inline support */ 172 173 174 if (doinline == 0) 175 return; 176 /* May cause lint to complain. but ... */ 177 f_print(fout, "\t register int32_t *buf;\n\n"); 178 179 } 180 181 static 182 print_prog_header(plist) 183 proc_list *plist; 184 { 185 print_generic_header(plist->args.argname, 1); 186 } 187 188 static 189 print_trailer() 190 { 191 f_print(fout, "\treturn (TRUE);\n"); 192 f_print(fout, "}\n"); 193 } 194 195 196 static 197 print_ifopen(indent, name) 198 int indent; 199 char *name; 200 { 201 tabify(fout, indent); 202 f_print(fout, " if (!xdr_%s(xdrs", name); 203 } 204 205 static 206 print_ifarg(arg) 207 char *arg; 208 { 209 f_print(fout, ", %s", arg); 210 } 211 212 static 213 print_ifsizeof(prefix, type) 214 char *prefix; 215 char *type; 216 { 217 if (streq(type, "bool")) { 218 f_print(fout, ", sizeof(bool_t), (xdrproc_t)xdr_bool"); 219 } else { 220 f_print(fout, ", sizeof("); 221 if (undefined(type) && prefix) { 222 f_print(fout, "%s ", prefix); 223 } 224 f_print(fout, "%s), (xdrproc_t)xdr_%s", type, type); 225 } 226 } 227 228 static 229 print_ifclose(indent) 230 int indent; 231 { 232 f_print(fout, ")) {\n"); 233 tabify(fout, indent); 234 f_print(fout, "\t return (FALSE);\n"); 235 tabify(fout, indent); 236 f_print(fout, " }\n"); 237 } 238 239 static 240 print_ifstat(indent, prefix, type, rel, amax, objname, name) 241 int indent; 242 char *prefix; 243 char *type; 244 relation rel; 245 char *amax; 246 char *objname; 247 char *name; 248 { 249 char *alt = NULL; 250 251 switch (rel) { 252 case REL_POINTER: 253 print_ifopen(indent, "pointer"); 254 print_ifarg("(char **)"); 255 f_print(fout, "%s", objname); 256 print_ifsizeof(prefix, type); 257 break; 258 case REL_VECTOR: 259 if (streq(type, "string")) { 260 alt = "string"; 261 } else 262 if (streq(type, "opaque")) { 263 alt = "opaque"; 264 } 265 if (alt) { 266 print_ifopen(indent, alt); 267 print_ifarg(objname); 268 } else { 269 print_ifopen(indent, "vector"); 270 print_ifarg("(char *)"); 271 f_print(fout, "%s", objname); 272 } 273 print_ifarg(amax); 274 if (!alt) { 275 print_ifsizeof(prefix, type); 276 } 277 break; 278 case REL_ARRAY: 279 if (streq(type, "string")) { 280 alt = "string"; 281 } else 282 if (streq(type, "opaque")) { 283 alt = "bytes"; 284 } 285 if (streq(type, "string")) { 286 print_ifopen(indent, alt); 287 print_ifarg(objname); 288 } else { 289 if (alt) { 290 print_ifopen(indent, alt); 291 } else { 292 print_ifopen(indent, "array"); 293 } 294 print_ifarg("(char **)"); 295 if (*objname == '&') { 296 f_print(fout, "%s.%s_val, (u_int *)%s.%s_len", 297 objname, name, objname, name); 298 } else { 299 f_print(fout, "&%s->%s_val, (u_int *)&%s->%s_len", 300 objname, name, objname, name); 301 } 302 } 303 print_ifarg(amax); 304 if (!alt) { 305 print_ifsizeof(prefix, type); 306 } 307 break; 308 case REL_ALIAS: 309 print_ifopen(indent, type); 310 print_ifarg(objname); 311 break; 312 } 313 print_ifclose(indent); 314 } 315 316 /* ARGSUSED */ 317 static 318 emit_enum(def) 319 definition *def; 320 { 321 print_ifopen(1, "enum"); 322 print_ifarg("(enum_t *)objp"); 323 print_ifclose(1); 324 } 325 326 static 327 emit_program(def) 328 definition *def; 329 { 330 decl_list *dl; 331 version_list *vlist; 332 proc_list *plist; 333 334 for (vlist = def->def.pr.versions; vlist != NULL; vlist = vlist->next) 335 for (plist = vlist->procs; plist != NULL; plist = plist->next) { 336 if (!newstyle || plist->arg_num < 2) 337 continue; /* old style, or single 338 * argument */ 339 print_prog_header(plist); 340 for (dl = plist->args.decls; dl != NULL; 341 dl = dl->next) 342 print_stat(1, &dl->decl); 343 print_trailer(); 344 } 345 } 346 347 348 static 349 emit_union(def) 350 definition *def; 351 { 352 declaration *dflt; 353 case_list *cl; 354 declaration *cs; 355 char *object; 356 char *vecformat = "objp->%s_u.%s"; 357 char *format = "&objp->%s_u.%s"; 358 359 print_stat(1, &def->def.un.enum_decl); 360 f_print(fout, "\tswitch (objp->%s) {\n", def->def.un.enum_decl.name); 361 for (cl = def->def.un.cases; cl != NULL; cl = cl->next) { 362 363 f_print(fout, "\tcase %s:\n", cl->case_name); 364 if (cl->contflag == 1) /* a continued case statement */ 365 continue; 366 cs = &cl->case_decl; 367 if (!streq(cs->type, "void")) { 368 object = alloc(strlen(def->def_name) + strlen(format) + 369 strlen(cs->name) + 1); 370 if (isvectordef(cs->type, cs->rel)) { 371 s_print(object, vecformat, def->def_name, 372 cs->name); 373 } else { 374 s_print(object, format, def->def_name, 375 cs->name); 376 } 377 print_ifstat(2, cs->prefix, cs->type, cs->rel, cs->array_max, 378 object, cs->name); 379 free(object); 380 } 381 f_print(fout, "\t\tbreak;\n"); 382 } 383 dflt = def->def.un.default_decl; 384 if (dflt != NULL) { 385 if (!streq(dflt->type, "void")) { 386 f_print(fout, "\tdefault:\n"); 387 object = alloc(strlen(def->def_name) + strlen(format) + 388 strlen(dflt->name) + 1); 389 if (isvectordef(dflt->type, dflt->rel)) { 390 s_print(object, vecformat, def->def_name, 391 dflt->name); 392 } else { 393 s_print(object, format, def->def_name, 394 dflt->name); 395 } 396 397 print_ifstat(2, dflt->prefix, dflt->type, dflt->rel, 398 dflt->array_max, object, dflt->name); 399 free(object); 400 f_print(fout, "\t\tbreak;\n"); 401 } 402 } else { 403 f_print(fout, "\tdefault:\n"); 404 f_print(fout, "\t\treturn (FALSE);\n"); 405 } 406 407 f_print(fout, "\t}\n"); 408 } 409 410 static 411 emit_struct(def) 412 definition *def; 413 { 414 decl_list *dl; 415 int i, j, size, flag; 416 decl_list *cur, *psav; 417 bas_type *ptr; 418 char *sizestr, *plus; 419 char ptemp[256]; 420 int can_inline; 421 422 423 if (doinline == 0) { 424 for (dl = def->def.st.decls; dl != NULL; dl = dl->next) 425 print_stat(1, &dl->decl); 426 return; 427 } 428 for (dl = def->def.st.decls; dl != NULL; dl = dl->next) 429 if (dl->decl.rel == REL_VECTOR) { 430 f_print(fout, "\t int i;\n"); 431 break; 432 } 433 size = 0; 434 can_inline = 0; 435 for (dl = def->def.st.decls; dl != NULL; dl = dl->next) 436 if ((dl->decl.prefix == NULL) && 437 ((ptr = find_type(dl->decl.type)) != NULL) && 438 ((dl->decl.rel == REL_ALIAS) || (dl->decl.rel == REL_VECTOR))) { 439 440 if (dl->decl.rel == REL_ALIAS) 441 size += ptr->length; 442 else { 443 can_inline = 1; 444 break; /* can be inlined */ 445 }; 446 } else { 447 if (size >= doinline) { 448 can_inline = 1; 449 break; /* can be inlined */ 450 } 451 size = 0; 452 } 453 if (size > doinline) 454 can_inline = 1; 455 456 if (can_inline == 0) { /* can not inline, drop back to old mode */ 457 for (dl = def->def.st.decls; dl != NULL; dl = dl->next) 458 print_stat(1, &dl->decl); 459 return; 460 }; 461 462 463 464 465 flag = PUT; 466 for (j = 0; j < 2; j++) { 467 468 if (flag == PUT) 469 f_print(fout, "\n\t if (xdrs->x_op == XDR_ENCODE) {\n"); 470 else 471 f_print(fout, "\n \t return (TRUE);\n\t} else if (xdrs->x_op == XDR_DECODE) {\n"); 472 473 474 i = 0; 475 size = 0; 476 sizestr = NULL; 477 for (dl = def->def.st.decls; dl != NULL; dl = dl->next) { /* xxx */ 478 479 /* now walk down the list and check for basic types */ 480 if ((dl->decl.prefix == NULL) && ((ptr = find_type(dl->decl.type)) != NULL) && ((dl->decl.rel == REL_ALIAS) || (dl->decl.rel == REL_VECTOR))) { 481 if (i == 0) 482 cur = dl; 483 i++; 484 485 if (dl->decl.rel == REL_ALIAS) 486 size += ptr->length; 487 else { 488 /* this is required to handle arrays */ 489 490 if (sizestr == NULL) 491 plus = " "; 492 else 493 plus = "+"; 494 495 if (ptr->length != 1) 496 s_print(ptemp, " %s %s * %d", plus, dl->decl.array_max, ptr->length); 497 else 498 s_print(ptemp, " %s %s ", plus, dl->decl.array_max); 499 500 /* now concatenate to sizestr !!!! */ 501 if (sizestr == NULL) 502 sizestr = strdup(ptemp); 503 else { 504 sizestr = (char *)realloc(sizestr, strlen(sizestr) + strlen(ptemp) + 1); 505 if (sizestr == NULL) { 506 507 f_print(stderr, "Fatal error : no memory \n"); 508 crash(); 509 }; 510 sizestr = strcat(sizestr, ptemp); /* build up length of 511 * array */ 512 513 } 514 } 515 516 } else { 517 if (i > 0) 518 if (sizestr == NULL && size < doinline) { 519 /* don't expand into inline 520 * code if size < doinline */ 521 while (cur != dl) { 522 print_stat(1, &cur->decl); 523 cur = cur->next; 524 } 525 } else { 526 527 528 529 /* were already looking at a 530 * xdr_inlineable structure */ 531 if (sizestr == NULL) 532 f_print(fout, "\t buf = (int32_t *)XDR_INLINE(xdrs,%d * BYTES_PER_XDR_UNIT);", 533 size); 534 else 535 if (size == 0) 536 f_print(fout, 537 "\t buf = (int32_t *)XDR_INLINE(xdrs,%s * BYTES_PER_XDR_UNIT);", 538 sizestr); 539 else 540 f_print(fout, 541 "\t buf = (int32_t *)XDR_INLINE(xdrs,(%d + %s)* BYTES_PER_XDR_UNIT);", 542 size, sizestr); 543 544 f_print(fout, "\n\t if (buf == NULL) {\n"); 545 546 psav = cur; 547 while (cur != dl) { 548 print_stat(2, &cur->decl); 549 cur = cur->next; 550 } 551 552 f_print(fout, "\n\t }\n\t else {\n"); 553 554 cur = psav; 555 while (cur != dl) { 556 emit_inline(&cur->decl, flag); 557 cur = cur->next; 558 } 559 560 f_print(fout, "\t }\n"); 561 } 562 size = 0; 563 i = 0; 564 sizestr = NULL; 565 print_stat(1, &dl->decl); 566 } 567 568 } 569 if (i > 0) 570 if (sizestr == NULL && size < doinline) { 571 /* don't expand into inline code if size < 572 * doinline */ 573 while (cur != dl) { 574 print_stat(1, &cur->decl); 575 cur = cur->next; 576 } 577 } else { 578 579 /* were already looking at a xdr_inlineable 580 * structure */ 581 if (sizestr == NULL) 582 f_print(fout, "\t\tbuf = (int32_t *)XDR_INLINE(xdrs,%d * BYTES_PER_XDR_UNIT);", 583 size); 584 else 585 if (size == 0) 586 f_print(fout, 587 "\t\tbuf = (int32_t *)XDR_INLINE(xdrs,%s * BYTES_PER_XDR_UNIT);", 588 sizestr); 589 else 590 f_print(fout, 591 "\t\tbuf = (int32_t *)XDR_INLINE(xdrs,(%d + %s)* BYTES_PER_XDR_UNIT);", 592 size, sizestr); 593 594 f_print(fout, "\n\t\tif (buf == NULL) {\n"); 595 596 psav = cur; 597 while (cur != NULL) { 598 print_stat(2, &cur->decl); 599 cur = cur->next; 600 } 601 f_print(fout, "\n\t }\n\t else {\n"); 602 603 cur = psav; 604 while (cur != dl) { 605 emit_inline(&cur->decl, flag); 606 cur = cur->next; 607 } 608 609 f_print(fout, "\t }\n"); 610 611 } 612 flag = GET; 613 } 614 f_print(fout, "\t return(TRUE);\n\t}\n\n"); 615 616 /* now take care of XDR_FREE case */ 617 618 for (dl = def->def.st.decls; dl != NULL; dl = dl->next) 619 print_stat(1, &dl->decl); 620 } 621 622 static 623 emit_typedef(def) 624 definition *def; 625 { 626 char *prefix = def->def.ty.old_prefix; 627 char *type = def->def.ty.old_type; 628 char *amax = def->def.ty.array_max; 629 relation rel = def->def.ty.rel; 630 631 632 print_ifstat(1, prefix, type, rel, amax, "objp", def->def_name); 633 } 634 635 static 636 print_stat(indent, dec) 637 declaration *dec; 638 int indent; 639 { 640 char *prefix = dec->prefix; 641 char *type = dec->type; 642 char *amax = dec->array_max; 643 relation rel = dec->rel; 644 char name[256]; 645 646 if (isvectordef(type, rel)) { 647 s_print(name, "objp->%s", dec->name); 648 } else { 649 s_print(name, "&objp->%s", dec->name); 650 } 651 print_ifstat(indent, prefix, type, rel, amax, name, dec->name); 652 } 653 654 655 char *upcase __P((char *)); 656 657 658 emit_inline(decl, flag) 659 declaration *decl; 660 int flag; 661 { 662 663 /*check whether an array or not */ 664 665 switch (decl->rel) { 666 case REL_ALIAS: 667 emit_single_in_line(decl, flag, REL_ALIAS); 668 break; 669 case REL_VECTOR: 670 f_print(fout, "\t\t{ register %s *genp; \n", decl->type); 671 f_print(fout, "\t\t for ( i = 0,genp=objp->%s;\n \t\t\ti < %s; i++){\n\t\t", 672 decl->name, decl->array_max); 673 emit_single_in_line(decl, flag, REL_VECTOR); 674 f_print(fout, "\t\t }\n\t\t };\n"); 675 676 } 677 } 678 679 emit_single_in_line(decl, flag, rel) 680 declaration *decl; 681 int flag; 682 relation rel; 683 { 684 char *upp_case; 685 int freed = 0; 686 687 688 689 if (flag == PUT) 690 f_print(fout, "\t\t IXDR_PUT_"); 691 else 692 if (rel == REL_ALIAS) 693 f_print(fout, "\t\t objp->%s = IXDR_GET_", decl->name); 694 else 695 f_print(fout, "\t\t *genp++ = IXDR_GET_"); 696 697 upp_case = upcase(decl->type); 698 699 /* hack - XX */ 700 if (strcmp(upp_case, "INT") == 0) { 701 free(upp_case); 702 freed = 1; 703 upp_case = "LONG"; 704 } 705 if (strcmp(upp_case, "U_INT") == 0) { 706 free(upp_case); 707 freed = 1; 708 upp_case = "U_LONG"; 709 } 710 if (flag == PUT) 711 if (rel == REL_ALIAS) 712 f_print(fout, "%s(buf,objp->%s);\n", upp_case, decl->name); 713 else 714 f_print(fout, "%s(buf,*genp++);\n", upp_case); 715 716 else 717 f_print(fout, "%s(buf);\n", upp_case); 718 if (!freed) 719 free(upp_case); 720 721 } 722 723 724 char * 725 upcase(str) 726 char *str; 727 { 728 char *ptr, *hptr; 729 730 731 ptr = (char *) malloc(strlen(str)+1); 732 if (ptr == (char *) NULL) { 733 f_print(stderr, "malloc failed \n"); 734 exit(1); 735 }; 736 737 hptr = ptr; 738 while (*str != '\0') 739 *ptr++ = toupper(*str++); 740 741 *ptr = '\0'; 742 return (hptr); 743 744 } 745