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