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_tblout.c, Dispatch table outputter for the RPC protocol compiler
  42  */
  43 #include <stdio.h>
  44 #include <string.h>
  45 #include "rpc_parse.h"
  46 #include "rpc_util.h"
  47 
  48 extern int nullproc(proc_list *);
  49 
  50 static void write_table(definition *);
  51 static void printit(char *, char *);
  52 
  53 #define TABSIZE         8
  54 #define TABCOUNT        5
  55 #define TABSTOP         (TABSIZE*TABCOUNT)
  56 
  57 static char tabstr[TABCOUNT+1] = "\t\t\t\t\t";
  58 
  59 static char tbl_hdr[] = "struct rpcgen_table %s_table[] = {\n";
  60 static char tbl_end[] = "};\n";
  61 
  62 static char null_entry_b[] = "\n\t(char *(*)())0,\n"
  63                         " \t(xdrproc_t)xdr_void,\t\t\t0,\n"
  64                         " \t(xdrproc_t)xdr_void,\t\t\t0,\n";
  65 
  66 static char null_entry[] = "\n\t(void *(*)())0,\n"
  67                         " \t(xdrproc_t)xdr_void,\t\t\t0,\n"
  68                         " \t(xdrproc_t)xdr_void,\t\t\t0,\n";
  69 
  70 
  71 static char tbl_nproc[] = "int %s_nproc =\n\tsizeof(%s_table)"
  72                                 "/sizeof(%s_table[0]);\n\n";
  73 
  74 void
  75 write_tables(void)
  76 {
  77         list *l;
  78         definition *def;
  79 
  80         f_print(fout, "\n");
  81         for (l = defined; l != NULL; l = l->next) {
  82                 def = (definition *)l->val;
  83                 if (def->def_kind == DEF_PROGRAM) {
  84                         write_table(def);
  85                 }
  86         }
  87 }
  88 
  89 static void
  90 write_table(definition *def)
  91 {
  92         version_list *vp;
  93         proc_list *proc;
  94         int current;
  95         int expected;
  96         char progvers[100];
  97         int warning;
  98 
  99         for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) {
 100                 warning = 0;
 101                 (void) snprintf(progvers, sizeof (progvers), "%s_%s",
 102                     locase(def->def_name), vp->vers_num);
 103                 /* print the table header */
 104                 f_print(fout, tbl_hdr, progvers);
 105 
 106                 if (nullproc(vp->procs)) {
 107                         expected = 0;
 108                 } else {
 109                         expected = 1;
 110                         if (tirpcflag)
 111                                 f_print(fout, null_entry);
 112                         else
 113                                 f_print(fout, null_entry_b);
 114                 }
 115                 for (proc = vp->procs; proc != NULL; proc = proc->next) {
 116                         current = atoi(proc->proc_num);
 117                         if (current != expected++) {
 118                                 f_print(fout,
 119                         "\n/*\n * WARNING: table out of order\n */\n");
 120                                 if (warning == 0) {
 121                                         f_print(stderr,
 122                                     "WARNING %s table is out of order\n",
 123                                             progvers);
 124                                         warning = 1;
 125                                         nonfatalerrors = 1;
 126                                 }
 127                                 expected = current + 1;
 128                         }
 129                         if (tirpcflag)
 130                                 f_print(fout,
 131                                     "\n\t(void *(*)())RPCGEN_ACTION(");
 132                         else
 133                                 f_print(fout,
 134                                     "\n\t(char *(*)())RPCGEN_ACTION(");
 135 
 136                         /* routine to invoke */
 137                         if (!newstyle)
 138                                 pvname_svc(proc->proc_name, vp->vers_num);
 139                         else {
 140                                 if (newstyle) /* calls internal func */
 141                                         f_print(fout, "_");
 142                                 pvname(proc->proc_name, vp->vers_num);
 143                         }
 144                         f_print(fout, "),\n");
 145 
 146                         /* argument info */
 147                         if (proc->arg_num > 1)
 148                                 printit(NULL, proc->args.argname);
 149                         else
 150                         /* do we have to do something special for newstyle */
 151                                 printit(proc->args.decls->decl.prefix,
 152                                     proc->args.decls->decl.type);
 153                         /* result info */
 154                         printit(proc->res_prefix, proc->res_type);
 155                 }
 156 
 157                 /* print the table trailer */
 158                 f_print(fout, tbl_end);
 159                 f_print(fout, tbl_nproc, progvers, progvers, progvers);
 160         }
 161 }
 162 
 163 static void
 164 printit(char *prefix, char *type)
 165 {
 166         int len;
 167         int tabs;
 168 
 169 
 170         if (streq(type, "oneway"))
 171                 len = fprintf(fout, "\t(xdrproc_t)xdr_void,");
 172         else
 173                 len = fprintf(fout, "\t(xdrproc_t)xdr_%s,", stringfix(type));
 174         /* account for leading tab expansion */
 175         len += TABSIZE - 1;
 176         if (len >= TABSTOP) {
 177                 f_print(fout, "\n");
 178                 len = 0;
 179         }
 180         /* round up to tabs required */
 181         tabs = (TABSTOP - len + TABSIZE - 1)/TABSIZE;
 182         f_print(fout, "%s", &tabstr[TABCOUNT-tabs]);
 183 
 184         if (streq(type, "void") || streq(type, "oneway")) {
 185                 f_print(fout, "0");
 186         } else {
 187                 f_print(fout, "sizeof ( ");
 188                 /* XXX: should "follow" be 1 ??? */
 189                 ptype(prefix, type, 0);
 190                 f_print(fout, ")");
 191         }
 192         f_print(fout, ",\n");
 193 }