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