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