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