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_hout.c, Header file outputter for the RPC protocol compiler
  42  */
  43 #include <stdio.h>
  44 #include <stdlib.h>
  45 #include <ctype.h>
  46 #include "rpc_parse.h"
  47 #include "rpc_util.h"
  48 
  49 extern void pprocdef(proc_list *, version_list *, char *, int);
  50 extern void pdeclaration(char *, declaration *, int, char *);
  51 
  52 static void storexdrfuncdecl(char *, int);
  53 static void pconstdef(definition *);
  54 static void pstructdef(definition *);
  55 static void puniondef(definition *);
  56 static void pdefine(char *, char *);
  57 static void pprogramdef(definition *);
  58 static void parglist(proc_list *, char *);
  59 static void penumdef(definition *);
  60 static void ptypedef(definition *);
  61 static uint_t undefined2(char *, char *);
  62 
  63 enum rpc_gvc {
  64         PROGRAM,
  65         VERSION,
  66         PROCEDURE
  67 };
  68 
  69 /*
  70  * Print the C-version of an xdr definition
  71  */
  72 void
  73 print_datadef(definition *def)
  74 {
  75         if (def->def_kind == DEF_PROGRAM)  /* handle data only */
  76                 return;
  77 
  78         if (def->def_kind != DEF_CONST)
  79                 f_print(fout, "\n");
  80         switch (def->def_kind) {
  81         case DEF_STRUCT:
  82                 pstructdef(def);
  83                 break;
  84         case DEF_UNION:
  85                 puniondef(def);
  86                 break;
  87         case DEF_ENUM:
  88                 penumdef(def);
  89                 break;
  90         case DEF_TYPEDEF:
  91                 ptypedef(def);
  92                 break;
  93         case DEF_PROGRAM:
  94                 pprogramdef(def);
  95                 break;
  96         case DEF_CONST:
  97                 pconstdef(def);
  98                 break;
  99         }
 100         if (def->def_kind != DEF_PROGRAM && def->def_kind != DEF_CONST)
 101                 storexdrfuncdecl(def->def_name, def->def_kind != DEF_TYPEDEF ||
 102                     !isvectordef(def->def.ty.old_type, def->def.ty.rel));
 103 }
 104 
 105 
 106 void
 107 print_funcdef(definition *def)
 108 {
 109         switch (def->def_kind) {
 110         case DEF_PROGRAM:
 111                 f_print(fout, "\n");
 112                 pprogramdef(def);
 113                 break;
 114         }
 115 }
 116 
 117 /*
 118  * store away enough information to allow the XDR functions to be spat
 119  * out at the end of the file
 120  */
 121 static void
 122 storexdrfuncdecl(char *name, int pointerp)
 123 {
 124         xdrfunc *xdrptr;
 125 
 126         xdrptr = malloc(sizeof (struct xdrfunc));
 127 
 128         xdrptr->name = name;
 129         xdrptr->pointerp = pointerp;
 130         xdrptr->next = NULL;
 131 
 132         if (xdrfunc_tail == NULL) {
 133                 xdrfunc_head = xdrptr;
 134                 xdrfunc_tail = xdrptr;
 135         } else {
 136                 xdrfunc_tail->next = xdrptr;
 137                 xdrfunc_tail = xdrptr;
 138         }
 139 
 140 
 141 }
 142 
 143 void
 144 print_xdr_func_def(char *name, int pointerp)
 145 {
 146         f_print(fout, "extern  bool_t xdr_%s(XDR *, %s%s);\n", name,
 147             name, pointerp ? "*" : "");
 148 }
 149 
 150 
 151 static void
 152 pconstdef(definition *def)
 153 {
 154         pdefine(def->def_name, def->def.co);
 155 }
 156 
 157 /*
 158  * print out the definitions for the arguments of functions in the
 159  * header file
 160  */
 161 static void
 162 pargdef(definition *def)
 163 {
 164         decl_list *l;
 165         version_list *vers;
 166         char *name;
 167         proc_list *plist;
 168 
 169         for (vers = def->def.pr.versions; vers != NULL; vers = vers->next) {
 170                 for (plist = vers->procs; plist != NULL; plist = plist->next) {
 171                         if (!newstyle || plist->arg_num < 2)
 172                                 continue; /* old style or single args */
 173                         name = plist->args.argname;
 174                         f_print(fout, "struct %s {\n", name);
 175                         for (l = plist->args.decls; l != NULL; l = l->next)
 176                                 pdeclaration(name, &l->decl, 1, ";\n");
 177                         f_print(fout, "};\n");
 178                         f_print(fout, "typedef struct %s %s;\n", name, name);
 179                         storexdrfuncdecl(name, 1);
 180                         f_print(fout, "\n");
 181                 }
 182         }
 183 }
 184 
 185 
 186 static void
 187 pstructdef(definition *def)
 188 {
 189         decl_list *l;
 190         char *name = def->def_name;
 191 
 192         f_print(fout, "struct %s {\n", name);
 193         for (l = def->def.st.decls; l != NULL; l = l->next)
 194                 pdeclaration(name, &l->decl, 1, ";\n");
 195         f_print(fout, "};\n");
 196         f_print(fout, "typedef struct %s %s;\n", name, name);
 197 }
 198 
 199 static void
 200 puniondef(definition *def)
 201 {
 202         case_list *l;
 203         char *name = def->def_name;
 204         declaration *decl;
 205 
 206         f_print(fout, "struct %s {\n", name);
 207         decl = &def->def.un.enum_decl;
 208         if (streq(decl->type, "bool"))
 209                 f_print(fout, "\tbool_t %s;\n", decl->name);
 210         else
 211                 f_print(fout, "\t%s %s;\n", decl->type, decl->name);
 212         f_print(fout, "\tunion {\n");
 213         for (l = def->def.un.cases; l != NULL; l = l->next) {
 214                 if (l->contflag == 0)
 215                         pdeclaration(name, &l->case_decl, 2, ";\n");
 216         }
 217         decl = def->def.un.default_decl;
 218         if (decl && !streq(decl->type, "void"))
 219                 pdeclaration(name, decl, 2, ";\n");
 220         f_print(fout, "\t} %s_u;\n", name);
 221         f_print(fout, "};\n");
 222         f_print(fout, "typedef struct %s %s;\n", name, name);
 223 }
 224 
 225 static void
 226 pdefine(char *name, char *num)
 227 {
 228         f_print(fout, "#define\t%s %s\n", name, num);
 229 }
 230 
 231 static void
 232 puldefine(char *name, char *num, enum rpc_gvc which)
 233 {
 234         switch (which) {
 235         case PROGRAM:
 236         case VERSION:
 237         case PROCEDURE:
 238                 f_print(fout, "#define\t%s\t%s\n", name, num);
 239                 break;
 240         default:
 241                 break;
 242         }
 243 }
 244 
 245 static uint_t
 246 define_printed(proc_list *stop, version_list *start)
 247 {
 248         version_list *vers;
 249         proc_list *proc;
 250 
 251         for (vers = start; vers != NULL; vers = vers->next) {
 252                 for (proc = vers->procs; proc != NULL; proc = proc->next) {
 253                         if (proc == stop)
 254                                 return (0);
 255                         if (streq(proc->proc_name, stop->proc_name))
 256                                 return (1);
 257                 }
 258         }
 259         abort();
 260         /* NOTREACHED */
 261 }
 262 
 263 static void
 264 pfreeprocdef(char *name, char *vers)
 265 {
 266         f_print(fout, "extern int ");
 267         pvname(name, vers);
 268         f_print(fout, "_freeresult(SVCXPRT *, xdrproc_t, caddr_t);\n");
 269 }
 270 
 271 static void
 272 pprogramdef(definition *def)
 273 {
 274         version_list *vers;
 275         proc_list *proc;
 276 
 277         pargdef(def);
 278 
 279         puldefine(def->def_name, def->def.pr.prog_num, PROGRAM);
 280         for (vers = def->def.pr.versions; vers != NULL; vers = vers->next) {
 281                 if (tblflag) {
 282                         f_print(fout,
 283                             "extern struct rpcgen_table %s_%s_table[];\n",
 284                             locase(def->def_name), vers->vers_num);
 285                         f_print(fout,
 286                             "extern int %s_%s_nproc;\n",
 287                             locase(def->def_name), vers->vers_num);
 288                 }
 289                 puldefine(vers->vers_name, vers->vers_num, VERSION);
 290 
 291                 for (proc = vers->procs; proc != NULL;
 292                     proc = proc->next) {
 293                         if (!define_printed(proc,
 294                             def->def.pr.versions)) {
 295                                 puldefine(proc->proc_name,
 296                                     proc->proc_num, PROCEDURE);
 297                         }
 298                         f_print(fout, "extern  ");
 299                         pprocdef(proc, vers, "CLIENT *", 0);
 300                         f_print(fout, "extern  ");
 301                         pprocdef(proc, vers, "struct svc_req *", 1);
 302                 }
 303                 pfreeprocdef(def->def_name, vers->vers_num);
 304         }
 305 }
 306 
 307 void
 308 pprocdef(proc_list *proc, version_list *vp, char *addargtype, int server_p)
 309 {
 310         if (mtflag) {
 311                 /* Print MT style stubs */
 312                 if (server_p)
 313                         f_print(fout, "bool_t ");
 314                 else
 315                         f_print(fout, "enum clnt_stat ");
 316         } else {
 317                 ptype(proc->res_prefix, proc->res_type, 1);
 318                 f_print(fout, "* ");
 319         }
 320         if (server_p)
 321                 pvname_svc(proc->proc_name, vp->vers_num);
 322         else
 323                 pvname(proc->proc_name, vp->vers_num);
 324 
 325         parglist(proc, addargtype);
 326 }
 327 
 328 /* print out argument list of procedure */
 329 static void
 330 parglist(proc_list *proc, char *addargtype)
 331 {
 332         decl_list *dl;
 333         int oneway = streq(proc->res_type, "oneway");
 334 
 335         f_print(fout, "(");
 336         if (proc->arg_num < 2 && newstyle &&
 337             streq(proc->args.decls->decl.type, "void")) {
 338                 /* 0 argument in new style:  do nothing */
 339                 /* EMPTY */
 340         } else {
 341                 for (dl = proc->args.decls; dl != NULL; dl = dl->next) {
 342                         ptype(dl->decl.prefix, dl->decl.type, 1);
 343                         if (!newstyle || (dl->decl.rel == REL_POINTER))
 344                                 f_print(fout, "*");
 345                         /* old style passes by reference */
 346                         f_print(fout, ", ");
 347                 }
 348         }
 349 
 350         if (mtflag && !oneway)  {
 351                 ptype(proc->res_prefix, proc->res_type, 1);
 352                 f_print(fout, "*, ");
 353         }
 354 
 355         f_print(fout, "%s);\n", addargtype);
 356 }
 357 
 358 static void
 359 penumdef(definition *def)
 360 {
 361         char *name = def->def_name;
 362         enumval_list *l;
 363         char *last = NULL;
 364         int count = 0;
 365 
 366         f_print(fout, "enum %s {\n", name);
 367         for (l = def->def.en.vals; l != NULL; l = l->next) {
 368                 f_print(fout, "\t%s", l->name);
 369                 if (l->assignment) {
 370                         f_print(fout, " = %s", l->assignment);
 371                         last = l->assignment;
 372                         count = 1;
 373                 } else {
 374                         if (last == NULL)
 375                                 f_print(fout, " = %d", count++);
 376                         else
 377                                 f_print(fout, " = %s + %d", last, count++);
 378                 }
 379                 if (l->next)
 380                         f_print(fout, ",\n");
 381                 else
 382                         f_print(fout, "\n");
 383         }
 384         f_print(fout, "};\n");
 385         f_print(fout, "typedef enum %s %s;\n", name, name);
 386 }
 387 
 388 static void
 389 ptypedef(definition *def)
 390 {
 391         char *name = def->def_name;
 392         char *old = def->def.ty.old_type;
 393         char prefix[8]; /* enough to contain "struct ", including NUL */
 394         relation rel = def->def.ty.rel;
 395 
 396 
 397         if (!streq(name, old)) {
 398                 if (streq(old, "string")) {
 399                         old = "char";
 400                         rel = REL_POINTER;
 401                 } else if (streq(old, "opaque")) {
 402                         old = "char";
 403                 } else if (streq(old, "bool")) {
 404                         old = "bool_t";
 405                 }
 406                 if (undefined2(old, name) && def->def.ty.old_prefix)
 407                         (void) snprintf(prefix, sizeof (prefix), "%s ",
 408                             def->def.ty.old_prefix);
 409                 else
 410                         prefix[0] = 0;
 411                 f_print(fout, "typedef ");
 412                 switch (rel) {
 413                 case REL_ARRAY:
 414                         f_print(fout, "struct {\n");
 415                         f_print(fout, "\tu_int %s_len;\n", name);
 416                         f_print(fout, "\t%s%s *%s_val;\n", prefix, old, name);
 417                         f_print(fout, "} %s", name);
 418                         break;
 419                 case REL_POINTER:
 420                         f_print(fout, "%s%s *%s", prefix, old, name);
 421                         break;
 422                 case REL_VECTOR:
 423                         f_print(fout, "%s%s %s[%s]", prefix, old, name,
 424                             def->def.ty.array_max);
 425                         break;
 426                 case REL_ALIAS:
 427                         f_print(fout, "%s%s %s", prefix, old, name);
 428                         break;
 429                 }
 430                 f_print(fout, ";\n");
 431         }
 432 }
 433 
 434 void
 435 pdeclaration(char *name, declaration *dec, int tab, char *separator)
 436 {
 437         char buf[8];    /* enough to hold "struct ", include NUL */
 438         char *prefix;
 439         char *type;
 440 
 441         if (streq(dec->type, "void"))
 442                 return;
 443         tabify(fout, tab);
 444         if (streq(dec->type, name) && !dec->prefix)
 445                 f_print(fout, "struct ");
 446         if (streq(dec->type, "string")) {
 447                 f_print(fout, "char *%s", dec->name);
 448         } else {
 449                 prefix = "";
 450                 if (streq(dec->type, "bool")) {
 451                         type = "bool_t";
 452                 } else if (streq(dec->type, "opaque")) {
 453                         type = "char";
 454                 } else {
 455                         if (dec->prefix) {
 456                                 (void) snprintf(buf, sizeof (buf),
 457                                     "%s ", dec->prefix);
 458                                 prefix = buf;
 459                         }
 460                         type = dec->type;
 461                 }
 462                 switch (dec->rel) {
 463                 case REL_ALIAS:
 464                         f_print(fout, "%s%s %s", prefix, type, dec->name);
 465                         break;
 466                 case REL_VECTOR:
 467                         f_print(fout, "%s%s %s[%s]", prefix, type, dec->name,
 468                             dec->array_max);
 469                         break;
 470                 case REL_POINTER:
 471                         f_print(fout, "%s%s *%s", prefix, type, dec->name);
 472                         break;
 473                 case REL_ARRAY:
 474                         f_print(fout, "struct {\n");
 475                         tabify(fout, tab);
 476                         f_print(fout, "\tu_int %s_len;\n", dec->name);
 477                         tabify(fout, tab);
 478                         f_print(fout,
 479                             "\t%s%s *%s_val;\n", prefix, type, dec->name);
 480                         tabify(fout, tab);
 481                         f_print(fout, "} %s", dec->name);
 482                         break;
 483                 }
 484         }
 485         /* LINTED variable format */
 486         f_print(fout, separator);
 487 }
 488 
 489 static uint_t
 490 undefined2(char *type, char *stop)
 491 {
 492         list *l;
 493         definition *def;
 494 
 495         for (l = defined; l != NULL; l = l->next) {
 496                 def = (definition *) l->val;
 497                 if (def->def_kind != DEF_PROGRAM) {
 498                         if (streq(def->def_name, stop))
 499                                 return (1);
 500                         if (streq(def->def_name, type))
 501                                 return (0);
 502                 }
 503         }
 504         return (1);
 505 }