Remote and RPC.
[wrappi.git] / generator / wrappi_c_xdr.ml
1 (* wrappi
2  * Copyright (C) 2011 Red Hat Inc.
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17  *)
18
19 open Camlp4.PreCast
20
21 open Wrappi_utils
22 open Wrappi_types
23 open Wrappi_boilerplate
24 open Wrappi_pr
25
26 open Printf
27
28 let inputs = ["wrappi_c_xdr.ml"]
29
30 (* Traditionally 'rpcgen' is used to generate this code.  However the
31  * glibc maintainers have shown no interest (in fact, malign influence)
32  * in doing a proper job maintaining this, resulting in bitrot and poor
33  * code being generated.  In any case the code that rpcgen makes is
34  * relatively simple.
35  *)
36
37 let pr_xdr_of_ptype n = function
38   | TBool ->
39     pr "  if (!xdr_bool (xdrs, &%s)) return FALSE;\n" n
40   | TBuffer -> assert false (* XXX not implemented *)
41   | TEnum _ ->
42     pr "  if (!xdr_int (xdrs, &%s)) return FALSE;\n" n
43   | TFile -> assert false (* XXX not implemented *)
44   | THash t -> assert false (* XXX not implemented *)
45   | TInt -> (* XXX not int, correct type depends on preconditions *)
46     pr "  if (!xdr_int (xdrs, &%s)) return FALSE;\n" n
47   | TInt32 ->
48     pr "  if (!xdr_int32_t (xdrs, &%s)) return FALSE;\n" n
49   | TInt64 ->
50     pr "  if (!xdr_int64_t (xdrs, &%s)) return FALSE;\n" n
51   | TList t -> assert false (* XXX not implemented *)
52   | TNullable TString ->
53     pr "  if (!xdr_pointer (xdrs, &%s, sizeof (unlimited_string), (xdrproc_t) xdr_unlimited_string)) return FALSE;\n" n
54   | TNullable _ -> assert false (* XXX may be implemented in future *)
55   | TString ->
56     pr "  if (!xdr_unlimited_string (xdrs, (void *) &%s)) return FALSE;\n" n
57   | TStruct sname ->
58     pr "  if (!xdr_struct_%s (xdrs, %s)) return FALSE;\n" sname n
59   | TTypedef name -> assert false (* should never happen *)
60   | TUInt32 ->
61     pr "  if (!xdr_uint32_t (xdrs, &%s)) return FALSE;\n" n
62   | TUInt64 ->
63     pr "  if (!xdr_uint64_t (xdrs, &%s)) return FALSE;\n" n
64   | TUnion uname ->
65     pr "  if (!xdr_union_%s (xdrs, %s)) return FALSE;\n" uname n
66
67 let generate_lib_proto_xdr_impl_c api =
68   generate_header inputs CStyle LGPLv2plus;
69
70   pr "\
71 #include <stdlib.h>
72 #include <rpc/xdr.h>
73
74 #include \"wrappi.h\"
75 #include \"internal.h\"
76
77 /* An unlimited length string. */
78 typedef char *unlimited_string;
79
80 static bool_t
81 xdr_unlimited_string (XDR *xdrs, unlimited_string *objp)
82 {
83   if (!xdr_string (xdrs, objp, ~0)) return FALSE;
84   return TRUE;
85 }
86 ";
87
88   iter_structs api (
89     fun sd ->
90       let name = sd.sd_name in
91
92       pr "\n";
93       pr "static bool_t\n";
94       pr "xdr_struct_%s (XDR *xdrs, struct wrap_%s *objp)\n" name name;
95       pr "{\n";
96
97       Array.iter (
98         fun (n, t) ->
99           pr_xdr_of_ptype (sprintf "objp->%s" n) t
100       ) sd.sd_fields;
101
102       pr "  return TRUE;\n";
103       pr "}\n";
104   );
105
106   iter_entry_points api (
107     fun ep ->
108       if not ep.ep_local then (
109         let name = ep.ep_name in
110         let ret, req, opt = ep.ep_ftype in
111
112         pr "\n";
113         pr "bool_t\n";
114         pr "wrap_int_xdr_%s_args (XDR *xdrs, struct wrap_int_%s_args *args)\n"
115           name name;
116         pr "{\n";
117
118         List.iter (
119           fun (n, t, _) ->
120             pr_xdr_of_ptype (sprintf "args->%s" n) t
121         ) req;
122
123         if opt <> [] then assert false; (* XXX not implemented *)
124
125         pr "  return TRUE;\n";
126         pr "}\n";
127
128         pr "\n";
129         pr "bool_t\n";
130         pr "wrap_int_xdr_%s_ret (XDR *xdrs, struct wrap_int_%s_ret *ret)\n"
131           name name;
132         pr "{\n";
133
134         (match ret with
135         | RVoid -> ()
136         | RStaticString ->
137           assert false (* RStaticString cannot be used for remote functions. *)
138         | Return t ->
139           pr_xdr_of_ptype "ret->r" t
140         );
141
142         pr "  return TRUE;\n";
143         pr "}\n"
144       )
145   )
146
147 let generate api =
148   output_to "lib/proto-xdr-impl.c" generate_lib_proto_xdr_impl_c api