Update to 2.17
[platform/upstream/glibc.git] / sunrpc / rpc_clntout.c
1 /*
2  * rpc_clntout.c, Client-stub outputter for the RPC protocol compiler
3  * Copyright (c) 2010, Oracle America, Inc.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are
7  * met:
8  *
9  *     * Redistributions of source code must retain the above copyright
10  *       notice, this list of conditions and the following disclaimer.
11  *     * Redistributions in binary form must reproduce the above
12  *       copyright notice, this list of conditions and the following
13  *       disclaimer in the documentation and/or other materials
14  *       provided with the distribution.
15  *     * Neither the name of the "Oracle America, Inc." nor the names of its
16  *       contributors may be used to endorse or promote products derived
17  *       from this software without specific prior written permission.
18  *
19  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
22  *   FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
23  *   COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
24  *   INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25  *   DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
26  *   GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27  *   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28  *   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29  *   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32 #include <stdio.h>
33 #include <string.h>
34 #include "rpc/types.h"
35 #include "rpc_parse.h"
36 #include "rpc_util.h"
37 #include "proto.h"
38
39 #define DEFAULT_TIMEOUT 25      /* in seconds */
40 static const char RESULT[] = "clnt_res";
41
42 static void write_program (definition * def);
43 static void printbody (proc_list * proc);
44 static const char *ampr (const char *type);
45 static void printbody (proc_list * proc);
46
47
48 void
49 write_stubs (void)
50 {
51   list *l;
52   definition *def;
53
54   fprintf (fout,
55            "\n/* Default timeout can be changed using clnt_control() */\n");
56   fprintf (fout, "static struct timeval TIMEOUT = { %d, 0 };\n",
57            DEFAULT_TIMEOUT);
58   for (l = defined; l != NULL; l = l->next)
59     {
60       def = (definition *) l->val;
61       if (def->def_kind == DEF_PROGRAM)
62         {
63           write_program (def);
64         }
65     }
66 }
67
68 static void
69 write_program (definition * def)
70 {
71   version_list *vp;
72   proc_list *proc;
73
74   for (vp = def->def.pr.versions; vp != NULL; vp = vp->next)
75     {
76       for (proc = vp->procs; proc != NULL; proc = proc->next)
77         {
78           fprintf (fout, "\n");
79           if (mtflag == 0)
80             {
81               ptype (proc->res_prefix, proc->res_type, 1);
82               fprintf (fout, "*\n");
83               pvname (proc->proc_name, vp->vers_num);
84               printarglist (proc, RESULT, "clnt", "CLIENT *");
85             }
86           else
87             {
88               fprintf (fout, "enum clnt_stat \n");
89               pvname (proc->proc_name, vp->vers_num);
90               printarglist (proc, RESULT, "clnt", "CLIENT *");
91             }
92           fprintf (fout, "{\n");
93           printbody (proc);
94           fprintf (fout, "}\n");
95         }
96     }
97 }
98
99 /* Writes out declarations of procedure's argument list.
100    In either ANSI C style, in one of old rpcgen style (pass by reference),
101    or new rpcgen style (multiple arguments, pass by value);
102  */
103
104 /* sample addargname = "clnt"; sample addargtype = "CLIENT * " */
105
106 void
107 printarglist (proc_list * proc,  const char *result,
108               const char *addargname, const char *addargtype)
109 {
110
111   decl_list *l;
112
113   if (!newstyle)
114     { /* old style: always pass argument by reference */
115       if (Cflag)
116         {                       /* C++ style heading */
117           fprintf (fout, "(");
118           ptype (proc->args.decls->decl.prefix,
119                  proc->args.decls->decl.type, 1);
120
121           if (mtflag)
122             {/* Generate result field */
123               fprintf (fout, "*argp, ");
124               ptype(proc->res_prefix, proc->res_type, 1);
125               fprintf (fout, "*%s, %s%s)\n", result, addargtype, addargname);
126             }
127           else
128             fprintf (fout, "*argp, %s%s)\n", addargtype, addargname);
129         }
130       else
131         {
132           if (!mtflag)
133             fprintf (fout, "(argp, %s)\n", addargname);
134           else
135             fprintf (fout, "(argp, %s, %s)\n", result, addargname);
136           fprintf (fout, "\t");
137           ptype (proc->args.decls->decl.prefix,
138                  proc->args.decls->decl.type, 1);
139           fprintf (fout, "*argp;\n");
140           if (mtflag)
141             {
142               fprintf (fout, "\t");
143               ptype (proc->res_prefix, proc->res_type, 1);
144               fprintf (fout, "*%s;\n", result);
145             }
146         }
147     }
148   else if (streq (proc->args.decls->decl.type, "void"))
149     {
150       /* newstyle, 0 argument */
151       if (mtflag)
152         {
153           fprintf (fout, "(");
154           if (Cflag)
155             {
156               ptype(proc->res_prefix, proc->res_type, 1);
157               fprintf (fout, "*%s, %s%s)\n", result, addargtype, addargname);
158             }
159           else
160             fprintf (fout, "(%s)\n", addargname);
161         }
162       else if (Cflag)
163         fprintf (fout, "(%s%s)\n", addargtype, addargname);
164       else
165         fprintf (fout, "(%s)\n", addargname);
166     }
167   else
168     {
169       /* new style, 1 or multiple arguments */
170       if (!Cflag)
171         {
172           fprintf (fout, "(");
173           for (l = proc->args.decls; l != NULL; l = l->next)
174             fprintf (fout, "%s, ", l->decl.name);
175           if (mtflag)
176             fprintf (fout, "%s, ", result);
177           fprintf (fout, "%s)\n", addargname);
178           for (l = proc->args.decls; l != NULL; l = l->next)
179             {
180               pdeclaration (proc->args.argname, &l->decl, 1, ";\n");
181             }
182           if (mtflag)
183             {
184               fprintf (fout, "\t");
185               ptype (proc->res_prefix, proc->res_type, 1);
186               fprintf (fout, "*%s;\n", result);
187             }
188         }
189       else
190         {                       /* C++ style header */
191           fprintf (fout, "(");
192           for (l = proc->args.decls; l != NULL; l = l->next)
193             {
194               pdeclaration (proc->args.argname, &l->decl, 0, ", ");
195             }
196           if (mtflag)
197             {
198               ptype (proc->res_prefix, proc->res_type, 1);
199               fprintf (fout, "*%s, ", result);
200             }
201           fprintf (fout, " %s%s)\n", addargtype, addargname);
202         }
203     }
204
205   if (!Cflag)
206     fprintf (fout, "\t%s%s;\n", addargtype, addargname);
207 }
208
209
210 static
211 const char *
212 ampr (const char *type)
213 {
214   if (isvectordef (type, REL_ALIAS))
215     {
216       return "";
217     }
218   else
219     {
220       return "&";
221     }
222 }
223
224 static void
225 printbody (proc_list * proc)
226 {
227   decl_list *l;
228   bool_t args2 = (proc->arg_num > 1);
229 /*  int i; */
230
231   /* For new style with multiple arguments, need a structure in which
232      to stuff the arguments. */
233   if (newstyle && args2)
234     {
235       fprintf (fout, "\t%s", proc->args.argname);
236       fprintf (fout, " arg;\n");
237     }
238   if (!mtflag)
239     {
240       fprintf (fout, "\tstatic ");
241       if (streq (proc->res_type, "void"))
242         {
243           fprintf (fout, "char ");
244         }
245       else
246         {
247           ptype (proc->res_prefix, proc->res_type, 0);
248         }
249       fprintf (fout, "%s;\n", RESULT);
250       fprintf (fout, "\n");
251       fprintf (fout, "\tmemset((char *)%s%s, 0, sizeof(%s));\n",
252                ampr (proc->res_type), RESULT, RESULT);
253     }
254   if (newstyle && !args2 && (streq (proc->args.decls->decl.type, "void")))
255     {
256       /* newstyle, 0 arguments */
257       if (mtflag)
258         fprintf (fout, "\t return ");
259       else
260         fprintf (fout, "\t if ");
261       fprintf (fout,
262                "(clnt_call (clnt, %s, (xdrproc_t) xdr_void, ", proc->proc_name);
263
264       fprintf (fout,
265                "(caddr_t) NULL,\n\t\t(xdrproc_t) xdr_%s, (caddr_t) %s%s,",
266                stringfix(proc->res_type), (mtflag)?"":ampr(proc->res_type),
267                RESULT);
268       if (mtflag)
269         fprintf (fout, "\n\t\tTIMEOUT));\n\n");
270       else
271         fprintf (fout, "\n\t\tTIMEOUT) != RPC_SUCCESS) {\n");
272     }
273   else if (newstyle && args2)
274     {
275       /* newstyle, multiple arguments:  stuff arguments into structure */
276       for (l = proc->args.decls; l != NULL; l = l->next)
277         {
278           fprintf (fout, "\targ.%s = %s;\n",
279                    l->decl.name, l->decl.name);
280         }
281       if (mtflag)
282         fprintf (fout, "\treturn ");
283       else
284         fprintf (fout, "\tif ");
285
286       fprintf (fout,
287                "(clnt_call (clnt, %s, (xdrproc_t) xdr_%s", proc->proc_name,
288                proc->args.argname);
289       fprintf (fout,
290                ", (caddr_t) &arg,\n\t\t(xdrproc_t) xdr_%s, (caddr_t) %s%s,",
291                stringfix(proc->res_type), (mtflag)?"":ampr(proc->res_type),
292                RESULT);
293       if (mtflag)
294         fprintf (fout, "\n\t\tTIMEOUT));\n");
295       else
296         fprintf (fout, "\n\t\tTIMEOUT) != RPC_SUCCESS) {\n");
297     }
298   else
299     {                           /* single argument, new or old style */
300       if (!mtflag)
301         fprintf (fout,
302                  "\tif (clnt_call (clnt, %s,\n\t\t(xdrproc_t) xdr_%s, (caddr_t) %s%s,\n\t\t(xdrproc_t) xdr_%s, (caddr_t) %s%s,\n\t\tTIMEOUT) != RPC_SUCCESS) {\n",
303                  proc->proc_name,
304                  stringfix (proc->args.decls->decl.type),
305                  (newstyle ? "&" : ""),
306                  (newstyle ? proc->args.decls->decl.name : "argp"),
307                  stringfix (proc->res_type), ampr (proc->res_type),
308                  RESULT);
309       else
310         fprintf(fout,
311                 "\treturn (clnt_call(clnt, %s,\n\t\t(xdrproc_t) xdr_%s, (caddr_t) %s%s,\n\t\t(xdrproc_t) xdr_%s, (caddr_t) %s%s,\n\t\tTIMEOUT));\n",
312                 proc->proc_name,
313                 stringfix (proc->args.decls->decl.type),
314                 (newstyle ? "&" : ""),
315                 (newstyle ? proc->args.decls->decl.name : "argp"),
316                 stringfix (proc->res_type), "",
317                 RESULT);
318     }
319   if (!mtflag)
320     {
321       fprintf (fout, "\t\treturn (NULL);\n");
322       fprintf (fout, "\t}\n");
323       if (streq (proc->res_type, "void"))
324         {
325           fprintf (fout, "\treturn ((void *)%s%s);\n",
326                    ampr (proc->res_type), RESULT);
327         }
328       else
329         {
330           fprintf (fout, "\treturn (%s%s);\n", ampr (proc->res_type), RESULT);
331         }
332     }
333 }