1 /* $NetBSD: rpc_cout.c,v 1.17 2000/10/11 14:46:16 is 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.17 2000/10/11 14:46:16 is 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 char _t_kludge[32]; 197 198 /* 199 * XXX Solaris seems to strip the _t. No idea why. 200 */ 201 if (!strcmp(name, "rpcprog_t") || !strcmp(name, "rpcvers_t") || 202 !strcmp(name, "rpcproc_t") || !strcmp(name, "rpcprot_t") || 203 !strcmp(name, "rpcport_t") || !strcmp(name, "rpcpinline_t")) { 204 strncpy(_t_kludge, name, strlen(name) - 2); 205 name = _t_kludge; 206 } 207 tabify(fout, indent); 208 f_print(fout, "if (!xdr_%s(xdrs", name); 209 } 210 211 static void 212 print_ifarg(arg) 213 char *arg; 214 { 215 f_print(fout, ", %s", arg); 216 } 217 218 static void 219 print_ifsizeof(prefix, type) 220 char *prefix; 221 char *type; 222 { 223 if (streq(type, "bool")) { 224 f_print(fout, ", sizeof(bool_t), (xdrproc_t)xdr_bool"); 225 } else { 226 f_print(fout, ", sizeof("); 227 if (undefined(type) && prefix) { 228 f_print(fout, "%s ", prefix); 229 } 230 f_print(fout, "%s), (xdrproc_t)xdr_%s", type, type); 231 } 232 } 233 234 static void 235 print_ifclose(indent) 236 int indent; 237 { 238 f_print(fout, "))\n"); 239 tabify(fout, indent); 240 f_print(fout, "\treturn (FALSE);\n"); 241 } 242 243 static void 244 print_ifstat(indent, prefix, type, rel, amax, objname, name) 245 int indent; 246 char *prefix; 247 char *type; 248 relation rel; 249 char *amax; 250 char *objname; 251 char *name; 252 { 253 char *alt = NULL; 254 255 switch (rel) { 256 case REL_POINTER: 257 print_ifopen(indent, "pointer"); 258 print_ifarg("(char **)"); 259 f_print(fout, "%s", objname); 260 print_ifsizeof(prefix, type); 261 break; 262 case REL_VECTOR: 263 if (streq(type, "string")) { 264 alt = "string"; 265 } else 266 if (streq(type, "opaque")) { 267 alt = "opaque"; 268 } 269 if (alt) { 270 print_ifopen(indent, alt); 271 print_ifarg(objname); 272 } else { 273 print_ifopen(indent, "vector"); 274 print_ifarg("(char *)"); 275 f_print(fout, "%s", objname); 276 } 277 print_ifarg(amax); 278 if (!alt) { 279 print_ifsizeof(prefix, type); 280 } 281 break; 282 case REL_ARRAY: 283 if (streq(type, "string")) { 284 alt = "string"; 285 } else 286 if (streq(type, "opaque")) { 287 alt = "bytes"; 288 } 289 if (streq(type, "string")) { 290 print_ifopen(indent, alt); 291 print_ifarg(objname); 292 } else { 293 if (alt) { 294 print_ifopen(indent, alt); 295 } else { 296 print_ifopen(indent, "array"); 297 } 298 print_ifarg("(char **)"); 299 if (*objname == '&') { 300 f_print(fout, "%s.%s_val, (u_int *)%s.%s_len", 301 objname, name, objname, name); 302 } else { 303 f_print(fout, "&%s->%s_val, (u_int *)&%s->%s_len", 304 objname, name, objname, name); 305 } 306 } 307 print_ifarg(amax); 308 if (!alt) { 309 print_ifsizeof(prefix, type); 310 } 311 break; 312 case REL_ALIAS: 313 print_ifopen(indent, type); 314 print_ifarg(objname); 315 break; 316 } 317 print_ifclose(indent); 318 } 319 /* ARGSUSED */ 320 static void 321 emit_enum(def) 322 definition *def; 323 { 324 fprintf(fout, "\n"); 325 print_ifopen(1, "enum"); 326 print_ifarg("(enum_t *)objp"); 327 print_ifclose(1); 328 } 329 330 static void 331 emit_program(def) 332 definition *def; 333 { 334 decl_list *dl; 335 version_list *vlist; 336 proc_list *plist; 337 338 for (vlist = def->def.pr.versions; vlist != NULL; vlist = vlist->next) 339 for (plist = vlist->procs; plist != NULL; plist = plist->next) { 340 if (!newstyle || plist->arg_num < 2) 341 continue; /* old style, or single 342 * argument */ 343 print_prog_header(plist); 344 for (dl = plist->args.decls; dl != NULL; 345 dl = dl->next) 346 print_stat(1, &dl->decl); 347 print_trailer(); 348 } 349 } 350 351 352 static void 353 emit_union(def) 354 definition *def; 355 { 356 declaration *dflt; 357 case_list *cl; 358 declaration *cs; 359 char *object; 360 const char vecformat[] = "objp->%s_u.%s"; 361 const char format[] = "&objp->%s_u.%s"; 362 363 f_print(fout, "\n"); 364 print_stat(1, &def->def.un.enum_decl); 365 f_print(fout, "\tswitch (objp->%s) {\n", def->def.un.enum_decl.name); 366 for (cl = def->def.un.cases; cl != NULL; cl = cl->next) { 367 f_print(fout, "\tcase %s:\n", cl->case_name); 368 if (cl->contflag == 1) /* a continued case statement */ 369 continue; 370 cs = &cl->case_decl; 371 if (!streq(cs->type, "void")) { 372 object = alloc(strlen(def->def_name) + strlen(format) + 373 strlen(cs->name) + 1); 374 if (isvectordef(cs->type, cs->rel)) { 375 s_print(object, vecformat, def->def_name, 376 cs->name); 377 } else { 378 s_print(object, format, def->def_name, 379 cs->name); 380 } 381 print_ifstat(2, cs->prefix, cs->type, cs->rel, 382 cs->array_max, object, cs->name); 383 free(object); 384 } 385 f_print(fout, "\t\tbreak;\n"); 386 } 387 dflt = def->def.un.default_decl; 388 f_print(fout, "\tdefault:\n"); 389 if (dflt != NULL) { 390 if (!streq(dflt->type, "void")) { 391 object = alloc(strlen(def->def_name) + strlen(format) + 392 strlen(dflt->name) + 1); 393 if (isvectordef(dflt->type, dflt->rel)) { 394 s_print(object, vecformat, def->def_name, 395 dflt->name); 396 } else { 397 s_print(object, format, def->def_name, 398 dflt->name); 399 } 400 print_ifstat(2, dflt->prefix, dflt->type, dflt->rel, 401 dflt->array_max, object, dflt->name); 402 free(object); 403 } 404 f_print(fout, "\t\tbreak;\n"); 405 } else { 406 f_print(fout, "\t\treturn (FALSE);\n"); 407 } 408 409 f_print(fout, "\t}\n"); 410 } 411 412 static void 413 emit_struct(def) 414 definition *def; 415 { 416 decl_list *dl; 417 int i, j, size, flag; 418 decl_list *cur = NULL, *psav; 419 bas_type *ptr; 420 char *sizestr, *plus; 421 char ptemp[256]; 422 int can_inline; 423 424 425 if (doinline == 0) { 426 fprintf(fout, "\n"); 427 for (dl = def->def.st.decls; dl != NULL; dl = dl->next) 428 print_stat(1, &dl->decl); 429 return; 430 } 431 size = 0; 432 can_inline = 0; 433 for (dl = def->def.st.decls; dl != NULL; dl = dl->next) 434 if ((dl->decl.prefix == NULL) && 435 ((ptr = find_type(dl->decl.type)) != NULL) && 436 ((dl->decl.rel == REL_ALIAS) || (dl->decl.rel == REL_VECTOR))) { 437 438 if (dl->decl.rel == REL_ALIAS) 439 size += ptr->length; 440 else { 441 can_inline = 1; 442 break; /* can be inlined */ 443 }; 444 } else { 445 if (size >= doinline) { 446 can_inline = 1; 447 break; /* can be inlined */ 448 } 449 size = 0; 450 } 451 if (size > doinline) 452 can_inline = 1; 453 454 if (can_inline == 0) { /* can not inline, drop back to old mode */ 455 fprintf(fout, "\n"); 456 for (dl = def->def.st.decls; dl != NULL; dl = dl->next) 457 print_stat(1, &dl->decl); 458 return; 459 }; 460 461 /* May cause lint to complain. but ... */ 462 f_print(fout, "\tint32_t *buf;\n"); 463 464 flag = PUT; 465 f_print(fout, "\n\tif (xdrs->x_op == XDR_ENCODE) {\n"); 466 467 for (j = 0; j < 2; j++) { 468 i = 0; 469 size = 0; 470 sizestr = NULL; 471 for (dl = def->def.st.decls; dl != NULL; dl = dl->next) { /* xxx */ 472 473 /* now walk down the list and check for basic types */ 474 if ((dl->decl.prefix == NULL) && ((ptr = find_type(dl->decl.type)) != NULL) && ((dl->decl.rel == REL_ALIAS) || (dl->decl.rel == REL_VECTOR))) { 475 if (i == 0) 476 cur = dl; 477 i++; 478 479 if (dl->decl.rel == REL_ALIAS) 480 size += ptr->length; 481 else { 482 /* this is required to handle arrays */ 483 484 if (sizestr == NULL) 485 plus = ""; 486 else 487 plus = " + "; 488 489 if (ptr->length != 1) 490 s_print(ptemp, "%s%s * %d", plus, dl->decl.array_max, ptr->length); 491 else 492 s_print(ptemp, "%s%s", plus, dl->decl.array_max); 493 494 /* now concatenate to sizestr !!!! */ 495 if (sizestr == NULL) 496 sizestr = strdup(ptemp); 497 else { 498 sizestr = (char *) realloc(sizestr, strlen(sizestr) + strlen(ptemp) + 1); 499 if (sizestr == NULL) { 500 501 f_print(stderr, "Fatal error : no memory\n"); 502 crash(); 503 }; 504 sizestr = strcat(sizestr, ptemp); /* build up length of 505 * array */ 506 507 } 508 } 509 510 } else { 511 if (i > 0) { 512 if (sizestr == NULL && size < doinline) { 513 /* don't expand into inline 514 * code if size < doinline */ 515 while (cur != dl) { 516 print_stat(2, &cur->decl); 517 cur = cur->next; 518 } 519 } else { 520 521 522 523 /* were already looking at a 524 * xdr_inlineable structure */ 525 if (sizestr == NULL) 526 f_print(fout, "\t\tbuf = (int32_t *)XDR_INLINE(xdrs, %d * BYTES_PER_XDR_UNIT);\n", 527 size); 528 else 529 if (size == 0) 530 f_print(fout, 531 "\t\tbuf = (int32_t *)XDR_INLINE(xdrs, %s * BYTES_PER_XDR_UNIT);\n", 532 sizestr); 533 else 534 f_print(fout, 535 "\t\tbuf = (int32_t *)XDR_INLINE(xdrs, (%d + %s) * BYTES_PER_XDR_UNIT);\n", 536 size, sizestr); 537 538 f_print(fout, "\t\tif (buf == NULL) {\n"); 539 540 psav = cur; 541 while (cur != dl) { 542 print_stat(3, &cur->decl); 543 cur = cur->next; 544 } 545 546 f_print(fout, "\t\t} else {\n"); 547 548 cur = psav; 549 while (cur != dl) { 550 emit_inline(&cur->decl, flag); 551 cur = cur->next; 552 } 553 554 f_print(fout, "\t\t}\n"); 555 } 556 } 557 size = 0; 558 i = 0; 559 sizestr = NULL; 560 print_stat(2, &dl->decl); 561 } 562 563 } 564 if (i > 0) { 565 if (sizestr == NULL && size < doinline) { 566 /* don't expand into inline code if size < 567 * doinline */ 568 while (cur != dl) { 569 print_stat(2, &cur->decl); 570 cur = cur->next; 571 } 572 } else { 573 574 /* were already looking at a xdr_inlineable 575 * structure */ 576 if (sizestr == NULL) 577 f_print(fout, "\t\tbuf = (int32_t *)XDR_INLINE(xdrs, %d * BYTES_PER_XDR_UNIT);\n", 578 size); 579 else 580 if (size == 0) 581 f_print(fout, 582 "\t\tbuf = (int32_t *)XDR_INLINE(xdrs, %s * BYTES_PER_XDR_UNIT);\n", 583 sizestr); 584 else 585 f_print(fout, 586 "\t\tbuf = (int32_t *)XDR_INLINE(xdrs, (%d + %s) * BYTES_PER_XDR_UNIT);\n", 587 size, sizestr); 588 589 f_print(fout, "\t\tif (buf == NULL) {\n"); 590 591 psav = cur; 592 while (cur != NULL) { 593 print_stat(3, &cur->decl); 594 cur = cur->next; 595 } 596 f_print(fout, "\t\t} else {\n"); 597 598 cur = psav; 599 while (cur != dl) { 600 emit_inline(&cur->decl, flag); 601 cur = cur->next; 602 } 603 604 f_print(fout, "\t\t}\n"); 605 606 } 607 } 608 if (flag == PUT) { 609 flag = GET; 610 f_print(fout, "\t} else if (xdrs->x_op == XDR_DECODE) {\n"); 611 } 612 } 613 614 f_print(fout, "\t} else {\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(2, &dl->decl); 620 621 f_print(fout, "\t}\n"); 622 } 623 624 static void 625 emit_typedef(def) 626 definition *def; 627 { 628 char *prefix = def->def.ty.old_prefix; 629 char *type = def->def.ty.old_type; 630 char *amax = def->def.ty.array_max; 631 relation rel = def->def.ty.rel; 632 633 fprintf(fout, "\n"); 634 print_ifstat(1, prefix, type, rel, amax, "objp", def->def_name); 635 } 636 637 static void 638 print_stat(indent, dec) 639 declaration *dec; 640 int indent; 641 { 642 char *prefix = dec->prefix; 643 char *type = dec->type; 644 char *amax = dec->array_max; 645 relation rel = dec->rel; 646 char name[256]; 647 648 if (isvectordef(type, rel)) { 649 s_print(name, "objp->%s", dec->name); 650 } else { 651 s_print(name, "&objp->%s", dec->name); 652 } 653 print_ifstat(indent, prefix, type, rel, amax, name, dec->name); 654 } 655 656 657 void 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\t{\n"); 671 f_print(fout, "\t\t\t\tint i;\n"); 672 f_print(fout, "\t\t\t\t%s *genp;\n", decl->type); 673 f_print(fout, "\n"); 674 f_print(fout, "\t\t\t\tfor (i = 0, genp = objp->%s;\n", 675 decl->name); 676 f_print(fout, "\t\t\t\t i < %s; i++) {\n\t\t", 677 decl->array_max); 678 emit_single_in_line(decl, flag, REL_VECTOR); 679 f_print(fout, "\t\t\t\t}\n\t\t\t}\n"); 680 break; 681 case REL_ARRAY: 682 case REL_POINTER: 683 errx(1, "Internal error %s, %d: Case %d not handled\n", 684 __FILE__, __LINE__, decl->rel); 685 } 686 } 687 688 void 689 emit_single_in_line(decl, flag, rel) 690 declaration *decl; 691 int flag; 692 relation rel; 693 { 694 char *upp_case; 695 int freed = 0; 696 697 if (flag == PUT) 698 f_print(fout, "\t\t\tIXDR_PUT_"); 699 else 700 if (rel == REL_ALIAS) 701 f_print(fout, "\t\t\tobjp->%s = IXDR_GET_", decl->name); 702 else 703 f_print(fout, "\t\t\t*genp++ = IXDR_GET_"); 704 705 upp_case = upcase(decl->type); 706 707 /* hack - XX */ 708 if (strcmp(upp_case, "INT") == 0) { 709 free(upp_case); 710 freed = 1; 711 upp_case = "LONG"; 712 } 713 if (strcmp(upp_case, "U_INT") == 0) { 714 free(upp_case); 715 freed = 1; 716 upp_case = "U_LONG"; 717 } 718 if (flag == PUT) { 719 if (rel == REL_ALIAS) 720 f_print(fout, "%s(buf, objp->%s);\n", upp_case, decl->name); 721 else 722 f_print(fout, "%s(buf, *genp++);\n", upp_case); 723 724 } else 725 f_print(fout, "%s(buf);\n", upp_case); 726 if (!freed) 727 free(upp_case); 728 729 } 730 731 732 char * 733 upcase(str) 734 char *str; 735 { 736 char *ptr, *hptr; 737 738 739 ptr = (char *) malloc(strlen(str) + 1); 740 if (ptr == (char *) NULL) { 741 f_print(stderr, "malloc failed\n"); 742 exit(1); 743 }; 744 745 hptr = ptr; 746 while (*str != '\0') 747 *ptr++ = toupper(*str++); 748 749 *ptr = '\0'; 750 return (hptr); 751 752 } 753