xref: /freebsd/usr.bin/rpcgen/rpc_clntout.c (revision d3cb5ded92a4fcf21400c9742ca884549bebc99e)
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  * $FreeBSD$
30  */
31 
32 #ident	"@(#)rpc_clntout.c	1.15	94/04/25 SMI"
33 
34 #ifndef lint
35 static char sccsid[] = "@(#)rpc_clntout.c 1.11 89/02/22 (C) 1987 SMI";
36 #endif
37 
38 /*
39  * rpc_clntout.c, Client-stub outputter for the RPC protocol compiler
40  * Copyright (C) 1987, Sun Microsytsems, Inc.
41  */
42 #include <stdio.h>
43 #include <string.h>
44 #include <rpc/types.h>
45 #include "rpc_parse.h"
46 #include "rpc_util.h"
47 
48 extern void pdeclaration( char *, declaration *, int, char * );
49 void printarglist( proc_list *, char *, char *, char *);
50 static void write_program( definition * );
51 static void printbody( proc_list * );
52 
53 static char RESULT[] = "clnt_res";
54 
55 
56 #define DEFAULT_TIMEOUT 25	/* in seconds */
57 
58 
59 void
60 write_stubs()
61 {
62 	list *l;
63 	definition *def;
64 
65 	f_print(fout,
66 		"\n/* Default timeout can be changed using clnt_control() */\n");
67 	f_print(fout, "static struct timeval TIMEOUT = { %d, 0 };\n",
68 		DEFAULT_TIMEOUT);
69 	for (l = defined; l != NULL; l = l->next) {
70 		def = (definition *) l->val;
71 		if (def->def_kind == DEF_PROGRAM) {
72 			write_program(def);
73 		}
74 	}
75 }
76 
77 static void
78 write_program(def)
79 	definition *def;
80 {
81 	version_list *vp;
82 	proc_list *proc;
83 
84 	for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) {
85 		for (proc = vp->procs; proc != NULL; proc = proc->next) {
86 			f_print(fout, "\n");
87 			if (mtflag == 0) {
88 				ptype(proc->res_prefix, proc->res_type, 1);
89 				f_print(fout, "*\n");
90 				pvname(proc->proc_name, vp->vers_num);
91 				printarglist(proc, RESULT, "clnt", "CLIENT *");
92 			} else {
93 				f_print(fout, "enum clnt_stat \n");
94 				pvname(proc->proc_name, vp->vers_num);
95 				printarglist(proc, RESULT,  "clnt", "CLIENT *");
96 
97 			}
98 			f_print(fout, "{\n");
99 			printbody(proc);
100 
101 			f_print(fout, "}\n");
102 		}
103 	}
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 
114 void printarglist(proc, result, addargname, addargtype)
115 	proc_list *proc;
116 	char *result;
117 	char* addargname, * addargtype;
118 {
119 
120 	decl_list *l;
121 
122 	if (!newstyle) {
123 		/* old style: always pass argument by reference */
124 		if (Cflag) {	/* C++ style heading */
125 			f_print(fout, "(");
126 			ptype(proc->args.decls->decl.prefix,
127 			      proc->args.decls->decl.type, 1);
128 
129 			if (mtflag) {/* Generate result field */
130 				f_print(fout, "*argp, ");
131 				ptype(proc->res_prefix, proc->res_type, 1);
132 				f_print(fout, "*%s, %s%s)\n",
133 					result, addargtype, addargname);
134 			} else
135 				f_print(fout, "*argp, %s%s)\n", addargtype, addargname);
136 		} else {
137 			if (!mtflag)
138 				f_print(fout, "(argp, %s)\n", addargname);
139 			else
140 				f_print(fout, "(argp, %s, %s)\n",
141 					result, addargname);
142 			f_print(fout, "\t");
143 			ptype(proc->args.decls->decl.prefix,
144 			      proc->args.decls->decl.type, 1);
145 			f_print(fout, "*argp;\n");
146 			if (mtflag) {
147 				f_print(fout, "\t");
148 				ptype(proc->res_prefix, proc->res_type, 1);
149 				f_print(fout, "*%s;\n", result);
150 			}
151 		}
152 	} else if (streq(proc->args.decls->decl.type, "void")) {
153 		/* newstyle, 0 argument */
154 		if (mtflag) {
155 				f_print(fout, "(");
156 
157 
158 			if (Cflag) {
159 				ptype(proc->res_prefix, proc->res_type, 1);
160 				f_print(fout, "*%s, %s%s)\n",
161 					result, addargtype, addargname);
162 			}
163 			else
164 				f_print(fout, "(%s)\n", addargname);
165 
166 		} else
167 		if (Cflag)
168 			f_print(fout, "(%s%s)\n", addargtype, addargname);
169 		else
170 			f_print(fout, "(%s)\n", addargname);
171 	} else {
172 		/* new style, 1 or multiple arguments */
173 		if (!Cflag) {
174 			f_print(fout, "(");
175 			for (l = proc->args.decls;  l != NULL; l = l->next)
176 				f_print(fout, "%s, ", l->decl.name);
177 			if (mtflag)
178 				f_print(fout, "%s, ", result);
179 
180 			f_print(fout, "%s)\n", addargname);
181 			for (l = proc->args.decls; l != NULL; l = l->next) {
182 				pdeclaration(proc->args.argname,
183 					     &l->decl, 1, ";\n");
184 			}
185 			if (mtflag) {
186 				f_print(fout, "\t");
187 				ptype(proc->res_prefix, proc->res_type, 1);
188 				f_print(fout, "*%s;\n", result);
189 			}
190 
191 		} else {	/* C++ style header */
192 			f_print(fout, "(");
193 			for (l = proc->args.decls; l != NULL; l = l->next) {
194 				pdeclaration(proc->args.argname, &l->decl, 0,
195 					     ", ");
196 			}
197 			if (mtflag) {
198 				ptype(proc->res_prefix, proc->res_type, 1);
199 				f_print(fout, "*%s, ", result);
200 
201 			}
202 			f_print(fout, "%s%s)\n", addargtype, addargname);
203 		}
204 	}
205 
206 	if (!Cflag)
207 		f_print(fout, "\t%s%s;\n", addargtype, addargname);
208 }
209 
210 
211 
212 static char *
213 ampr(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 	/*
231 	 * For new style with multiple arguments, need a structure in which
232 	 *  to stuff the arguments.
233 	 */
234 
235 
236 	if (newstyle && args2) {
237 		f_print(fout, "\t%s", proc->args.argname);
238 		f_print(fout, " arg;\n");
239 	}
240 	if (!mtflag) {
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 		}
247 		f_print(fout, "%s;\n", RESULT);
248 		f_print(fout, "\n");
249 		f_print(fout, "\tmemset((char *)%s%s, 0, sizeof (%s));\n",
250 			ampr(proc->res_type), RESULT, RESULT);
251 
252 	}
253 	if (newstyle && !args2 &&
254 	    (streq(proc->args.decls->decl.type, "void"))) {
255 		/* newstyle, 0 arguments */
256 
257 		if (mtflag)
258 			f_print(fout, "\t return ");
259 		else
260 			f_print(fout, "\t if ");
261 
262 		f_print(fout,
263 			"(clnt_call(clnt, %s,\n\t\t(xdrproc_t) xdr_void, ",
264 			proc->proc_name);
265 		f_print(fout,
266 			"(caddr_t) NULL,\n\t\t(xdrproc_t) xdr_%s, (caddr_t) %s%s,",
267 			stringfix(proc->res_type), (mtflag)?"":ampr(proc->res_type),
268 			RESULT);
269 
270 		if (mtflag)
271 			f_print(fout, "\n\t\tTIMEOUT));\n");
272 		else
273 			f_print(fout, "\n\t\tTIMEOUT) != RPC_SUCCESS) {\n");
274 
275 	} else if (newstyle && args2) {
276 		/*
277 		 * Newstyle, multiple arguments
278 		 * stuff arguments into structure
279 		 */
280 		for (l = proc->args.decls;  l != NULL; l = l->next) {
281 			f_print(fout, "\targ.%s = %s;\n",
282 				l->decl.name, l->decl.name);
283 		}
284 		if (mtflag)
285 			f_print(fout, "\treturn ");
286 		else
287 			f_print(fout, "\tif ");
288 		f_print(fout,
289 			"(clnt_call(clnt, %s,\n\t\t(xdrproc_t) xdr_%s",
290 			proc->proc_name,proc->args.argname);
291 		f_print(fout,
292 			", (caddr_t) &arg,\n\t\t(xdrproc_t) xdr_%s, (caddr_t) %s%s,",
293 			stringfix(proc->res_type), (mtflag)?"":ampr(proc->res_type),
294 			RESULT);
295 		if (mtflag)
296 			f_print(fout, "\n\t\tTIMEOUT));\n");
297 		else
298 			f_print(fout, "\n\t\tTIMEOUT) != RPC_SUCCESS) {\n");
299 	} else {		/* single argument, new or old style */
300 		if (!mtflag)
301 			f_print(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 
311 		f_print(fout,
312 			"\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 			proc->proc_name,
314 			stringfix(proc->args.decls->decl.type),
315 			(newstyle ? "&" : ""),
316 			(newstyle ? proc->args.decls->decl.name : "argp"),
317 			stringfix(proc->res_type), "",
318 			RESULT);
319 	}
320 	if (!mtflag) {
321 		f_print(fout, "\t\treturn (NULL);\n");
322 		f_print(fout, "\t}\n");
323 
324 		if (streq(proc->res_type, "void")) {
325 			f_print(fout, "\treturn ((void *)%s%s);\n",
326 				ampr(proc->res_type), RESULT);
327 		} else {
328 			f_print(fout, "\treturn (%s%s);\n",
329 				ampr(proc->res_type), RESULT);
330 		}
331 	}
332 }
333