xref: /illumos-gate/usr/src/cmd/rpcgen/rpc_clntout.c (revision 5279807d7e1818eac6f90ac640b7a89cdb37522d)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
27 /* All Rights Reserved */
28 /*
29  * University Copyright- Copyright (c) 1982, 1986, 1988
30  * The Regents of the University of California
31  * All Rights Reserved
32  *
33  * University Acknowledgment- Portions of this document are derived from
34  * software developed by the University of California, Berkeley, and its
35  * contributors.
36  */
37 
38 /*
39  * rpc_clntout.c, Client-stub outputter for the RPC protocol compiler
40  */
41 #include <stdio.h>
42 #include <string.h>
43 #include <rpc/types.h>
44 #include "rpc_parse.h"
45 #include "rpc_util.h"
46 
47 extern void pdeclaration(char *, declaration *, int, char *);
48 extern void printarglist(proc_list *, char *, char *, char *);
49 
50 static void write_program(definition *);
51 static void printbody(proc_list *);
52 
53 static char RESULT[] = "clnt_res";
54 
55 #define	DEFAULT_TIMEOUT 25	/* in seconds */
56 
57 void
58 write_stubs(void)
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 
75 static void
76 write_program(definition *def)
77 {
78 	version_list *vp;
79 	proc_list *proc;
80 
81 	for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) {
82 		for (proc = vp->procs; proc != NULL; proc = proc->next) {
83 			f_print(fout, "\n");
84 			if (mtflag == 0) {
85 				ptype(proc->res_prefix, proc->res_type, 1);
86 				f_print(fout, "*\n");
87 				pvname(proc->proc_name, vp->vers_num);
88 				printarglist(proc, RESULT, "clnt", "CLIENT *");
89 			} else {
90 				f_print(fout, "enum clnt_stat \n");
91 				pvname(proc->proc_name, vp->vers_num);
92 				printarglist(proc, RESULT,  "clnt", "CLIENT *");
93 
94 			}
95 			f_print(fout, "{\n");
96 			printbody(proc);
97 
98 			f_print(fout, "}\n");
99 		}
100 	}
101 }
102 
103 /*
104  * Writes out declarations of procedure's argument list.
105  * In either ANSI C style, in one of old rpcgen style (pass by reference),
106  * or new rpcgen style (multiple arguments, pass by value);
107  */
108 
109 /* sample addargname = "clnt"; sample addargtype = "CLIENT * " */
110 
111 void
112 printarglist(proc_list *proc, char *result, char *addargname, char *addargtype)
113 {
114 	bool_t oneway = streq(proc->res_type, "oneway");
115 	decl_list *l;
116 
117 	if (!newstyle) {
118 		/* old style: always pass argument by reference */
119 		if (Cflag) {	/* C++ style heading */
120 			f_print(fout, "(");
121 			ptype(proc->args.decls->decl.prefix,
122 			    proc->args.decls->decl.type, 1);
123 
124 			if (mtflag) {	/* Generate result field */
125 				f_print(fout, "*argp, ");
126 				if (!oneway) {
127 					ptype(proc->res_prefix,
128 					    proc->res_type, 1);
129 					f_print(fout, "*%s, ", result);
130 				}
131 				f_print(fout, "%s%s)\n",
132 				    addargtype, addargname);
133 			} else
134 				f_print(fout, "*argp, %s%s)\n",
135 				    addargtype, addargname);
136 		} else {
137 			if (!mtflag)
138 				f_print(fout, "(argp, %s)\n", addargname);
139 			else {
140 				f_print(fout, "(argp, ");
141 				if (!oneway) {
142 					f_print(fout, "%s, ",
143 					    result);
144 				}
145 				f_print(fout, "%s)\n",
146 				    addargname);
147 			}
148 			f_print(fout, "\t");
149 			ptype(proc->args.decls->decl.prefix,
150 			    proc->args.decls->decl.type, 1);
151 			f_print(fout, "*argp;\n");
152 			if (mtflag && !oneway) {
153 				f_print(fout, "\t");
154 				ptype(proc->res_prefix, proc->res_type, 1);
155 				f_print(fout, "*%s;\n", result);
156 			}
157 		}
158 	} else if (streq(proc->args.decls->decl.type, "void")) {
159 		/* newstyle, 0 argument */
160 		if (mtflag) {
161 			f_print(fout, "(");
162 
163 			if (Cflag) {
164 				if (!oneway) {
165 					ptype(proc->res_prefix,
166 					    proc->res_type, 1);
167 					f_print(fout, "*%s, ", result);
168 				}
169 				f_print(fout, "%s%s)\n",
170 				    addargtype, addargname);
171 			} else
172 				f_print(fout, "(%s)\n", addargname);
173 
174 		} else
175 		if (Cflag)
176 			f_print(fout, "(%s%s)\n", addargtype, addargname);
177 		else
178 			f_print(fout, "(%s)\n", addargname);
179 	} else {
180 		/* new style, 1 or multiple arguments */
181 		if (!Cflag) {
182 			f_print(fout, "(");
183 			for (l = proc->args.decls;  l != NULL; l = l->next)
184 				f_print(fout, "%s, ", l->decl.name);
185 			if (mtflag && !oneway)
186 				f_print(fout, "%s, ", result);
187 
188 			f_print(fout, "%s)\n", addargname);
189 			for (l = proc->args.decls; l != NULL; l = l->next) {
190 				pdeclaration(proc->args.argname,
191 				    &l->decl, 1, ";\n");
192 			}
193 			if (mtflag && !oneway) {
194 				f_print(fout, "\t");
195 				ptype(proc->res_prefix, proc->res_type, 1);
196 				f_print(fout, "*%s;\n", result);
197 			}
198 
199 		} else {	/* C++ style header */
200 			f_print(fout, "(");
201 			for (l = proc->args.decls; l != NULL; l = l->next) {
202 				pdeclaration(proc->args.argname, &l->decl, 0,
203 				    ", ");
204 			}
205 			if (mtflag && !oneway) {
206 				ptype(proc->res_prefix, proc->res_type, 1);
207 				f_print(fout, "*%s, ", result);
208 
209 			}
210 			f_print(fout, "%s%s)\n", addargtype, addargname);
211 		}
212 	}
213 
214 	if (!Cflag)
215 		f_print(fout, "\t%s%s;\n", addargtype, addargname);
216 }
217 
218 
219 
220 static char *
221 ampr(char *type)
222 {
223 	if (isvectordef(type, REL_ALIAS)) {
224 		return ("");
225 	} else {
226 		return ("&");
227 	}
228 }
229 
230 static void
231 printbody(proc_list *proc)
232 {
233 	decl_list *l;
234 	bool_t args2 = (proc->arg_num > 1);
235 	bool_t oneway = streq(proc->res_type, "oneway");
236 
237 	/*
238 	 * For new style with multiple arguments, need a structure in which
239 	 *  to stuff the arguments.
240 	 */
241 	if (newstyle && args2) {
242 		f_print(fout, "\t%s", proc->args.argname);
243 		f_print(fout, " arg;\n");
244 	}
245 	if (!oneway) {
246 		if (!mtflag) {
247 			f_print(fout, "\tstatic ");
248 			if (streq(proc->res_type, "void")) {
249 				f_print(fout, "char ");
250 			} else {
251 				ptype(proc->res_prefix, proc->res_type, 0);
252 			}
253 			f_print(fout, "%s;\n", RESULT);
254 			f_print(fout, "\n");
255 			f_print(fout,
256 			    "\t(void) memset(%s%s, 0, sizeof (%s));\n",
257 			    ampr(proc->res_type), RESULT, RESULT);
258 
259 		}
260 		if (newstyle && !args2 &&
261 		    (streq(proc->args.decls->decl.type, "void"))) {
262 			/* newstyle, 0 arguments */
263 
264 			if (mtflag)
265 				f_print(fout, "\t return ");
266 			else
267 				f_print(fout, "\t if ");
268 
269 			f_print(fout,
270 			    "(clnt_call(clnt, %s,\n\t\t(xdrproc_t)xdr_void, ",
271 			    proc->proc_name);
272 			f_print(fout,
273 			    "NULL,\n\t\t(xdrproc_t)xdr_%s, "
274 			    "(caddr_t)%s%s,",
275 			    stringfix(proc->res_type),
276 			    (mtflag)?"":ampr(proc->res_type),
277 			    RESULT);
278 
279 			if (mtflag)
280 				f_print(fout, "\n\t\tTIMEOUT));\n");
281 			else
282 				f_print(fout,
283 				    "\n\t\tTIMEOUT) != RPC_SUCCESS) {\n");
284 
285 		} else if (newstyle && args2) {
286 			/*
287 			 * Newstyle, multiple arguments
288 			 * stuff arguments into structure
289 			 */
290 			for (l = proc->args.decls;  l != NULL; l = l->next) {
291 				f_print(fout, "\targ.%s = %s;\n",
292 				    l->decl.name, l->decl.name);
293 			}
294 			if (mtflag)
295 				f_print(fout, "\treturn ");
296 			else
297 				f_print(fout, "\tif ");
298 			f_print(fout,
299 			    "(clnt_call(clnt, %s,\n\t\t(xdrproc_t)xdr_%s",
300 			    proc->proc_name, proc->args.argname);
301 			f_print(fout,
302 			    ", (caddr_t)&arg,\n\t\t(xdrproc_t)xdr_%s, "
303 			    "(caddr_t)%s%s,",
304 			    stringfix(proc->res_type),
305 			    (mtflag)?"":ampr(proc->res_type),
306 			    RESULT);
307 			if (mtflag)
308 				f_print(fout, "\n\t\tTIMEOUT));\n");
309 			else
310 				f_print(fout,
311 				    "\n\t\tTIMEOUT) != RPC_SUCCESS) {\n");
312 		} else {		/* single argument, new or old style */
313 			if (!mtflag)
314 				f_print(fout,
315 				    "\tif (clnt_call(clnt, "
316 				    "%s,\n\t\t(xdrproc_t)xdr_%s, "
317 				    "(caddr_t)%s%s,\n\t\t(xdrproc_t)xdr_%s, "
318 				    "(caddr_t)%s%s,\n\t\tTIMEOUT) != "
319 				    "RPC_SUCCESS) {\n",
320 				    proc->proc_name,
321 				    stringfix(proc->args.decls->decl.type),
322 				    (newstyle ? "&" : ""),
323 				    (newstyle ?
324 				    proc->args.decls->decl.name :
325 				    "argp"),
326 				    stringfix(proc->res_type),
327 				    ampr(proc->res_type),
328 				    RESULT);
329 			else
330 				f_print(fout,
331 				    "\treturn (clnt_call(clnt, "
332 				    "%s,\n\t\t(xdrproc_t)xdr_%s, "
333 				    "(caddr_t)%s%s,\n\t\t(xdrproc_t)xdr_%s, "
334 				    "(caddr_t)%s%s,\n\t\tTIMEOUT));\n",
335 				    proc->proc_name,
336 				    stringfix(proc->args.decls->decl.type),
337 				    (newstyle ? "&" : ""),
338 				    (newstyle ?
339 				    proc->args.decls->decl.name :
340 				    "argp"),
341 				    stringfix(proc->res_type), "",
342 				    RESULT);
343 		}
344 		if (!mtflag) {
345 			f_print(fout, "\t\treturn (NULL);\n");
346 			f_print(fout, "\t}\n");
347 
348 			if (streq(proc->res_type, "void")) {
349 				f_print(fout, "\treturn ((void *)%s%s);\n",
350 				    ampr(proc->res_type), RESULT);
351 			} else {
352 				f_print(fout, "\treturn (%s%s);\n",
353 				    ampr(proc->res_type), RESULT);
354 			}
355 		}
356 	} else {
357 		/* oneway call */
358 		if (!mtflag) {
359 			f_print(fout, "\tstatic enum clnt_stat ");
360 			f_print(fout, "%s;\n", RESULT);
361 			f_print(fout, "\n");
362 			f_print(fout,
363 			    "\t(void) memset(&%s, 0, sizeof (%s));\n",
364 			    RESULT, RESULT);
365 
366 		}
367 		if (newstyle && !args2 &&
368 		    (streq(proc->args.decls->decl.type, "void"))) {
369 			/* newstyle, 0 arguments */
370 
371 			if (mtflag)
372 				f_print(fout, "\t return (");
373 			else
374 				f_print(fout, "\t if ((%s = ", RESULT);
375 
376 			f_print(fout,
377 			    "clnt_send(clnt, %s,\n\t\t(xdrproc_t)xdr_void, ",
378 			    proc->proc_name);
379 			f_print(fout, "NULL)");
380 
381 			if (mtflag)
382 				f_print(fout, ");\n");
383 			else
384 				f_print(fout, ") != RPC_SUCCESS) {\n");
385 
386 		} else if (newstyle && args2) {
387 			/*
388 			 * Newstyle, multiple arguments
389 			 * stuff arguments into structure
390 			 */
391 			for (l = proc->args.decls;  l != NULL; l = l->next) {
392 				f_print(fout, "\targ.%s = %s;\n",
393 				    l->decl.name, l->decl.name);
394 			}
395 			if (mtflag)
396 				f_print(fout, "\treturn (");
397 			else
398 				f_print(fout, "\tif ((%s =", RESULT);
399 			f_print(fout,
400 			    "clnt_send(clnt, %s,\n\t\t(xdrproc_t)xdr_%s",
401 			    proc->proc_name, proc->args.argname);
402 			f_print(fout,
403 			    ", (caddr_t)&arg)");
404 			if (mtflag)
405 				f_print(fout, ");\n");
406 			else
407 				f_print(fout, ") != RPC_SUCCESS) {\n");
408 		} else {		/* single argument, new or old style */
409 			if (!mtflag)
410 				f_print(fout,
411 				    "\tif ((%s = clnt_send(clnt, "
412 				    "%s,\n\t\t(xdrproc_t)xdr_%s, "
413 				    "(caddr_t)%s%s)) != RPC_SUCCESS) {\n",
414 				    RESULT,
415 				    proc->proc_name,
416 				    stringfix(proc->args.decls->decl.type),
417 				    (newstyle ? "&" : ""),
418 				    (newstyle ?
419 				    proc->args.decls->decl.name :
420 				    "argp"));
421 			else
422 
423 				f_print(fout,
424 				    "\treturn (clnt_send(clnt, "
425 				    "%s,\n\t\t(xdrproc_t)xdr_%s, "
426 				    "(caddr_t)%s%s));\n",
427 				    proc->proc_name,
428 				    stringfix(proc->args.decls->decl.type),
429 				    (newstyle ? "&" : ""),
430 				    (newstyle ?
431 				    proc->args.decls->decl.name :
432 				    "argp"));
433 		}
434 		if (!mtflag) {
435 			f_print(fout, "\t\treturn (NULL);\n");
436 			f_print(fout, "\t}\n");
437 
438 			f_print(fout, "\treturn ((void *)&%s);\n",
439 			    RESULT);
440 		}
441 	}
442 }
443