xref: /freebsd/usr.bin/rpcgen/rpc_clntout.c (revision 40ad88851bea3bb7fce12e7d23e5a0c1159e9080)
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 #if 0
36 static char sccsid[] = "@(#)rpc_clntout.c 1.11 89/02/22 (C) 1987 SMI";
37 #endif
38 #endif
39 
40 /*
41  * rpc_clntout.c, Client-stub outputter for the RPC protocol compiler
42  * Copyright (C) 1987, Sun Microsytsems, Inc.
43  */
44 #include <stdio.h>
45 #include <string.h>
46 #include <rpc/types.h>
47 #include "rpc_parse.h"
48 #include "rpc_util.h"
49 
50 extern void pdeclaration( char *, declaration *, int, char * );
51 void printarglist( proc_list *, char *, char *, char *);
52 static void write_program( definition * );
53 static void printbody( proc_list * );
54 
55 static char RESULT[] = "clnt_res";
56 
57 
58 #define DEFAULT_TIMEOUT 25	/* in seconds */
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 (mtflag == 0) {
90 				ptype(proc->res_prefix, proc->res_type, 1);
91 				f_print(fout, "*\n");
92 				pvname(proc->proc_name, vp->vers_num);
93 				printarglist(proc, RESULT, "clnt", "CLIENT *");
94 			} else {
95 				f_print(fout, "enum clnt_stat \n");
96 				pvname(proc->proc_name, vp->vers_num);
97 				printarglist(proc, RESULT,  "clnt", "CLIENT *");
98 
99 			}
100 			f_print(fout, "{\n");
101 			printbody(proc);
102 
103 			f_print(fout, "}\n");
104 		}
105 	}
106 }
107 
108 /*
109  * Writes out declarations of procedure's argument list.
110  * In either ANSI C style, in one of old rpcgen style (pass by reference),
111  * or new rpcgen style (multiple arguments, pass by value);
112  */
113 
114 /* sample addargname = "clnt"; sample addargtype = "CLIENT * " */
115 
116 void printarglist(proc, result, addargname, addargtype)
117 	proc_list *proc;
118 	char *result;
119 	char* addargname, * addargtype;
120 {
121 
122 	decl_list *l;
123 
124 	if (!newstyle) {
125 		/* old style: always pass argument by reference */
126 		if (Cflag) {	/* C++ style heading */
127 			f_print(fout, "(");
128 			ptype(proc->args.decls->decl.prefix,
129 			      proc->args.decls->decl.type, 1);
130 
131 			if (mtflag) {/* Generate result field */
132 				f_print(fout, "*argp, ");
133 				ptype(proc->res_prefix, proc->res_type, 1);
134 				f_print(fout, "*%s, %s%s)\n",
135 					result, addargtype, addargname);
136 			} else
137 				f_print(fout, "*argp, %s%s)\n", addargtype, addargname);
138 		} else {
139 			if (!mtflag)
140 				f_print(fout, "(argp, %s)\n", addargname);
141 			else
142 				f_print(fout, "(argp, %s, %s)\n",
143 					result, addargname);
144 			f_print(fout, "\t");
145 			ptype(proc->args.decls->decl.prefix,
146 			      proc->args.decls->decl.type, 1);
147 			f_print(fout, "*argp;\n");
148 			if (mtflag) {
149 				f_print(fout, "\t");
150 				ptype(proc->res_prefix, proc->res_type, 1);
151 				f_print(fout, "*%s;\n", result);
152 			}
153 		}
154 	} else if (streq(proc->args.decls->decl.type, "void")) {
155 		/* newstyle, 0 argument */
156 		if (mtflag) {
157 				f_print(fout, "(");
158 
159 
160 			if (Cflag) {
161 				ptype(proc->res_prefix, proc->res_type, 1);
162 				f_print(fout, "*%s, %s%s)\n",
163 					result, addargtype, addargname);
164 			}
165 			else
166 				f_print(fout, "(%s)\n", addargname);
167 
168 		} else
169 		if (Cflag)
170 			f_print(fout, "(%s%s)\n", addargtype, addargname);
171 		else
172 			f_print(fout, "(%s)\n", addargname);
173 	} else {
174 		/* new style, 1 or multiple arguments */
175 		if (!Cflag) {
176 			f_print(fout, "(");
177 			for (l = proc->args.decls;  l != NULL; l = l->next)
178 				f_print(fout, "%s, ", l->decl.name);
179 			if (mtflag)
180 				f_print(fout, "%s, ", result);
181 
182 			f_print(fout, "%s)\n", addargname);
183 			for (l = proc->args.decls; l != NULL; l = l->next) {
184 				pdeclaration(proc->args.argname,
185 					     &l->decl, 1, ";\n");
186 			}
187 			if (mtflag) {
188 				f_print(fout, "\t");
189 				ptype(proc->res_prefix, proc->res_type, 1);
190 				f_print(fout, "*%s;\n", result);
191 			}
192 
193 		} else {	/* C++ style header */
194 			f_print(fout, "(");
195 			for (l = proc->args.decls; l != NULL; l = l->next) {
196 				pdeclaration(proc->args.argname, &l->decl, 0,
197 					     ", ");
198 			}
199 			if (mtflag) {
200 				ptype(proc->res_prefix, proc->res_type, 1);
201 				f_print(fout, "*%s, ", result);
202 
203 			}
204 			f_print(fout, "%s%s)\n", addargtype, addargname);
205 		}
206 	}
207 
208 	if (!Cflag)
209 		f_print(fout, "\t%s%s;\n", addargtype, addargname);
210 }
211 
212 
213 
214 static char *
215 ampr(type)
216 	char *type;
217 {
218 	if (isvectordef(type, REL_ALIAS)) {
219 		return ("");
220 	} else {
221 		return ("&");
222 	}
223 }
224 
225 static void
226 printbody(proc)
227 	proc_list *proc;
228 {
229 	decl_list *l;
230 	bool_t args2 = (proc->arg_num > 1);
231 
232 	/*
233 	 * For new style with multiple arguments, need a structure in which
234 	 *  to stuff the arguments.
235 	 */
236 
237 
238 	if (newstyle && args2) {
239 		f_print(fout, "\t%s", proc->args.argname);
240 		f_print(fout, " arg;\n");
241 	}
242 	if (!mtflag) {
243 		f_print(fout, "\tstatic ");
244 		if (streq(proc->res_type, "void")) {
245 			f_print(fout, "char ");
246 		} else {
247 			ptype(proc->res_prefix, proc->res_type, 0);
248 		}
249 		f_print(fout, "%s;\n", RESULT);
250 		f_print(fout, "\n");
251 		f_print(fout, "\tmemset((char *)%s%s, 0, sizeof (%s));\n",
252 			ampr(proc->res_type), RESULT, RESULT);
253 
254 	}
255 	if (newstyle && !args2 &&
256 	    (streq(proc->args.decls->decl.type, "void"))) {
257 		/* newstyle, 0 arguments */
258 
259 		if (mtflag)
260 			f_print(fout, "\t return ");
261 		else
262 			f_print(fout, "\t if ");
263 
264 		f_print(fout,
265 			"(clnt_call(clnt, %s,\n\t\t(xdrproc_t) xdr_void, ",
266 			proc->proc_name);
267 		f_print(fout,
268 			"(caddr_t) NULL,\n\t\t(xdrproc_t) xdr_%s, (caddr_t) %s%s,",
269 			stringfix(proc->res_type), (mtflag)?"":ampr(proc->res_type),
270 			RESULT);
271 
272 		if (mtflag)
273 			f_print(fout, "\n\t\tTIMEOUT));\n");
274 		else
275 			f_print(fout, "\n\t\tTIMEOUT) != RPC_SUCCESS) {\n");
276 
277 	} else if (newstyle && args2) {
278 		/*
279 		 * Newstyle, multiple arguments
280 		 * stuff arguments into structure
281 		 */
282 		for (l = proc->args.decls;  l != NULL; l = l->next) {
283 			f_print(fout, "\targ.%s = %s;\n",
284 				l->decl.name, l->decl.name);
285 		}
286 		if (mtflag)
287 			f_print(fout, "\treturn ");
288 		else
289 			f_print(fout, "\tif ");
290 		f_print(fout,
291 			"(clnt_call(clnt, %s,\n\t\t(xdrproc_t) xdr_%s",
292 			proc->proc_name,proc->args.argname);
293 		f_print(fout,
294 			", (caddr_t) &arg,\n\t\t(xdrproc_t) xdr_%s, (caddr_t) %s%s,",
295 			stringfix(proc->res_type), (mtflag)?"":ampr(proc->res_type),
296 			RESULT);
297 		if (mtflag)
298 			f_print(fout, "\n\t\tTIMEOUT));\n");
299 		else
300 			f_print(fout, "\n\t\tTIMEOUT) != RPC_SUCCESS) {\n");
301 	} else {		/* single argument, new or old style */
302 		if (!mtflag)
303 			f_print(fout,
304 			"\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",
305 			proc->proc_name,
306 			stringfix(proc->args.decls->decl.type),
307 			(newstyle ? "&" : ""),
308 			(newstyle ? proc->args.decls->decl.name : "argp"),
309 			stringfix(proc->res_type), ampr(proc->res_type),
310 			RESULT);
311 		else
312 
313 		f_print(fout,
314 			"\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",
315 			proc->proc_name,
316 			stringfix(proc->args.decls->decl.type),
317 			(newstyle ? "&" : ""),
318 			(newstyle ? proc->args.decls->decl.name : "argp"),
319 			stringfix(proc->res_type), "",
320 			RESULT);
321 	}
322 	if (!mtflag) {
323 		f_print(fout, "\t\treturn (NULL);\n");
324 		f_print(fout, "\t}\n");
325 
326 		if (streq(proc->res_type, "void")) {
327 			f_print(fout, "\treturn ((void *)%s%s);\n",
328 				ampr(proc->res_type), RESULT);
329 		} else {
330 			f_print(fout, "\treturn (%s%s);\n",
331 				ampr(proc->res_type), RESULT);
332 		}
333 	}
334 }
335