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