1/*	$NetBSD: rpc_clntout.c,v 1.12 2002/01/31 19:36:48 tv Exp $	*/
2/*
3 * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
4 * unrestricted use provided that this legend is included on all tape
5 * media and as a part of the software program in whole or part.  Users
6 * may copy or modify Sun RPC without charge, but are not authorized
7 * to license or distribute it to anyone else except as part of a product or
8 * program developed by the user or with the express written consent of
9 * Sun Microsystems, Inc.
10 *
11 * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
12 * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
13 * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
14 *
15 * Sun RPC is provided with no support and without any obligation on the
16 * part of Sun Microsystems, Inc. to assist in its use, correction,
17 * modification or enhancement.
18 *
19 * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
20 * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
21 * OR ANY PART THEREOF.
22 *
23 * In no event will Sun Microsystems, Inc. be liable for any lost revenue
24 * or profits or other special, indirect and consequential damages, even if
25 * Sun has been advised of the possibility of such damages.
26 *
27 * Sun Microsystems, Inc.
28 * 2550 Garcia Avenue
29 * Mountain View, California  94043
30 */
31
32#if HAVE_NBTOOL_CONFIG_H
33#include "nbtool_config.h"
34#endif
35
36#include <sys/cdefs.h>
37#if defined(__RCSID) && !defined(lint)
38#if 0
39static char sccsid[] = "@(#)rpc_clntout.c 1.11 89/02/22 (C) 1987 SMI";
40#else
41__RCSID("$NetBSD: rpc_clntout.c,v 1.12 2002/01/31 19:36:48 tv Exp $");
42#endif
43#endif
44
45/*
46 * rpc_clntout.c, Client-stub outputter for the RPC protocol compiler
47 * Copyright (C) 1987, Sun Microsytsems, Inc.
48 */
49#include <stdio.h>
50#include <string.h>
51#include <rpc/types.h>
52#include "rpc_scan.h"
53#include "rpc_parse.h"
54#include "rpc_util.h"
55
56static void write_program __P((definition *));
57static char *ampr __P((char *));
58static char *aster __P((char *));
59static void printbody __P((proc_list *));
60
61#define DEFAULT_TIMEOUT 25	/* in seconds */
62static char RESULT[] = "clnt_res";
63
64
65void
66write_stubs()
67{
68	list   *l;
69	definition *def;
70
71	f_print(fout,
72	    "\n/* Default timeout can be changed using clnt_control() */\n");
73	f_print(fout, "static struct timeval TIMEOUT = { %d, 0 };\n",
74	    DEFAULT_TIMEOUT);
75	for (l = defined; l != NULL; l = l->next) {
76		def = (definition *) l->val;
77		if (def->def_kind == DEF_PROGRAM) {
78			write_program(def);
79		}
80	}
81}
82
83static void
84write_program(def)
85	definition *def;
86{
87	version_list *vp;
88	proc_list *proc;
89
90	for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) {
91		for (proc = vp->procs; proc != NULL; proc = proc->next) {
92			f_print(fout, "\n");
93			if (Mflag)
94				f_print(fout, "enum clnt_stat\n");
95			else {
96				ptype(proc->res_prefix, proc->res_type, 1);
97				f_print(fout, "*\n");
98			}
99			pvname(proc->proc_name, vp->vers_num);
100			printarglist(proc, RESULT, "clnt", "CLIENT *");
101			f_print(fout, "{\n");
102			printbody(proc);
103			f_print(fout, "}\n");
104		}
105	}
106}
107/* Writes out declarations of procedure's argument list.
108   In either ANSI C style, in one of old rpcgen style (pass by reference),
109   or new rpcgen style (multiple arguments, pass by value);
110   */
111
112/* sample addargname = "clnt"; sample addargtype = "CLIENT * " */
113
114void
115printarglist(proc, result, addargname, addargtype)
116	proc_list *proc;
117	char   *result, *addargname, *addargtype;
118{
119
120	decl_list *l;
121
122	if (!newstyle) {	/* old style: always pass argument by
123				 * reference */
124		if (Cflag) {	/* C++ style heading */
125			f_print(fout, "(");
126			ptype(proc->args.decls->decl.prefix, proc->args.decls->decl.type, 1);
127			f_print(fout, "*argp, ");
128			if (Mflag) {
129				if (streq(proc->res_type, "void"))
130					f_print(fout, "char ");
131				else
132					ptype(proc->res_prefix, proc->res_type, 0);
133				f_print(fout, "%s%s, ", aster(proc->res_type),
134				    result);
135			}
136			f_print(fout, "%s%s)\n", addargtype, addargname);
137		} else {
138			f_print(fout, "(argp, ");
139			if (Mflag)
140				f_print(fout, "%s, ", result);
141			f_print(fout, "%s)\n", addargname);
142			f_print(fout, "\t");
143			ptype(proc->args.decls->decl.prefix, proc->args.decls->decl.type, 1);
144			f_print(fout, "*argp;\n");
145			if (Mflag) {
146				f_print(fout, "\t");
147				if (streq(proc->res_type, "void"))
148					f_print(fout, "char ");
149				else
150					ptype(proc->res_prefix, proc->res_type, 0);
151				f_print(fout, "%s%s;\n", aster(proc->res_type),
152				    result);
153			}
154		}
155	} else {
156		f_print(fout, "(");
157		if (!streq(proc->args.decls->decl.type, "void")) {
158			/* new style, 1 or multiple arguments */
159			if (!Cflag) {
160				for (l = proc->args.decls; l != NULL;
161				    l = l->next)
162					f_print(fout, "%s, ", l->decl.name);
163			} else {/* C++ style header */
164				for (l = proc->args.decls; l != NULL;
165				    l = l->next)
166					pdeclaration(proc->args.argname,
167					    &l->decl, 0, ", ");
168			}
169		}
170		if (!Cflag) {
171			if (Mflag) {
172				f_print(fout, "\t");
173				if (streq(proc->res_type, "void"))
174					f_print(fout, "char ");
175				else
176					ptype(proc->res_prefix, proc->res_type, 0);
177				f_print(fout, "%s%s;\n", aster(proc->res_type),
178				    result);
179			}
180			f_print(fout, "%s)\n", addargname);
181			if (!streq(proc->args.decls->decl.type, "void")) {
182				for (l = proc->args.decls; l != NULL;
183				    l = l->next)
184					pdeclaration(proc->args.argname,
185					    &l->decl, 1, ";\n");
186			}
187		} else {
188			if (Mflag) {
189				if (streq(proc->res_type, "void"))
190					f_print(fout, "char ");
191				else
192					ptype(proc->res_prefix, proc->res_type, 0);
193				f_print(fout, "%s%s, ", aster(proc->res_type),
194				    result);
195			}
196			f_print(fout, "%s%s)\n", addargtype, addargname);
197		}
198	}
199
200	if (!Cflag)
201		f_print(fout, "\t%s%s;\n", addargtype, addargname);
202}
203
204
205static char *
206ampr(type)
207	char   *type;
208{
209	if (isvectordef(type, REL_ALIAS)) {
210		return ("");
211	} else {
212		return ("&");
213	}
214}
215
216static char *
217aster(type)
218	char   *type;
219{
220	if (isvectordef(type, REL_ALIAS)) {
221		return ("");
222	} else {
223		return ("*");
224	}
225}
226
227static void
228printbody(proc)
229	proc_list *proc;
230{
231	decl_list *l;
232	bool_t  args2 = (proc->arg_num > 1);
233
234	/* For new style with multiple arguments, need a structure in which to
235	 * stuff the arguments. */
236	if (newstyle && args2) {
237		f_print(fout, "\t%s", proc->args.argname);
238		f_print(fout, " arg;\n");
239	}
240	if (!Mflag) {
241		f_print(fout, "\tstatic ");
242		if (streq(proc->res_type, "void"))
243			f_print(fout, "char ");
244		else
245			ptype(proc->res_prefix, proc->res_type, 0);
246		f_print(fout, "%s;\n", RESULT);
247	}
248	f_print(fout, "\n");
249	if (!Mflag)
250		f_print(fout, "\tmemset((char *)%s%s, 0, sizeof(%s));\n",
251		    ampr(proc->res_type), RESULT, RESULT);
252	if (newstyle && !args2 && (streq(proc->args.decls->decl.type, "void"))) {
253		/* newstyle, 0 arguments */
254		if (Mflag) {
255			f_print(fout, "\treturn (clnt_call(clnt, %s, xdr_void",
256			    proc->proc_name);
257			f_print(fout, ", NULL, xdr_%s, %s, TIMEOUT));\n",
258			    stringfix(proc->res_type), RESULT);
259		} else {
260			f_print(fout, "\tif (clnt_call(clnt, %s, xdr_void, ",
261			    proc->proc_name);
262			f_print(fout,
263			    "NULL, xdr_%s, %s%s, TIMEOUT) != RPC_SUCCESS)\n",
264			    stringfix(proc->res_type), ampr(proc->res_type),
265			    RESULT);
266		}
267	} else {
268		if (newstyle && args2) {
269			/* newstyle, multiple arguments:  stuff arguments into
270			 * structure */
271			for (l = proc->args.decls; l != NULL; l = l->next) {
272				f_print(fout, "\targ.%s = %s;\n",
273				    l->decl.name, l->decl.name);
274			}
275			if (Mflag) {
276				f_print(fout,
277				    "\treturn (clnt_call(clnt, %s, xdr_%s, &arg, xdr_%s, %s, TIMEOUT));\n",
278				    proc->proc_name, proc->args.argname,
279				    stringfix(proc->res_type), RESULT);
280			} else {
281				f_print(fout,
282				    "\tif (clnt_call(clnt, %s, xdr_%s, &arg, xdr_%s, %s%s, TIMEOUT) != RPC_SUCCESS)\n",
283				    proc->proc_name, proc->args.argname,
284				    stringfix(proc->res_type),
285				    ampr(proc->res_type), RESULT);
286			}
287		} else {	/* single argument, new or old style */
288			if (Mflag) {
289				f_print(fout,
290				    "\treturn (clnt_call(clnt, %s, xdr_%s, %s%s, xdr_%s, %s, TIMEOUT));\n",
291				    proc->proc_name,
292				    stringfix(proc->args.decls->decl.type),
293				    (newstyle ? "&" : ""),
294				    (newstyle ? proc->args.decls->decl.name : "argp"),
295				    stringfix(proc->res_type), RESULT);
296			} else {
297				f_print(fout,
298				    "\tif (clnt_call(clnt, %s, xdr_%s, %s%s, xdr_%s, %s%s, TIMEOUT) != RPC_SUCCESS)\n",
299				    proc->proc_name,
300				    stringfix(proc->args.decls->decl.type),
301				    (newstyle ? "&" : ""),
302				    (newstyle ? proc->args.decls->decl.name : "argp"),
303				    stringfix(proc->res_type),
304				    ampr(proc->res_type), RESULT);
305			}
306		}
307	}
308	if (!Mflag) {
309		f_print(fout, "\t\treturn (NULL);\n");
310		if (streq(proc->res_type, "void"))
311			f_print(fout, "\treturn ((void *)%s%s);\n",
312			    ampr(proc->res_type), RESULT);
313		else
314			f_print(fout, "\treturn (%s%s);\n",
315			    ampr(proc->res_type), RESULT);
316	}
317}
318