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