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