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