xref: /netbsd/usr.bin/rpcgen/rpc_clntout.c (revision bf9ec67e)
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 #include <sys/cdefs.h>
33 #if defined(__RCSID) && !defined(lint)
34 #if 0
35 static char sccsid[] = "@(#)rpc_clntout.c 1.11 89/02/22 (C) 1987 SMI";
36 #else
37 __RCSID("$NetBSD: rpc_clntout.c,v 1.12 2002/01/31 19:36:48 tv Exp $");
38 #endif
39 #endif
40 
41 /*
42  * rpc_clntout.c, Client-stub outputter for the RPC protocol compiler
43  * Copyright (C) 1987, Sun Microsytsems, Inc.
44  */
45 #include <stdio.h>
46 #include <string.h>
47 #include <rpc/types.h>
48 #include "rpc_scan.h"
49 #include "rpc_parse.h"
50 #include "rpc_util.h"
51 
52 static void write_program __P((definition *));
53 static char *ampr __P((char *));
54 static char *aster __P((char *));
55 static void printbody __P((proc_list *));
56 
57 #define DEFAULT_TIMEOUT 25	/* in seconds */
58 static char RESULT[] = "clnt_res";
59 
60 
61 void
62 write_stubs()
63 {
64 	list   *l;
65 	definition *def;
66 
67 	f_print(fout,
68 	    "\n/* Default timeout can be changed using clnt_control() */\n");
69 	f_print(fout, "static struct timeval TIMEOUT = { %d, 0 };\n",
70 	    DEFAULT_TIMEOUT);
71 	for (l = defined; l != NULL; l = l->next) {
72 		def = (definition *) l->val;
73 		if (def->def_kind == DEF_PROGRAM) {
74 			write_program(def);
75 		}
76 	}
77 }
78 
79 static void
80 write_program(def)
81 	definition *def;
82 {
83 	version_list *vp;
84 	proc_list *proc;
85 
86 	for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) {
87 		for (proc = vp->procs; proc != NULL; proc = proc->next) {
88 			f_print(fout, "\n");
89 			if (Mflag)
90 				f_print(fout, "enum clnt_stat\n");
91 			else {
92 				ptype(proc->res_prefix, proc->res_type, 1);
93 				f_print(fout, "*\n");
94 			}
95 			pvname(proc->proc_name, vp->vers_num);
96 			printarglist(proc, RESULT, "clnt", "CLIENT *");
97 			f_print(fout, "{\n");
98 			printbody(proc);
99 			f_print(fout, "}\n");
100 		}
101 	}
102 }
103 /* Writes out declarations of procedure's argument list.
104    In either ANSI C style, in one of old rpcgen style (pass by reference),
105    or new rpcgen style (multiple arguments, pass by value);
106    */
107 
108 /* sample addargname = "clnt"; sample addargtype = "CLIENT * " */
109 
110 void
111 printarglist(proc, result, addargname, addargtype)
112 	proc_list *proc;
113 	char   *result, *addargname, *addargtype;
114 {
115 
116 	decl_list *l;
117 
118 	if (!newstyle) {	/* old style: always pass argument by
119 				 * reference */
120 		if (Cflag) {	/* C++ style heading */
121 			f_print(fout, "(");
122 			ptype(proc->args.decls->decl.prefix, proc->args.decls->decl.type, 1);
123 			f_print(fout, "*argp, ");
124 			if (Mflag) {
125 				if (streq(proc->res_type, "void"))
126 					f_print(fout, "char ");
127 				else
128 					ptype(proc->res_prefix, proc->res_type, 0);
129 				f_print(fout, "%s%s, ", aster(proc->res_type),
130 				    result);
131 			}
132 			f_print(fout, "%s%s)\n", addargtype, addargname);
133 		} else {
134 			f_print(fout, "(argp, ");
135 			if (Mflag)
136 				f_print(fout, "%s, ", result);
137 			f_print(fout, "%s)\n", addargname);
138 			f_print(fout, "\t");
139 			ptype(proc->args.decls->decl.prefix, proc->args.decls->decl.type, 1);
140 			f_print(fout, "*argp;\n");
141 			if (Mflag) {
142 				f_print(fout, "\t");
143 				if (streq(proc->res_type, "void"))
144 					f_print(fout, "char ");
145 				else
146 					ptype(proc->res_prefix, proc->res_type, 0);
147 				f_print(fout, "%s%s;\n", aster(proc->res_type),
148 				    result);
149 			}
150 		}
151 	} else {
152 		f_print(fout, "(");
153 		if (!streq(proc->args.decls->decl.type, "void")) {
154 			/* new style, 1 or multiple arguments */
155 			if (!Cflag) {
156 				for (l = proc->args.decls; l != NULL;
157 				    l = l->next)
158 					f_print(fout, "%s, ", l->decl.name);
159 			} else {/* C++ style header */
160 				for (l = proc->args.decls; l != NULL;
161 				    l = l->next)
162 					pdeclaration(proc->args.argname,
163 					    &l->decl, 0, ", ");
164 			}
165 		}
166 		if (!Cflag) {
167 			if (Mflag) {
168 				f_print(fout, "\t");
169 				if (streq(proc->res_type, "void"))
170 					f_print(fout, "char ");
171 				else
172 					ptype(proc->res_prefix, proc->res_type, 0);
173 				f_print(fout, "%s%s;\n", aster(proc->res_type),
174 				    result);
175 			}
176 			f_print(fout, "%s)\n", addargname);
177 			if (!streq(proc->args.decls->decl.type, "void")) {
178 				for (l = proc->args.decls; l != NULL;
179 				    l = l->next)
180 					pdeclaration(proc->args.argname,
181 					    &l->decl, 1, ";\n");
182 			}
183 		} else {
184 			if (Mflag) {
185 				if (streq(proc->res_type, "void"))
186 					f_print(fout, "char ");
187 				else
188 					ptype(proc->res_prefix, proc->res_type, 0);
189 				f_print(fout, "%s%s, ", aster(proc->res_type),
190 				    result);
191 			}
192 			f_print(fout, "%s%s)\n", addargtype, addargname);
193 		}
194 	}
195 
196 	if (!Cflag)
197 		f_print(fout, "\t%s%s;\n", addargtype, addargname);
198 }
199 
200 
201 static char *
202 ampr(type)
203 	char   *type;
204 {
205 	if (isvectordef(type, REL_ALIAS)) {
206 		return ("");
207 	} else {
208 		return ("&");
209 	}
210 }
211 
212 static char *
213 aster(type)
214 	char   *type;
215 {
216 	if (isvectordef(type, REL_ALIAS)) {
217 		return ("");
218 	} else {
219 		return ("*");
220 	}
221 }
222 
223 static void
224 printbody(proc)
225 	proc_list *proc;
226 {
227 	decl_list *l;
228 	bool_t  args2 = (proc->arg_num > 1);
229 
230 	/* For new style with multiple arguments, need a structure in which to
231 	 * stuff the arguments. */
232 	if (newstyle && args2) {
233 		f_print(fout, "\t%s", proc->args.argname);
234 		f_print(fout, " arg;\n");
235 	}
236 	if (!Mflag) {
237 		f_print(fout, "\tstatic ");
238 		if (streq(proc->res_type, "void"))
239 			f_print(fout, "char ");
240 		else
241 			ptype(proc->res_prefix, proc->res_type, 0);
242 		f_print(fout, "%s;\n", RESULT);
243 	}
244 	f_print(fout, "\n");
245 	if (!Mflag)
246 		f_print(fout, "\tmemset((char *)%s%s, 0, sizeof(%s));\n",
247 		    ampr(proc->res_type), RESULT, RESULT);
248 	if (newstyle && !args2 && (streq(proc->args.decls->decl.type, "void"))) {
249 		/* newstyle, 0 arguments */
250 		if (Mflag) {
251 			f_print(fout, "\treturn (clnt_call(clnt, %s, xdr_void",
252 			    proc->proc_name);
253 			f_print(fout, ", NULL, xdr_%s, %s, TIMEOUT));\n",
254 			    stringfix(proc->res_type), RESULT);
255 		} else {
256 			f_print(fout, "\tif (clnt_call(clnt, %s, xdr_void, ",
257 			    proc->proc_name);
258 			f_print(fout,
259 			    "NULL, xdr_%s, %s%s, TIMEOUT) != RPC_SUCCESS)\n",
260 			    stringfix(proc->res_type), ampr(proc->res_type),
261 			    RESULT);
262 		}
263 	} else {
264 		if (newstyle && args2) {
265 			/* newstyle, multiple arguments:  stuff arguments into
266 			 * structure */
267 			for (l = proc->args.decls; l != NULL; l = l->next) {
268 				f_print(fout, "\targ.%s = %s;\n",
269 				    l->decl.name, l->decl.name);
270 			}
271 			if (Mflag) {
272 				f_print(fout,
273 				    "\treturn (clnt_call(clnt, %s, xdr_%s, &arg, xdr_%s, %s, TIMEOUT));\n",
274 				    proc->proc_name, proc->args.argname,
275 				    stringfix(proc->res_type), RESULT);
276 			} else {
277 				f_print(fout,
278 				    "\tif (clnt_call(clnt, %s, xdr_%s, &arg, xdr_%s, %s%s, TIMEOUT) != RPC_SUCCESS)\n",
279 				    proc->proc_name, proc->args.argname,
280 				    stringfix(proc->res_type),
281 				    ampr(proc->res_type), RESULT);
282 			}
283 		} else {	/* single argument, new or old style */
284 			if (Mflag) {
285 				f_print(fout,
286 				    "\treturn (clnt_call(clnt, %s, xdr_%s, %s%s, xdr_%s, %s, TIMEOUT));\n",
287 				    proc->proc_name,
288 				    stringfix(proc->args.decls->decl.type),
289 				    (newstyle ? "&" : ""),
290 				    (newstyle ? proc->args.decls->decl.name : "argp"),
291 				    stringfix(proc->res_type), RESULT);
292 			} else {
293 				f_print(fout,
294 				    "\tif (clnt_call(clnt, %s, xdr_%s, %s%s, xdr_%s, %s%s, TIMEOUT) != RPC_SUCCESS)\n",
295 				    proc->proc_name,
296 				    stringfix(proc->args.decls->decl.type),
297 				    (newstyle ? "&" : ""),
298 				    (newstyle ? proc->args.decls->decl.name : "argp"),
299 				    stringfix(proc->res_type),
300 				    ampr(proc->res_type), RESULT);
301 			}
302 		}
303 	}
304 	if (!Mflag) {
305 		f_print(fout, "\t\treturn (NULL);\n");
306 		if (streq(proc->res_type, "void"))
307 			f_print(fout, "\treturn ((void *)%s%s);\n",
308 			    ampr(proc->res_type), RESULT);
309 		else
310 			f_print(fout, "\treturn (%s%s);\n",
311 			    ampr(proc->res_type), RESULT);
312 	}
313 }
314