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