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