rpc_clntout.c 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333
  1. /*
  2. * rpc_clntout.c, Client-stub outputter for the RPC protocol compiler
  3. * Copyright (c) 2010, Oracle America, Inc.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions are
  7. * met:
  8. *
  9. * * Redistributions of source code must retain the above copyright
  10. * notice, this list of conditions and the following disclaimer.
  11. * * Redistributions in binary form must reproduce the above
  12. * copyright notice, this list of conditions and the following
  13. * disclaimer in the documentation and/or other materials
  14. * provided with the distribution.
  15. * * Neither the name of the "Oracle America, Inc." nor the names of its
  16. * contributors may be used to endorse or promote products derived
  17. * from this software without specific prior written permission.
  18. *
  19. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  20. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  21. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  22. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  23. * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
  24. * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  25. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
  26. * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  27. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  28. * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  29. * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  30. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  31. */
  32. #include <stdio.h>
  33. #include <string.h>
  34. #include "rpc/types.h"
  35. #include "rpc_parse.h"
  36. #include "rpc_util.h"
  37. #include "proto.h"
  38. #define DEFAULT_TIMEOUT 25 /* in seconds */
  39. static const char RESULT[] = "clnt_res";
  40. static void write_program (definition * def);
  41. static void printbody (proc_list * proc);
  42. static const char *ampr (const char *type);
  43. static void printbody (proc_list * proc);
  44. void
  45. write_stubs (void)
  46. {
  47. list *l;
  48. definition *def;
  49. fprintf (fout,
  50. "\n/* Default timeout can be changed using clnt_control() */\n");
  51. fprintf (fout, "static struct timeval TIMEOUT = { %d, 0 };\n",
  52. DEFAULT_TIMEOUT);
  53. for (l = defined; l != NULL; l = l->next)
  54. {
  55. def = (definition *) l->val;
  56. if (def->def_kind == DEF_PROGRAM)
  57. {
  58. write_program (def);
  59. }
  60. }
  61. }
  62. static void
  63. write_program (definition * def)
  64. {
  65. version_list *vp;
  66. proc_list *proc;
  67. for (vp = def->def.pr.versions; vp != NULL; vp = vp->next)
  68. {
  69. for (proc = vp->procs; proc != NULL; proc = proc->next)
  70. {
  71. fprintf (fout, "\n");
  72. if (mtflag == 0)
  73. {
  74. ptype (proc->res_prefix, proc->res_type, 1);
  75. fprintf (fout, "*\n");
  76. pvname (proc->proc_name, vp->vers_num);
  77. printarglist (proc, RESULT, "clnt", "CLIENT *");
  78. }
  79. else
  80. {
  81. fprintf (fout, "enum clnt_stat \n");
  82. pvname (proc->proc_name, vp->vers_num);
  83. printarglist (proc, RESULT, "clnt", "CLIENT *");
  84. }
  85. fprintf (fout, "{\n");
  86. printbody (proc);
  87. fprintf (fout, "}\n");
  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. /* sample addargname = "clnt"; sample addargtype = "CLIENT * " */
  96. void
  97. printarglist (proc_list * proc, const char *result,
  98. const char *addargname, const char *addargtype)
  99. {
  100. decl_list *l;
  101. if (!newstyle)
  102. { /* old style: always pass argument by reference */
  103. if (Cflag)
  104. { /* C++ style heading */
  105. fprintf (fout, "(");
  106. ptype (proc->args.decls->decl.prefix,
  107. proc->args.decls->decl.type, 1);
  108. if (mtflag)
  109. {/* Generate result field */
  110. fprintf (fout, "*argp, ");
  111. ptype(proc->res_prefix, proc->res_type, 1);
  112. fprintf (fout, "*%s, %s%s)\n", result, addargtype, addargname);
  113. }
  114. else
  115. fprintf (fout, "*argp, %s%s)\n", addargtype, addargname);
  116. }
  117. else
  118. {
  119. if (!mtflag)
  120. fprintf (fout, "(argp, %s)\n", addargname);
  121. else
  122. fprintf (fout, "(argp, %s, %s)\n", result, addargname);
  123. fprintf (fout, "\t");
  124. ptype (proc->args.decls->decl.prefix,
  125. proc->args.decls->decl.type, 1);
  126. fprintf (fout, "*argp;\n");
  127. if (mtflag)
  128. {
  129. fprintf (fout, "\t");
  130. ptype (proc->res_prefix, proc->res_type, 1);
  131. fprintf (fout, "*%s;\n", result);
  132. }
  133. }
  134. }
  135. else if (streq (proc->args.decls->decl.type, "void"))
  136. {
  137. /* newstyle, 0 argument */
  138. if (mtflag)
  139. {
  140. fprintf (fout, "(");
  141. if (Cflag)
  142. {
  143. ptype(proc->res_prefix, proc->res_type, 1);
  144. fprintf (fout, "*%s, %s%s)\n", result, addargtype, addargname);
  145. }
  146. else
  147. fprintf (fout, "(%s)\n", addargname);
  148. }
  149. else if (Cflag)
  150. fprintf (fout, "(%s%s)\n", addargtype, addargname);
  151. else
  152. fprintf (fout, "(%s)\n", addargname);
  153. }
  154. else
  155. {
  156. /* new style, 1 or multiple arguments */
  157. if (!Cflag)
  158. {
  159. fprintf (fout, "(");
  160. for (l = proc->args.decls; l != NULL; l = l->next)
  161. fprintf (fout, "%s, ", l->decl.name);
  162. if (mtflag)
  163. fprintf (fout, "%s, ", result);
  164. fprintf (fout, "%s)\n", addargname);
  165. for (l = proc->args.decls; l != NULL; l = l->next)
  166. {
  167. pdeclaration (proc->args.argname, &l->decl, 1, ";\n");
  168. }
  169. if (mtflag)
  170. {
  171. fprintf (fout, "\t");
  172. ptype (proc->res_prefix, proc->res_type, 1);
  173. fprintf (fout, "*%s;\n", result);
  174. }
  175. }
  176. else
  177. { /* C++ style header */
  178. fprintf (fout, "(");
  179. for (l = proc->args.decls; l != NULL; l = l->next)
  180. {
  181. pdeclaration (proc->args.argname, &l->decl, 0, ", ");
  182. }
  183. if (mtflag)
  184. {
  185. ptype (proc->res_prefix, proc->res_type, 1);
  186. fprintf (fout, "*%s, ", result);
  187. }
  188. fprintf (fout, " %s%s)\n", addargtype, addargname);
  189. }
  190. }
  191. if (!Cflag)
  192. fprintf (fout, "\t%s%s;\n", addargtype, addargname);
  193. }
  194. static
  195. const char *
  196. ampr (const char *type)
  197. {
  198. if (isvectordef (type, REL_ALIAS))
  199. {
  200. return "";
  201. }
  202. else
  203. {
  204. return "&";
  205. }
  206. }
  207. static void
  208. printbody (proc_list * proc)
  209. {
  210. decl_list *l;
  211. bool_t args2 = (proc->arg_num > 1);
  212. /* int i; */
  213. /* For new style with multiple arguments, need a structure in which
  214. to stuff the arguments. */
  215. if (newstyle && args2)
  216. {
  217. fprintf (fout, "\t%s", proc->args.argname);
  218. fprintf (fout, " arg;\n");
  219. }
  220. if (!mtflag)
  221. {
  222. fprintf (fout, "\tstatic ");
  223. if (streq (proc->res_type, "void"))
  224. {
  225. fprintf (fout, "char ");
  226. }
  227. else
  228. {
  229. ptype (proc->res_prefix, proc->res_type, 0);
  230. }
  231. fprintf (fout, "%s;\n", RESULT);
  232. fprintf (fout, "\n");
  233. fprintf (fout, "\tmemset((char *)%s%s, 0, sizeof(%s));\n",
  234. ampr (proc->res_type), RESULT, RESULT);
  235. }
  236. if (newstyle && !args2 && (streq (proc->args.decls->decl.type, "void")))
  237. {
  238. /* newstyle, 0 arguments */
  239. if (mtflag)
  240. fprintf (fout, "\t return ");
  241. else
  242. fprintf (fout, "\t if ");
  243. fprintf (fout,
  244. "(clnt_call (clnt, %s, (xdrproc_t) xdr_void, ", proc->proc_name);
  245. fprintf (fout,
  246. "(caddr_t) NULL,\n\t\t(xdrproc_t) xdr_%s, (caddr_t) %s%s,",
  247. stringfix(proc->res_type), (mtflag)?"":ampr(proc->res_type),
  248. RESULT);
  249. if (mtflag)
  250. fprintf (fout, "\n\t\tTIMEOUT));\n\n");
  251. else
  252. fprintf (fout, "\n\t\tTIMEOUT) != RPC_SUCCESS) {\n");
  253. }
  254. else if (newstyle && args2)
  255. {
  256. /* newstyle, multiple arguments: stuff arguments into structure */
  257. for (l = proc->args.decls; l != NULL; l = l->next)
  258. {
  259. fprintf (fout, "\targ.%s = %s;\n",
  260. l->decl.name, l->decl.name);
  261. }
  262. if (mtflag)
  263. fprintf (fout, "\treturn ");
  264. else
  265. fprintf (fout, "\tif ");
  266. fprintf (fout,
  267. "(clnt_call (clnt, %s, (xdrproc_t) xdr_%s", proc->proc_name,
  268. proc->args.argname);
  269. fprintf (fout,
  270. ", (caddr_t) &arg,\n\t\t(xdrproc_t) xdr_%s, (caddr_t) %s%s,",
  271. stringfix(proc->res_type), (mtflag)?"":ampr(proc->res_type),
  272. RESULT);
  273. if (mtflag)
  274. fprintf (fout, "\n\t\tTIMEOUT));\n");
  275. else
  276. fprintf (fout, "\n\t\tTIMEOUT) != RPC_SUCCESS) {\n");
  277. }
  278. else
  279. { /* single argument, new or old style */
  280. if (!mtflag)
  281. fprintf (fout,
  282. "\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",
  283. proc->proc_name,
  284. stringfix (proc->args.decls->decl.type),
  285. (newstyle ? "&" : ""),
  286. (newstyle ? proc->args.decls->decl.name : "argp"),
  287. stringfix (proc->res_type), ampr (proc->res_type),
  288. RESULT);
  289. else
  290. fprintf(fout,
  291. "\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",
  292. proc->proc_name,
  293. stringfix (proc->args.decls->decl.type),
  294. (newstyle ? "&" : ""),
  295. (newstyle ? proc->args.decls->decl.name : "argp"),
  296. stringfix (proc->res_type), "",
  297. RESULT);
  298. }
  299. if (!mtflag)
  300. {
  301. fprintf (fout, "\t\treturn (NULL);\n");
  302. fprintf (fout, "\t}\n");
  303. if (streq (proc->res_type, "void"))
  304. {
  305. fprintf (fout, "\treturn ((void *)%s%s);\n",
  306. ampr (proc->res_type), RESULT);
  307. }
  308. else
  309. {
  310. fprintf (fout, "\treturn (%s%s);\n", ampr (proc->res_type), RESULT);
  311. }
  312. }
  313. }