1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright 2014 Garrett D'Amore <garrett@damore.org>
  24  *
  25  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  26  * Use is subject to license terms.
  27  */
  28 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
  29 /* All Rights Reserved */
  30 /*
  31  * University Copyright- Copyright (c) 1982, 1986, 1988
  32  * The Regents of the University of California
  33  * All Rights Reserved
  34  *
  35  * University Acknowledgment- Portions of this document are derived from
  36  * software developed by the University of California, Berkeley, and its
  37  * contributors.
  38  */
  39 
  40 /*
  41  * rpc_cout.c, XDR routine outputter for the RPC protocol compiler
  42  */
  43 #include <stdio.h>
  44 #include <stdlib.h>
  45 #include <string.h>
  46 #include <ctype.h>
  47 #include "rpc_parse.h"
  48 #include "rpc_util.h"
  49 
  50 extern void crash(void);
  51 
  52 static void print_header(definition *);
  53 static void print_trailer(void);
  54 static void emit_enum(definition *);
  55 static void emit_program(definition *);
  56 static void emit_union(definition *);
  57 static void emit_struct(definition *);
  58 static void emit_typedef(definition *);
  59 static void print_stat(int, declaration *);
  60 static void emit_inline(int, declaration *, int);
  61 static void emit_inline64(int, declaration *, int);
  62 static void emit_single_in_line(int, declaration *, int, relation);
  63 static void emit_single_in_line64(int, declaration *, int, relation);
  64 static char *upcase(char *);
  65 
  66 /*
  67  * Emit the C-routine for the given definition
  68  */
  69 void
  70 emit(definition *def)
  71 {
  72         if (def->def_kind == DEF_CONST)
  73                 return;
  74         if (def->def_kind == DEF_PROGRAM) {
  75                 emit_program(def);
  76                 return;
  77         }
  78         if (def->def_kind == DEF_TYPEDEF) {
  79                 /*
  80                  * now we need to handle declarations like
  81                  * struct typedef foo foo;
  82                  * since we dont want this to be expanded into 2 calls
  83                  * to xdr_foo
  84                  */
  85 
  86                 if (strcmp(def->def.ty.old_type, def->def_name) == 0)
  87                         return;
  88         };
  89         print_header(def);
  90         switch (def->def_kind) {
  91         case DEF_UNION:
  92                 emit_union(def);
  93                 break;
  94         case DEF_ENUM:
  95                 emit_enum(def);
  96                 break;
  97         case DEF_STRUCT:
  98                 emit_struct(def);
  99                 break;
 100         case DEF_TYPEDEF:
 101                 emit_typedef(def);
 102                 break;
 103         }
 104         print_trailer();
 105 }
 106 
 107 static int
 108 findtype(definition *def, char *type)
 109 {
 110 
 111         if (def->def_kind == DEF_PROGRAM || def->def_kind == DEF_CONST)
 112                 return (0);
 113         return (streq(def->def_name, type));
 114 }
 115 
 116 static int
 117 undefined(char *type)
 118 {
 119         definition *def;
 120 
 121         def = (definition *)FINDVAL(defined, type, findtype);
 122         return (def == NULL);
 123 }
 124 
 125 
 126 static void
 127 print_generic_header(char *procname, int pointerp)
 128 {
 129         f_print(fout, "\n");
 130         f_print(fout, "bool_t\n");
 131         f_print(fout, "xdr_%s(", procname);
 132         f_print(fout, "XDR *xdrs, ");
 133         f_print(fout, "%s ", procname);
 134         if (pointerp)
 135                 f_print(fout, "*");
 136         f_print(fout, "objp)\n{\n\n");
 137 }
 138 
 139 static void
 140 print_header(definition *def)
 141 {
 142         print_generic_header(def->def_name,
 143             def->def_kind != DEF_TYPEDEF ||
 144             !isvectordef(def->def.ty.old_type, def->def.ty.rel));
 145         /* Now add Inline support */
 146 
 147         if (inlinelen == 0)
 148                 return;
 149         /* May cause lint to complain. but  ... */
 150         f_print(fout, "\trpc_inline_t *buf;\n\n");
 151 }
 152 
 153 static void
 154 print_prog_header(proc_list *plist)
 155 {
 156         print_generic_header(plist->args.argname, 1);
 157 }
 158 
 159 static void
 160 print_trailer(void)
 161 {
 162         f_print(fout, "\treturn (TRUE);\n");
 163         f_print(fout, "}\n");
 164 }
 165 
 166 
 167 static void
 168 print_ifopen(int indent, char *name)
 169 {
 170         tabify(fout, indent);
 171         if (streq(name, "rpcprog_t") ||
 172             streq(name, "rpcvers_t") ||
 173             streq(name, "rpcproc_t") ||
 174             streq(name, "rpcprot_t") ||
 175             streq(name, "rpcport_t"))
 176                 (void) strtok(name, "_");
 177         f_print(fout, "if (!xdr_%s(xdrs", name);
 178 }
 179 
 180 static void
 181 print_ifarg(char *arg)
 182 {
 183         f_print(fout, ", %s", arg);
 184 }
 185 
 186 static void
 187 print_ifsizeof(int indent, char *prefix, char *type)
 188 {
 189         if (indent) {
 190                 f_print(fout, ",\n");
 191                 tabify(fout, indent);
 192         } else {
 193                 f_print(fout, ", ");
 194         }
 195         if (streq(type, "bool")) {
 196                 f_print(fout, "sizeof (bool_t), (xdrproc_t)xdr_bool");
 197         } else {
 198                 f_print(fout, "sizeof (");
 199                 if (undefined(type) && prefix) {
 200                         f_print(fout, "%s ", prefix);
 201                 }
 202                 f_print(fout, "%s), (xdrproc_t)xdr_%s", type, type);
 203         }
 204 }
 205 
 206 static void
 207 print_ifclose(int indent)
 208 {
 209         f_print(fout, "))\n");
 210         tabify(fout, indent);
 211         f_print(fout, "\treturn (FALSE);\n");
 212 }
 213 
 214 static void
 215 print_ifstat(int indent, char *prefix, char *type, relation rel,
 216                                         char *amax, char *objname, char *name)
 217 {
 218         char *alt = NULL;
 219 
 220         switch (rel) {
 221         case REL_POINTER:
 222                 print_ifopen(indent, "pointer");
 223                 print_ifarg("(char **)");
 224                 f_print(fout, "%s", objname);
 225                 print_ifsizeof(0, prefix, type);
 226                 break;
 227         case REL_VECTOR:
 228                 if (streq(type, "string"))
 229                         alt = "string";
 230                 else if (streq(type, "opaque"))
 231                         alt = "opaque";
 232                 if (alt) {
 233                         print_ifopen(indent, alt);
 234                         print_ifarg(objname);
 235                 } else {
 236                         print_ifopen(indent, "vector");
 237                         print_ifarg("(char *)");
 238                         f_print(fout, "%s", objname);
 239                 }
 240                 print_ifarg(amax);
 241                 if (!alt)
 242                         print_ifsizeof(indent + 1, prefix, type);
 243                 break;
 244         case REL_ARRAY:
 245                 if (streq(type, "string"))
 246                         alt = "string";
 247                 else if (streq(type, "opaque"))
 248                         alt = "bytes";
 249                 if (streq(type, "string")) {
 250                         print_ifopen(indent, alt);
 251                         print_ifarg(objname);
 252                 } else {
 253                         if (alt)
 254                                 print_ifopen(indent, alt);
 255                         else
 256                                 print_ifopen(indent, "array");
 257                         print_ifarg("(char **)");
 258                         if (*objname == '&')
 259                                 f_print(fout, "%s.%s_val, (u_int *) %s.%s_len",
 260                                     objname, name, objname, name);
 261                         else
 262                                 f_print(fout,
 263                                     "&%s->%s_val, (u_int *) &%s->%s_len",
 264                                     objname, name, objname, name);
 265                 }
 266                 print_ifarg(amax);
 267                 if (!alt)
 268                         print_ifsizeof(indent + 1, prefix, type);
 269                 break;
 270         case REL_ALIAS:
 271                 print_ifopen(indent, type);
 272                 print_ifarg(objname);
 273                 break;
 274         }
 275         print_ifclose(indent);
 276 }
 277 
 278 /* ARGSUSED */
 279 static void
 280 emit_enum(definition *def)
 281 {
 282         print_ifopen(1, "enum");
 283         print_ifarg("(enum_t *)objp");
 284         print_ifclose(1);
 285 }
 286 
 287 static void
 288 emit_program(definition *def)
 289 {
 290         decl_list *dl;
 291         version_list *vlist;
 292         proc_list *plist;
 293 
 294         for (vlist = def->def.pr.versions; vlist != NULL; vlist = vlist->next)
 295                 for (plist = vlist->procs; plist != NULL; plist = plist->next) {
 296                         if (!newstyle || plist->arg_num < 2)
 297                                 continue; /* old style, or single argument */
 298                         print_prog_header(plist);
 299                         for (dl = plist->args.decls; dl != NULL;
 300                             dl = dl->next)
 301                                 print_stat(1, &dl->decl);
 302                         print_trailer();
 303                 }
 304 }
 305 
 306 
 307 static void
 308 emit_union(definition *def)
 309 {
 310         declaration *dflt;
 311         case_list *cl;
 312         declaration *cs;
 313         char *object;
 314 
 315         print_stat(1, &def->def.un.enum_decl);
 316         f_print(fout, "\tswitch (objp->%s) {\n", def->def.un.enum_decl.name);
 317         for (cl = def->def.un.cases; cl != NULL; cl = cl->next) {
 318 
 319                 f_print(fout, "\tcase %s:\n", cl->case_name);
 320                 if (cl->contflag == 1) /* a continued case statement */
 321                         continue;
 322                 cs = &cl->case_decl;
 323                 if (!streq(cs->type, "void")) {
 324                         size_t len = strlen(def->def_name) +
 325                             strlen("&objp->%s_u.%s") +
 326                             strlen(cs->name) + 1;
 327                         object = malloc(len);
 328                         if (isvectordef(cs->type, cs->rel))
 329                                 (void) snprintf(object, len, "objp->%s_u.%s",
 330                                     def->def_name, cs->name);
 331                         else
 332                                 (void) snprintf(object, len, "&objp->%s_u.%s",
 333                                     def->def_name, cs->name);
 334                         print_ifstat(2, cs->prefix, cs->type, cs->rel,
 335                             cs->array_max, object, cs->name);
 336                         free(object);
 337                 }
 338                 f_print(fout, "\t\tbreak;\n");
 339         }
 340         dflt = def->def.un.default_decl;
 341         if (dflt != NULL) {
 342                 if (!streq(dflt->type, "void")) {
 343                         size_t len = strlen(def->def_name) +
 344                             strlen("&objp->%s_u.%s") +
 345                             strlen(dflt->name) + 1;
 346                         f_print(fout, "\tdefault:\n");
 347                         object = malloc(len);
 348                         if (isvectordef(dflt->type, dflt->rel))
 349                                 (void) snprintf(object, len, "objp->%s_u.%s",
 350                                     def->def_name, dflt->name);
 351                         else
 352                                 (void) snprintf(object, len, "&objp->%s_u.%s",
 353                                     def->def_name, dflt->name);
 354 
 355                         print_ifstat(2, dflt->prefix, dflt->type, dflt->rel,
 356                             dflt->array_max, object, dflt->name);
 357                         free(object);
 358                         f_print(fout, "\t\tbreak;\n");
 359                 }
 360         } else {
 361                 f_print(fout, "\tdefault:\n");
 362                 f_print(fout, "\t\treturn (FALSE);\n");
 363         }
 364 
 365         f_print(fout, "\t}\n");
 366 }
 367 
 368 static void
 369 expand_inline(int indent, const char *sizestr,
 370     int size, int flag, decl_list *dl, decl_list *cur)
 371 {
 372         decl_list *psav;
 373 
 374         /*
 375          * were already looking at a xdr_inlineable structure
 376          */
 377         tabify(fout, indent + 1);
 378         if (sizestr == NULL)
 379                 f_print(fout,
 380                     "buf = XDR_INLINE(xdrs, %d * BYTES_PER_XDR_UNIT);",
 381                     size);
 382         else if (size == 0)
 383                 f_print(fout,
 384                     "buf = XDR_INLINE(xdrs, (%s) * BYTES_PER_XDR_UNIT);",
 385                     sizestr);
 386         else
 387                 f_print(fout,
 388                     "buf = XDR_INLINE(xdrs, (%d + (%s)) "
 389                     "* BYTES_PER_XDR_UNIT);", size, sizestr);
 390 
 391         f_print(fout, "\n");
 392         tabify(fout, indent + 1);
 393         f_print(fout, "if (buf == NULL) {\n");
 394 
 395         psav = cur;
 396         while (cur != dl) {
 397                 print_stat(indent + 2,
 398                     &cur->decl);
 399                 cur = cur->next;
 400         }
 401 
 402         tabify(fout, indent+1);
 403         f_print(fout, "} else {\n");
 404 
 405         f_print(fout, "#if defined(_LP64) || defined(_KERNEL)\n");
 406         cur = psav;
 407         while (cur != dl) {
 408                 emit_inline64(indent + 2, &cur->decl, flag);
 409                 cur = cur->next;
 410         }
 411         f_print(fout, "#else\n");
 412         cur = psav;
 413         while (cur != dl) {
 414                 emit_inline(indent + 2, &cur->decl, flag);
 415                 cur = cur->next;
 416         }
 417         f_print(fout, "#endif\n");
 418 
 419         tabify(fout, indent + 1);
 420         f_print(fout, "}\n");
 421 }
 422 
 423 /*
 424  * An inline type is a base type (interger type) or a vector of base types.
 425  */
 426 static int
 427 inline_type(declaration *dc, int *size)
 428 {
 429         bas_type *ptr;
 430 
 431         *size = 0;
 432 
 433         if (dc->prefix == NULL &&
 434             (dc->rel == REL_ALIAS || dc->rel == REL_VECTOR)) {
 435                 ptr = find_type(dc->type);
 436                 if (ptr != NULL) {
 437                         *size = ptr->length;
 438                         return (1);
 439                 }
 440         }
 441 
 442         return (0);
 443 }
 444 
 445 static char *
 446 arraysize(char *sz, declaration *dc, int elsize)
 447 {
 448         int len;
 449         int elsz = elsize;
 450         int digits;
 451         int slen = 0;
 452         char *plus = "";
 453         char *tmp;
 454         size_t tlen;
 455 
 456         /*
 457          * Calculate the size of a string to hold the size of all arrays
 458          * to be inlined.
 459          *
 460          * We have the string representation of the total size that has already
 461          * been seen. (Null if this is the first array).
 462          * We have the string representation of array max from the declaration,
 463          * optionally the plus string, " + ", if this is not the first array,
 464          * and the number of digits for the element size for this declaration.
 465          */
 466         if (sz != NULL) {
 467                 plus = " + ";
 468                 slen = strlen(sz);
 469         }
 470 
 471         /* Calculate the number of digits to hold the element size */
 472         for (digits = 1; elsz >= 10; digits++)
 473                 elsz /= 10;
 474 
 475         /*
 476          * If elsize != 1 the allocate 3 extra bytes for the times
 477          * string, " * ", the "()" below,  and the digits. One extra
 478          * for the trailing NULL
 479          */
 480         len = strlen(dc->array_max) +  (elsize == 1 ? 0 : digits + 5) + 1;
 481         tlen = slen + len + strlen(plus);
 482         tmp = realloc(sz, tlen);
 483         if (tmp == NULL) {
 484                 f_print(stderr, "Fatal error : no memory\n");
 485                 crash();
 486         }
 487 
 488         if (elsize == 1)
 489                 (void) snprintf(tmp + slen, tlen - slen, "%s%s",
 490                     plus, dc->array_max);
 491         else
 492                 (void) snprintf(tmp + slen, tlen - slen, "%s(%s) * %d",
 493                     plus, dc->array_max, elsize);
 494 
 495         return (tmp);
 496 }
 497 
 498 static void
 499 inline_struct(decl_list *dl, decl_list *last, int flag, int indent)
 500 {
 501         int size, tsize;
 502         decl_list *cur;
 503         char *sizestr;
 504 
 505         cur = NULL;
 506         tsize = 0;
 507         sizestr = NULL;
 508         for (; dl != last; dl = dl->next) {
 509                 if (inline_type(&dl->decl, &size)) {
 510                         if (cur == NULL)
 511                                 cur = dl;
 512 
 513                         if (dl->decl.rel == REL_ALIAS)
 514                                 tsize += size;
 515                         else {
 516                                 /* this code is required to handle arrays */
 517                                 sizestr = arraysize(sizestr, &dl->decl, size);
 518                         }
 519                 } else {
 520                         if (cur != NULL)
 521                                 if (sizestr == NULL && tsize < inlinelen) {
 522                                         /*
 523                                          * don't expand into inline code
 524                                          * if tsize < inlinelen
 525                                          */
 526                                         while (cur != dl) {
 527                                                 print_stat(indent + 1,
 528                                                     &cur->decl);
 529                                                 cur = cur->next;
 530                                         }
 531                                 } else {
 532                                         expand_inline(indent, sizestr,
 533                                             tsize, flag, dl, cur);
 534                                 }
 535                         tsize = 0;
 536                         cur = NULL;
 537                         sizestr = NULL;
 538                         print_stat(indent + 1, &dl->decl);
 539                 }
 540         }
 541 
 542         if (cur == NULL)
 543                 return;
 544         if (sizestr == NULL && tsize < inlinelen) {
 545                 /* don't expand into inline code if tsize < inlinelen */
 546                 while (cur != dl) {
 547                         print_stat(indent + 1, &cur->decl);
 548                         cur = cur->next;
 549                 }
 550         } else {
 551                 expand_inline(indent, sizestr, tsize, flag, dl, cur);
 552         }
 553 }
 554 
 555 /*
 556  * Check if we can inline this structure. While we are at it check if the
 557  * declaration list has any vectors defined of "basic" types.
 558  */
 559 static int
 560 check_inline(decl_list *dl, int inlinelen, int *have_vector)
 561 {
 562         int tsize = 0;
 563         int size;
 564         int doinline = 0;
 565 
 566         *have_vector = 0;
 567         if (inlinelen == 0)
 568                 return (0);
 569 
 570         for (; dl != NULL; dl = dl->next) {
 571                 if (!inline_type(&dl->decl, &size)) {
 572                         tsize = 0;
 573                         continue;
 574                 }
 575                 if (dl->decl.rel == REL_VECTOR) {
 576                         *have_vector = 1;
 577                         return (1);
 578                 }
 579                 tsize += size;
 580                 if (tsize >= inlinelen)
 581                         doinline = 1;
 582         }
 583 
 584         return (doinline);
 585 }
 586 
 587 
 588 static void
 589 emit_struct_tail_recursion(definition *defp, int can_inline)
 590 {
 591         int indent = 3;
 592         struct_def *sp = &defp->def.st;
 593         decl_list *dl;
 594 
 595 
 596         f_print(fout, "\t%s *tmp_%s;\n",
 597             defp->def_name, defp->def_name);
 598 
 599         f_print(fout, "\tbool_t more_data = TRUE;\n");
 600         f_print(fout, "\tbool_t first_objp = TRUE;\n\n");
 601 
 602         f_print(fout, "\n\tif (xdrs->x_op == XDR_DECODE) {\n");
 603         f_print(fout, "\n\t\twhile (more_data) {\n");
 604         f_print(fout, "\n\t\t\tvoid bzero();\n\n");
 605 
 606         if (can_inline)
 607                 inline_struct(sp->decls, sp->tail, GET, indent);
 608         else
 609                 for (dl = sp->decls; dl != NULL && dl != sp->tail;
 610                     dl = dl->next)
 611                         print_stat(indent, &dl->decl);
 612 
 613         f_print(fout, "\t\t\tif (!xdr_bool(xdrs, "
 614             "&more_data))\n\t\t\t\treturn (FALSE);\n");
 615 
 616         f_print(fout, "\n\t\t\tif (!more_data) {\n");
 617         f_print(fout, "\t\t\t\tobjp->%s = NULL;\n", sp->tail->decl.name);
 618         f_print(fout, "\t\t\t\tbreak;\n");
 619         f_print(fout, "\t\t\t}\n\n");
 620         f_print(fout, "\t\t\tif (objp->%s == NULL) {\n", sp->tail->decl.name);
 621         f_print(fout, "\t\t\t\tobjp->%s = "
 622             "(%s *)\n\t\t\t\t\tmem_alloc(sizeof (%s));\n",
 623             sp->tail->decl.name, defp->def_name, defp->def_name);
 624 
 625         f_print(fout, "\t\t\t\tif (objp->%s == NULL)\n"
 626             "\t\t\t\t\treturn (FALSE);\n", sp->tail->decl.name);
 627         f_print(fout, "\t\t\t\tbzero(objp->%s, sizeof (%s));\n",
 628             sp->tail->decl.name, defp->def_name);
 629         f_print(fout, "\t\t\t}\n");
 630         f_print(fout, "\t\t\tobjp = objp->%s;\n", sp->tail->decl.name);
 631         f_print(fout, "\t\t}\n");
 632 
 633         f_print(fout, "\n\t} else if (xdrs->x_op == XDR_ENCODE) {\n");
 634         f_print(fout, "\n\t\twhile (more_data) {\n");
 635 
 636         if (can_inline)
 637                 inline_struct(sp->decls, sp->tail, PUT, indent);
 638         else
 639                 for (dl = sp->decls; dl != NULL && dl != sp->tail;
 640                     dl = dl->next)
 641                         print_stat(indent, &dl->decl);
 642 
 643         f_print(fout, "\t\t\tobjp = objp->%s;\n", sp->tail->decl.name);
 644         f_print(fout, "\t\t\tif (objp == NULL)\n");
 645         f_print(fout, "\t\t\t\tmore_data = FALSE;\n");
 646 
 647         f_print(fout, "\t\t\tif (!xdr_bool(xdrs, &more_data))\n"
 648             "\t\t\t\treturn (FALSE);\n");
 649 
 650         f_print(fout, "\t\t}\n");
 651 
 652         f_print(fout, "\n\t} else {\n");
 653         f_print(fout, "\n\t\twhile (more_data) {\n");
 654 
 655         for (dl = sp->decls; dl != NULL && dl != sp->tail; dl = dl->next)
 656                 print_stat(indent, &dl->decl);
 657 
 658         f_print(fout, "\t\t\ttmp_%s = objp;\n", defp->def_name);
 659         f_print(fout, "\t\t\tobjp = objp->%s;\n", sp->tail->decl.name);
 660 
 661         f_print(fout, "\t\t\tif (objp == NULL)\n");
 662         f_print(fout, "\t\t\t\tmore_data = FALSE;\n");
 663 
 664         f_print(fout, "\t\t\tif (!first_objp)\n");
 665 
 666         f_print(fout, "\t\t\t\tmem_free(tmp_%s, sizeof (%s));\n",
 667             defp->def_name, defp->def_name);
 668 
 669         f_print(fout, "\t\t\telse\n\t\t\t\tfirst_objp = FALSE;\n\t\t}\n");
 670 
 671         f_print(fout, "\n\t}\n");
 672 }
 673 
 674 static void
 675 emit_struct(definition *def)
 676 {
 677         decl_list *dl = def->def.st.decls;
 678         int can_inline, have_vector;
 679 
 680 
 681         can_inline = check_inline(dl, inlinelen, &have_vector);
 682         if (have_vector)
 683                 f_print(fout, "\tint i;\n");
 684 
 685 
 686         if (rflag && def->def.st.self_pointer) {
 687                 /* Handle tail recursion elimination */
 688                 emit_struct_tail_recursion(def, can_inline);
 689                 return;
 690         }
 691 
 692 
 693         if (can_inline) {
 694                 f_print(fout, "\n\tif (xdrs->x_op == XDR_ENCODE) {\n");
 695                 inline_struct(dl, NULL, PUT, 1);
 696 
 697                 f_print(fout, "\t\treturn (TRUE);\n\t}"
 698                     " else if (xdrs->x_op == XDR_DECODE) {\n");
 699 
 700                 inline_struct(dl, NULL, GET, 1);
 701                 f_print(fout, "\t\treturn (TRUE);\n\t}\n\n");
 702         }
 703 
 704         /* now take care of XDR_FREE inline  case or the non-inline cases */
 705 
 706         for (dl = def->def.st.decls; dl != NULL; dl = dl->next)
 707                 print_stat(1, &dl->decl);
 708 
 709 }
 710 
 711 static void
 712 emit_typedef(definition *def)
 713 {
 714         char *prefix = def->def.ty.old_prefix;
 715         char *type = def->def.ty.old_type;
 716         char *amax = def->def.ty.array_max;
 717         relation rel = def->def.ty.rel;
 718 
 719         print_ifstat(1, prefix, type, rel, amax, "objp", def->def_name);
 720 }
 721 
 722 static void
 723 print_stat(int indent, declaration *dec)
 724 {
 725         char *prefix = dec->prefix;
 726         char *type = dec->type;
 727         char *amax = dec->array_max;
 728         relation rel = dec->rel;
 729         char name[256];
 730 
 731         if (isvectordef(type, rel))
 732                 (void) snprintf(name, sizeof (name), "objp->%s", dec->name);
 733         else
 734                 (void) snprintf(name, sizeof (name), "&objp->%s", dec->name);
 735         print_ifstat(indent, prefix, type, rel, amax, name, dec->name);
 736 }
 737 
 738 
 739 static void
 740 emit_inline(int indent, declaration *decl, int flag)
 741 {
 742         switch (decl->rel) {
 743         case  REL_ALIAS :
 744                 emit_single_in_line(indent, decl, flag, REL_ALIAS);
 745                 break;
 746         case REL_VECTOR :
 747                 tabify(fout, indent);
 748                 f_print(fout, "{\n");
 749                 tabify(fout, indent + 1);
 750                 f_print(fout, "%s *genp;\n\n", decl->type);
 751                 tabify(fout, indent + 1);
 752                 f_print(fout,
 753                     "for (i = 0, genp = objp->%s;\n", decl->name);
 754                 tabify(fout, indent + 2);
 755                 f_print(fout, "i < %s; i++) {\n", decl->array_max);
 756                 emit_single_in_line(indent + 2, decl, flag, REL_VECTOR);
 757                 tabify(fout, indent + 1);
 758                 f_print(fout, "}\n");
 759                 tabify(fout, indent);
 760                 f_print(fout, "}\n");
 761         }
 762 }
 763 
 764 static void
 765 emit_inline64(int indent, declaration *decl, int flag)
 766 {
 767         switch (decl->rel) {
 768         case  REL_ALIAS :
 769                 emit_single_in_line64(indent, decl, flag, REL_ALIAS);
 770                 break;
 771         case REL_VECTOR :
 772                 tabify(fout, indent);
 773                 f_print(fout, "{\n");
 774                 tabify(fout, indent + 1);
 775                 f_print(fout, "%s *genp;\n\n", decl->type);
 776                 tabify(fout, indent + 1);
 777                 f_print(fout,
 778                     "for (i = 0, genp = objp->%s;\n", decl->name);
 779                 tabify(fout, indent + 2);
 780                 f_print(fout, "i < %s; i++) {\n", decl->array_max);
 781                 emit_single_in_line64(indent + 2, decl, flag, REL_VECTOR);
 782                 tabify(fout, indent + 1);
 783                 f_print(fout, "}\n");
 784                 tabify(fout, indent);
 785                 f_print(fout, "}\n");
 786         }
 787 }
 788 
 789 static void
 790 emit_single_in_line(int indent, declaration *decl, int flag, relation rel)
 791 {
 792         char *upp_case;
 793         int freed = 0;
 794 
 795         tabify(fout, indent);
 796         if (flag == PUT)
 797                 f_print(fout, "IXDR_PUT_");
 798         else
 799                 if (rel == REL_ALIAS)
 800                         f_print(fout, "objp->%s = IXDR_GET_", decl->name);
 801                 else
 802                         f_print(fout, "*genp++ = IXDR_GET_");
 803 
 804         upp_case = upcase(decl->type);
 805 
 806         /* hack  - XX */
 807         if (strcmp(upp_case, "INT") == 0) {
 808                 free(upp_case);
 809                 freed = 1;
 810                 upp_case = "LONG";
 811         }
 812         if ((strcmp(upp_case, "U_INT") == 0) ||
 813             (strcmp(upp_case, "RPCPROG") == 0) ||
 814             (strcmp(upp_case, "RPCVERS") == 0) ||
 815             (strcmp(upp_case, "RPCPROC") == 0) ||
 816             (strcmp(upp_case, "RPCPROT") == 0) ||
 817             (strcmp(upp_case, "RPCPORT") == 0)) {
 818                 free(upp_case);
 819                 freed = 1;
 820                 upp_case = "U_LONG";
 821         }
 822 
 823         if (flag == PUT)
 824                 if (rel == REL_ALIAS)
 825                         f_print(fout,
 826                             "%s(buf, objp->%s);\n", upp_case, decl->name);
 827                 else
 828                         f_print(fout, "%s(buf, *genp++);\n", upp_case);
 829 
 830         else
 831                 f_print(fout, "%s(buf);\n", upp_case);
 832         if (!freed)
 833                 free(upp_case);
 834 }
 835 
 836 static void
 837 emit_single_in_line64(int indent, declaration *decl, int flag, relation rel)
 838 {
 839         char *upp_case;
 840         int freed = 0;
 841 
 842         tabify(fout, indent);
 843         if (flag == PUT)
 844                 f_print(fout, "IXDR_PUT_");
 845         else
 846                 if (rel == REL_ALIAS)
 847                         f_print(fout, "objp->%s = IXDR_GET_", decl->name);
 848                 else
 849                         f_print(fout, "*genp++ = IXDR_GET_");
 850 
 851         upp_case = upcase(decl->type);
 852 
 853         /* hack  - XX */
 854         if ((strcmp(upp_case, "INT") == 0)||(strcmp(upp_case, "LONG") == 0)) {
 855                 free(upp_case);
 856                 freed = 1;
 857                 upp_case = "INT32";
 858         }
 859         if ((strcmp(upp_case, "U_INT") == 0) ||
 860             (strcmp(upp_case, "U_LONG") == 0) ||
 861             (strcmp(upp_case, "RPCPROG") == 0) ||
 862             (strcmp(upp_case, "RPCVERS") == 0) ||
 863             (strcmp(upp_case, "RPCPROC") == 0) ||
 864             (strcmp(upp_case, "RPCPROT") == 0) ||
 865             (strcmp(upp_case, "RPCPORT") == 0)) {
 866                 free(upp_case);
 867                 freed = 1;
 868                 upp_case = "U_INT32";
 869         }
 870 
 871         if (flag == PUT)
 872                 if (rel == REL_ALIAS)
 873                         f_print(fout,
 874                             "%s(buf, objp->%s);\n", upp_case, decl->name);
 875                 else
 876                         f_print(fout, "%s(buf, *genp++);\n", upp_case);
 877 
 878         else
 879                 f_print(fout, "%s(buf);\n", upp_case);
 880         if (!freed)
 881                 free(upp_case);
 882 }
 883 
 884 static char *
 885 upcase(char *str)
 886 {
 887         char *ptr, *hptr;
 888 
 889         ptr = malloc(strlen(str)+1);
 890         if (ptr == NULL) {
 891                 f_print(stderr, "malloc failed\n");
 892                 exit(1);
 893         };
 894 
 895         hptr = ptr;
 896         while (*str != '\0')
 897                 *ptr++ = toupper(*str++);
 898 
 899         *ptr = '\0';
 900         return (hptr);
 901 }