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