Initial import from FreeBSD RELENG_4:
[dragonfly.git] / usr.bin / rpcgen / rpc_clntout.c
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
33 static 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
46 extern void pdeclaration __P(( char *, declaration *, int, char * ));
47 void printarglist __P(( proc_list *, char *, char *, char *));
48 static void write_program __P(( definition * ));
49 static void printbody __P(( proc_list * ));
50
51 static char RESULT[] = "clnt_res";
52
53
54 #define DEFAULT_TIMEOUT 25      /* in seconds */
55
56
57 void
58 write_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
75 static void
76 write_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
112 void 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
210 static char *
211 ampr(type)
212         char *type;
213 {
214         if (isvectordef(type, REL_ALIAS)) {
215                 return ("");
216         } else {
217                 return ("&");
218         }
219 }
220
221 static void
222 printbody(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 }