1 |
|
|
/* $OpenBSD: rpc_clntout.c,v 1.15 2010/09/01 14:43:34 millert Exp $ */ |
2 |
|
|
/* $NetBSD: rpc_clntout.c,v 1.4 1995/06/11 21:49:52 pk Exp $ */ |
3 |
|
|
|
4 |
|
|
/* |
5 |
|
|
* Copyright (c) 2010, Oracle America, Inc. |
6 |
|
|
* |
7 |
|
|
* Redistribution and use in source and binary forms, with or without |
8 |
|
|
* modification, are permitted provided that the following conditions are |
9 |
|
|
* met: |
10 |
|
|
* |
11 |
|
|
* * Redistributions of source code must retain the above copyright |
12 |
|
|
* notice, this list of conditions and the following disclaimer. |
13 |
|
|
* * Redistributions in binary form must reproduce the above |
14 |
|
|
* copyright notice, this list of conditions and the following |
15 |
|
|
* disclaimer in the documentation and/or other materials |
16 |
|
|
* provided with the distribution. |
17 |
|
|
* * Neither the name of the "Oracle America, Inc." nor the names of its |
18 |
|
|
* contributors may be used to endorse or promote products derived |
19 |
|
|
* from this software without specific prior written permission. |
20 |
|
|
* |
21 |
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
22 |
|
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
23 |
|
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS |
24 |
|
|
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE |
25 |
|
|
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, |
26 |
|
|
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
27 |
|
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE |
28 |
|
|
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
29 |
|
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, |
30 |
|
|
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
31 |
|
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
32 |
|
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
33 |
|
|
*/ |
34 |
|
|
|
35 |
|
|
/* |
36 |
|
|
* rpc_clntout.c, Client-stub outputter for the RPC protocol compiler |
37 |
|
|
*/ |
38 |
|
|
#include <stdio.h> |
39 |
|
|
#include <string.h> |
40 |
|
|
#include <rpc/types.h> |
41 |
|
|
#include "rpc_parse.h" |
42 |
|
|
#include "rpc_util.h" |
43 |
|
|
|
44 |
|
|
static void write_program(definition *); |
45 |
|
|
static void printbody(proc_list *); |
46 |
|
|
|
47 |
|
|
#define DEFAULT_TIMEOUT 25 /* in seconds */ |
48 |
|
|
static char RESULT[] = "clnt_res"; |
49 |
|
|
|
50 |
|
|
|
51 |
|
|
void |
52 |
|
|
write_stubs() |
53 |
|
|
{ |
54 |
|
|
list *l; |
55 |
|
|
definition *def; |
56 |
|
|
|
57 |
|
|
fprintf(fout, |
58 |
|
|
"\n/* Default timeout can be changed using clnt_control() */\n"); |
59 |
|
|
fprintf(fout, "static struct timeval TIMEOUT = { %d, 0 };\n", |
60 |
|
|
DEFAULT_TIMEOUT); |
61 |
|
|
for (l = defined; l != NULL; l = l->next) { |
62 |
|
|
def = (definition *) l->val; |
63 |
|
|
if (def->def_kind == DEF_PROGRAM) { |
64 |
|
|
write_program(def); |
65 |
|
|
} |
66 |
|
|
} |
67 |
|
|
} |
68 |
|
|
|
69 |
|
|
static void |
70 |
|
|
write_program(def) |
71 |
|
|
definition *def; |
72 |
|
|
{ |
73 |
|
|
version_list *vp; |
74 |
|
|
proc_list *proc; |
75 |
|
|
|
76 |
|
|
for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) { |
77 |
|
|
for (proc = vp->procs; proc != NULL; proc = proc->next) { |
78 |
|
|
fprintf(fout, "\n"); |
79 |
|
|
ptype(proc->res_prefix, proc->res_type, 1); |
80 |
|
|
fprintf(fout, "*\n"); |
81 |
|
|
pvname(proc->proc_name, vp->vers_num); |
82 |
|
|
printarglist(proc, "clnt", "CLIENT *"); |
83 |
|
|
fprintf(fout, "{\n"); |
84 |
|
|
printbody(proc); |
85 |
|
|
fprintf(fout, "}\n"); |
86 |
|
|
} |
87 |
|
|
} |
88 |
|
|
} |
89 |
|
|
|
90 |
|
|
/* |
91 |
|
|
* Writes out declarations of procedure's argument list. |
92 |
|
|
* In either ANSI C style, in one of old rpcgen style (pass by reference), |
93 |
|
|
* or new rpcgen style (multiple arguments, pass by value); |
94 |
|
|
*/ |
95 |
|
|
|
96 |
|
|
/* sample addargname = "clnt"; sample addargtype = "CLIENT * " */ |
97 |
|
|
|
98 |
|
|
void printarglist(proc, addargname, addargtype) |
99 |
|
|
proc_list *proc; |
100 |
|
|
char *addargname, *addargtype; |
101 |
|
|
{ |
102 |
|
|
decl_list *l; |
103 |
|
|
|
104 |
|
|
if (!newstyle) { /* old style: always pass argument by reference */ |
105 |
|
|
if (Cflag) { /* C++ style heading */ |
106 |
|
|
fprintf(fout, "("); |
107 |
|
|
ptype(proc->args.decls->decl.prefix, |
108 |
|
|
proc->args.decls->decl.type, 1); |
109 |
|
|
fprintf(fout, "*argp, %s%s)\n", addargtype, addargname); |
110 |
|
|
} else { |
111 |
|
|
fprintf(fout, "(argp, %s)\n", addargname); |
112 |
|
|
fprintf(fout, "\t"); |
113 |
|
|
ptype(proc->args.decls->decl.prefix, |
114 |
|
|
proc->args.decls->decl.type, 1); |
115 |
|
|
fprintf(fout, "*argp;\n"); |
116 |
|
|
} |
117 |
|
|
} else if (streq(proc->args.decls->decl.type, "void")) { |
118 |
|
|
/* newstyle, 0 argument */ |
119 |
|
|
if (Cflag) |
120 |
|
|
fprintf(fout, "(%s%s)\n", addargtype, addargname); |
121 |
|
|
else |
122 |
|
|
fprintf(fout, "(%s)\n", addargname); |
123 |
|
|
} else { |
124 |
|
|
/* new style, 1 or multiple arguments */ |
125 |
|
|
if (!Cflag) { |
126 |
|
|
fprintf(fout, "("); |
127 |
|
|
for (l = proc->args.decls; l != NULL; l = l->next) |
128 |
|
|
fprintf(fout, "%s, ", l->decl.name); |
129 |
|
|
fprintf(fout, "%s)\n", addargname); |
130 |
|
|
for (l = proc->args.decls; l != NULL; l = l->next) |
131 |
|
|
pdeclaration(proc->args.argname, &l->decl, 1, ";\n"); |
132 |
|
|
} else { /* C++ style header */ |
133 |
|
|
fprintf(fout, "("); |
134 |
|
|
for (l = proc->args.decls; l != NULL; l = l->next) |
135 |
|
|
pdeclaration(proc->args.argname, &l->decl, 0, ", "); |
136 |
|
|
fprintf(fout, " %s%s)\n", addargtype, addargname); |
137 |
|
|
} |
138 |
|
|
} |
139 |
|
|
|
140 |
|
|
if (!Cflag) |
141 |
|
|
fprintf(fout, "\t%s%s;\n", addargtype, addargname); |
142 |
|
|
} |
143 |
|
|
|
144 |
|
|
static char * |
145 |
|
|
ampr(char *type) |
146 |
|
|
{ |
147 |
|
|
if (isvectordef(type, REL_ALIAS)) { |
148 |
|
|
return (""); |
149 |
|
|
} else { |
150 |
|
|
return ("&"); |
151 |
|
|
} |
152 |
|
|
} |
153 |
|
|
|
154 |
|
|
static void |
155 |
|
|
printbody(proc) |
156 |
|
|
proc_list *proc; |
157 |
|
|
{ |
158 |
|
|
decl_list *l; |
159 |
|
|
bool_t args2 = (proc->arg_num > 1); |
160 |
|
|
|
161 |
|
|
/* |
162 |
|
|
* For new style with multiple arguments, need a structure in which |
163 |
|
|
* to stuff the arguments. |
164 |
|
|
*/ |
165 |
|
|
if (newstyle && args2) { |
166 |
|
|
fprintf(fout, "\t%s", proc->args.argname); |
167 |
|
|
fprintf(fout, " arg;\n"); |
168 |
|
|
} |
169 |
|
|
fprintf(fout, "\tstatic "); |
170 |
|
|
if (streq(proc->res_type, "void")) { |
171 |
|
|
fprintf(fout, "char "); |
172 |
|
|
} else { |
173 |
|
|
ptype(proc->res_prefix, proc->res_type, 0); |
174 |
|
|
} |
175 |
|
|
fprintf(fout, "%s;\n",RESULT); |
176 |
|
|
fprintf(fout, "\n"); |
177 |
|
|
fprintf(fout, "\tmemset((char *)%s%s, 0, sizeof(%s));\n", |
178 |
|
|
ampr(proc->res_type), RESULT, RESULT); |
179 |
|
|
if (newstyle && !args2 && (streq(proc->args.decls->decl.type, "void"))) { |
180 |
|
|
/* newstyle, 0 arguments */ |
181 |
|
|
fprintf(fout, |
182 |
|
|
"\tif (clnt_call(clnt, %s, xdr_void", proc->proc_name); |
183 |
|
|
fprintf(fout, |
184 |
|
|
", NULL, xdr_%s, %s%s, TIMEOUT) != RPC_SUCCESS) {\n", |
185 |
|
|
stringfix(proc->res_type), ampr(proc->res_type), RESULT); |
186 |
|
|
} else if (newstyle && args2) { |
187 |
|
|
/* newstyle, multiple arguments: stuff arguments into structure */ |
188 |
|
|
for (l = proc->args.decls; l != NULL; l = l->next) { |
189 |
|
|
fprintf(fout, "\targ.%s = %s;\n", |
190 |
|
|
l->decl.name, l->decl.name); |
191 |
|
|
} |
192 |
|
|
fprintf(fout, |
193 |
|
|
"\tif (clnt_call(clnt, %s, xdr_%s", proc->proc_name, |
194 |
|
|
proc->args.argname); |
195 |
|
|
fprintf(fout, |
196 |
|
|
", &arg, xdr_%s, %s%s, TIMEOUT) != RPC_SUCCESS) {\n", |
197 |
|
|
stringfix(proc->res_type), |
198 |
|
|
ampr(proc->res_type), RESULT); |
199 |
|
|
} else { /* single argument, new or old style */ |
200 |
|
|
fprintf(fout, |
201 |
|
|
"\tif (clnt_call(clnt, %s, xdr_%s, %s%s, xdr_%s, " |
202 |
|
|
"%s%s, TIMEOUT) != RPC_SUCCESS) {\n", |
203 |
|
|
proc->proc_name, |
204 |
|
|
stringfix(proc->args.decls->decl.type), |
205 |
|
|
(newstyle ? "&" : ""), |
206 |
|
|
(newstyle ? proc->args.decls->decl.name : "argp"), |
207 |
|
|
stringfix(proc->res_type), |
208 |
|
|
ampr(proc->res_type),RESULT); |
209 |
|
|
} |
210 |
|
|
fprintf(fout, "\t\treturn (NULL);\n"); |
211 |
|
|
fprintf(fout, "\t}\n"); |
212 |
|
|
if (streq(proc->res_type, "void")) { |
213 |
|
|
fprintf(fout, "\treturn ((void *)%s%s);\n", |
214 |
|
|
ampr(proc->res_type),RESULT); |
215 |
|
|
} else { |
216 |
|
|
fprintf(fout, "\treturn (%s%s);\n", ampr(proc->res_type),RESULT); |
217 |
|
|
} |
218 |
|
|
} |
219 |
|
|
|