2 * rpc_clntout.c, Client-stub outputter for the RPC protocol compiler
3 * Copyright (c) 2010, Oracle America, Inc.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
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.
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.
34 #include "rpc/types.h"
35 #include "rpc_parse.h"
39 #define DEFAULT_TIMEOUT 25 /* in seconds */
40 static const char RESULT
[] = "clnt_res";
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
);
55 "\n/* Default timeout can be changed using clnt_control() */\n");
56 fprintf (fout
, "static struct timeval TIMEOUT = { %d, 0 };\n",
58 for (l
= defined
; l
!= NULL
; l
= l
->next
)
60 def
= (definition
*) l
->val
;
61 if (def
->def_kind
== DEF_PROGRAM
)
69 write_program (definition
* def
)
74 for (vp
= def
->def
.pr
.versions
; vp
!= NULL
; vp
= vp
->next
)
76 for (proc
= vp
->procs
; proc
!= NULL
; proc
= proc
->next
)
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 *");
88 fprintf (fout
, "enum clnt_stat \n");
89 pvname (proc
->proc_name
, vp
->vers_num
);
90 printarglist (proc
, RESULT
, "clnt", "CLIENT *");
92 fprintf (fout
, "{\n");
94 fprintf (fout
, "}\n");
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);
104 /* sample addargname = "clnt"; sample addargtype = "CLIENT * " */
107 printarglist (proc_list
* proc
, const char *result
,
108 const char *addargname
, const char *addargtype
)
114 { /* old style: always pass argument by reference */
116 { /* C++ style heading */
118 ptype (proc
->args
.decls
->decl
.prefix
,
119 proc
->args
.decls
->decl
.type
, 1);
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
);
128 fprintf (fout
, "*argp, %s%s)\n", addargtype
, addargname
);
133 fprintf (fout
, "(argp, %s)\n", addargname
);
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");
142 fprintf (fout
, "\t");
143 ptype (proc
->res_prefix
, proc
->res_type
, 1);
144 fprintf (fout
, "*%s;\n", result
);
148 else if (streq (proc
->args
.decls
->decl
.type
, "void"))
150 /* newstyle, 0 argument */
156 ptype(proc
->res_prefix
, proc
->res_type
, 1);
157 fprintf (fout
, "*%s, %s%s)\n", result
, addargtype
, addargname
);
160 fprintf (fout
, "(%s)\n", addargname
);
163 fprintf (fout
, "(%s%s)\n", addargtype
, addargname
);
165 fprintf (fout
, "(%s)\n", addargname
);
169 /* new style, 1 or multiple arguments */
173 for (l
= proc
->args
.decls
; l
!= NULL
; l
= l
->next
)
174 fprintf (fout
, "%s, ", l
->decl
.name
);
176 fprintf (fout
, "%s, ", result
);
177 fprintf (fout
, "%s)\n", addargname
);
178 for (l
= proc
->args
.decls
; l
!= NULL
; l
= l
->next
)
180 pdeclaration (proc
->args
.argname
, &l
->decl
, 1, ";\n");
184 fprintf (fout
, "\t");
185 ptype (proc
->res_prefix
, proc
->res_type
, 1);
186 fprintf (fout
, "*%s;\n", result
);
190 { /* C++ style header */
192 for (l
= proc
->args
.decls
; l
!= NULL
; l
= l
->next
)
194 pdeclaration (proc
->args
.argname
, &l
->decl
, 0, ", ");
198 ptype (proc
->res_prefix
, proc
->res_type
, 1);
199 fprintf (fout
, "*%s, ", result
);
201 fprintf (fout
, " %s%s)\n", addargtype
, addargname
);
206 fprintf (fout
, "\t%s%s;\n", addargtype
, addargname
);
212 ampr (const char *type
)
214 if (isvectordef (type
, REL_ALIAS
))
225 printbody (proc_list
* proc
)
228 bool_t args2
= (proc
->arg_num
> 1);
231 /* For new style with multiple arguments, need a structure in which
232 to stuff the arguments. */
233 if (newstyle
&& args2
)
235 fprintf (fout
, "\t%s", proc
->args
.argname
);
236 fprintf (fout
, " arg;\n");
240 fprintf (fout
, "\tstatic ");
241 if (streq (proc
->res_type
, "void"))
243 fprintf (fout
, "char ");
247 ptype (proc
->res_prefix
, proc
->res_type
, 0);
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
);
254 if (newstyle
&& !args2
&& (streq (proc
->args
.decls
->decl
.type
, "void")))
256 /* newstyle, 0 arguments */
258 fprintf (fout
, "\t return ");
260 fprintf (fout
, "\t if ");
262 "(clnt_call (clnt, %s, (xdrproc_t) xdr_void, ", proc
->proc_name
);
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
),
269 fprintf (fout
, "\n\t\tTIMEOUT));\n\n");
271 fprintf (fout
, "\n\t\tTIMEOUT) != RPC_SUCCESS) {\n");
273 else if (newstyle
&& args2
)
275 /* newstyle, multiple arguments: stuff arguments into structure */
276 for (l
= proc
->args
.decls
; l
!= NULL
; l
= l
->next
)
278 fprintf (fout
, "\targ.%s = %s;\n",
279 l
->decl
.name
, l
->decl
.name
);
282 fprintf (fout
, "\treturn ");
284 fprintf (fout
, "\tif ");
287 "(clnt_call (clnt, %s, (xdrproc_t) xdr_%s", proc
->proc_name
,
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
),
294 fprintf (fout
, "\n\t\tTIMEOUT));\n");
296 fprintf (fout
, "\n\t\tTIMEOUT) != RPC_SUCCESS) {\n");
299 { /* single argument, new or old style */
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",
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
),
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",
313 stringfix (proc
->args
.decls
->decl
.type
),
314 (newstyle
? "&" : ""),
315 (newstyle
? proc
->args
.decls
->decl
.name
: "argp"),
316 stringfix (proc
->res_type
), "",
321 fprintf (fout
, "\t\treturn (NULL);\n");
322 fprintf (fout
, "\t}\n");
323 if (streq (proc
->res_type
, "void"))
325 fprintf (fout
, "\treturn ((void *)%s%s);\n",
326 ampr (proc
->res_type
), RESULT
);
330 fprintf (fout
, "\treturn (%s%s);\n", ampr (proc
->res_type
), RESULT
);