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