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