pidl:Samba4/NDR/Client: convert code to $self->pidl()
[amitay/samba.git] / pidl / lib / Parse / Pidl / Samba4 / NDR / Client.pm
1 ###################################################
2 # client calls generator
3 # Copyright tridge@samba.org 2003
4 # Copyright jelmer@samba.org 2005-2006
5 # released under the GNU GPL
6
7 package Parse::Pidl::Samba4::NDR::Client;
8
9 use Exporter;
10 @ISA = qw(Exporter);
11 @EXPORT_OK = qw(Parse);
12
13 use Parse::Pidl::Samba4 qw(choose_header is_intree);
14 use Parse::Pidl::Util qw(has_property);
15
16 use vars qw($VERSION);
17 $VERSION = '0.01';
18
19 use strict;
20
21 sub indent($) { my ($self) = @_; $self->{tabs}.="\t"; }
22 sub deindent($) { my ($self) = @_; $self->{tabs} = substr($self->{tabs}, 1); }
23 sub pidl($$) { my ($self,$txt) = @_; $self->{res} .= $txt ? "$self->{tabs}$txt\n" : "\n"; }
24 sub pidl_hdr($$) { my ($self, $txt) = @_; $self->{res_hdr} .= "$txt\n"; }
25 sub fn_declare($$) { my ($self,$n) = @_; $self->pidl($n); $self->pidl_hdr("$n;"); }
26
27 sub genpad($)
28 {
29         my ($s) = @_;
30         my $nt = int((length($s)+1)/8);
31         my $lt = ($nt*8)-1;
32         my $ns = (length($s)-$lt);
33         return "\t"x($nt)." "x($ns);
34 }
35
36 sub new($)
37 {
38         my ($class) = shift;
39         my $self = { res => "", res_hdr => "", tabs => "" };
40         bless($self, $class);
41 }
42
43 sub ParseFunction_r_State($$$$)
44 {
45         my ($self, $if, $fn, $name) = @_;
46         my $uname = uc $name;
47
48         $self->pidl("struct dcerpc_$name\_r_state {");
49         $self->indent;
50         $self->pidl("TALLOC_CTX *out_mem_ctx;");
51         $self->deindent;
52         $self->pidl("};");
53         $self->pidl("");
54         $self->pidl("static void dcerpc_$name\_r_done(struct tevent_req *subreq);");
55         $self->pidl("");
56 }
57
58 sub ParseFunction_r_Send($$$$)
59 {
60         my ($self, $if, $fn, $name) = @_;
61         my $uname = uc $name;
62
63         my $proto = "struct tevent_req *dcerpc_$name\_r_send(TALLOC_CTX *mem_ctx,\n";
64         $proto   .= "\tstruct tevent_context *ev,\n",
65         $proto   .= "\tstruct dcerpc_binding_handle *h,\n",
66         $proto   .= "\tstruct $name *r)";
67
68         $self->fn_declare($proto);
69
70         $self->pidl("{");
71         $self->indent;
72
73         $self->pidl("struct tevent_req *req;");
74         $self->pidl("struct dcerpc_$name\_r_state *state;");
75         $self->pidl("struct tevent_req *subreq;");
76         $self->pidl("");
77
78         $self->pidl("req = tevent_req_create(mem_ctx, &state,");
79         $self->pidl("\t\t\tstruct dcerpc_$name\_r_state);");
80         $self->pidl("if (req == NULL) {");
81         $self->indent;
82         $self->pidl("return NULL;");
83         $self->deindent;
84         $self->pidl("}");
85         $self->pidl("");
86
87         my $out_params = 0;
88         foreach (@{$fn->{ELEMENTS}}) {
89                 if (grep(/out/, @{$_->{DIRECTION}})) {
90                         $out_params++;
91                 }
92         }
93
94         my $submem;
95         if ($out_params > 0) {
96                 $self->pidl("state->out_mem_ctx = talloc_new(state);");
97                 $self->pidl("if (tevent_req_nomem(state->out_mem_ctx, req)) {");
98                 $self->indent;
99                 $self->pidl("return tevent_req_post(req, ev);");
100                 $self->deindent;
101                 $self->pidl("}");
102                 $self->pidl("");
103                 $submem = "state->out_mem_ctx";
104         } else {
105                 $self->pidl("state->out_mem_ctx = NULL;");
106                 $submem = "state";
107         }
108
109         $self->pidl("subreq = dcerpc_binding_handle_call_send(state, ev, h,");
110         $self->pidl("\t\tNULL, &ndr_table_$if->{NAME},");
111         $self->pidl("\t\tNDR_$uname, $submem, r);");
112         $self->pidl("if (tevent_req_nomem(subreq, req)) {");
113         $self->indent;
114         $self->pidl("return tevent_req_post(req, ev);");
115         $self->deindent;
116         $self->pidl("}");
117         $self->pidl("tevent_req_set_callback(subreq, dcerpc_$name\_r_done, req);");
118         $self->pidl("");
119
120         $self->pidl("return req;");
121         $self->deindent;
122         $self->pidl("}");
123         $self->pidl("");
124 }
125
126 sub ParseFunction_r_Done($$$$)
127 {
128         my ($self, $if, $fn, $name) = @_;
129         my $uname = uc $name;
130
131         my $proto = "static void dcerpc_$name\_r_done(struct tevent_req *subreq)";
132
133         $self->pidl("$proto");
134         $self->pidl("{");
135         $self->indent;
136
137         $self->pidl("struct tevent_req *req =");
138         $self->pidl("\ttevent_req_callback_data(subreq,");
139         $self->pidl("\tstruct tevent_req);");
140         $self->pidl("NTSTATUS status;");
141         $self->pidl("");
142
143         $self->pidl("status = dcerpc_binding_handle_call_recv(subreq);");
144         $self->pidl("if (!NT_STATUS_IS_OK(status)) {");
145         $self->indent;
146         $self->pidl("tevent_req_nterror(req, status);");
147         $self->pidl("return;");
148         $self->deindent;
149         $self->pidl("}");
150         $self->pidl("");
151
152         $self->pidl("tevent_req_done(req);");
153         $self->deindent;
154         $self->pidl("}");
155         $self->pidl("");
156 }
157
158 sub ParseFunction_r_Recv($$$$)
159 {
160         my ($if, $fn, $name) = @_;
161         my ($self, $if, $fn, $name) = @_;
162         my $uname = uc $name;
163
164         my $proto = "NTSTATUS dcerpc_$name\_r_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx)";
165
166         $self->fn_declare($proto);
167
168         $self->pidl("{");
169         $self->indent;
170
171         $self->pidl("struct dcerpc_$name\_r_state *state =");
172         $self->pidl("\ttevent_req_data(req,");
173         $self->pidl("\tstruct dcerpc_$name\_r_state);");
174         $self->pidl("NTSTATUS status;");
175         $self->pidl("");
176
177         $self->pidl("if (tevent_req_is_nterror(req, &status)) {");
178         $self->indent;
179         $self->pidl("tevent_req_received(req);");
180         $self->pidl("return status;");
181         $self->deindent;
182         $self->pidl("}");
183         $self->pidl("");
184
185         $self->pidl("talloc_steal(mem_ctx, state->out_mem_ctx);");
186         $self->pidl("");
187
188         $self->pidl("tevent_req_received(req);");
189         $self->pidl("return NT_STATUS_OK;");
190         $self->deindent;
191         $self->pidl("}");
192         $self->pidl("");
193 }
194
195 sub ParseFunction_r_Sync($$$$)
196 {
197         my ($if, $fn, $name) = @_;
198         my ($self, $if, $fn, $name) = @_;
199         my $uname = uc $name;
200
201         my $proto = "NTSTATUS dcerpc_$name\_r(struct dcerpc_binding_handle *h, TALLOC_CTX *mem_ctx, struct $name *r)";
202
203         $self->fn_declare($proto);
204
205         $self->pidl("{");
206         $self->indent;
207         $self->pidl("NTSTATUS status;");
208         $self->pidl("");
209
210         $self->pidl("status = dcerpc_binding_handle_call(h,");
211         $self->pidl("\t\tNULL, &ndr_table_$if->{NAME},");
212         $self->pidl("\t\tNDR_$uname, mem_ctx, r);");
213         $self->pidl("");
214         $self->pidl("return status;");
215
216         $self->deindent;
217         $self->pidl("}");
218         $self->pidl("");
219 }
220
221 #####################################################################
222 # parse a function
223 sub ParseFunction($$$)
224 {
225         my ($self, $if, $fn) = @_;
226
227         $self->ParseFunction_r_State($if, $fn, $fn->{NAME});
228         $self->ParseFunction_r_Send($if, $fn, $fn->{NAME});
229         $self->ParseFunction_r_Done($if, $fn, $fn->{NAME});
230         $self->ParseFunction_r_Recv($if, $fn, $fn->{NAME});
231         $self->ParseFunction_r_Sync($if, $fn, $fn->{NAME});
232
233         $self->pidl_hdr("");
234 }
235
236 my %done;
237
238 #####################################################################
239 # parse the interface definitions
240 sub ParseInterface($$)
241 {
242         my ($self, $if) = @_;
243
244         $self->pidl_hdr("#ifndef _HEADER_RPC_$if->{NAME}");
245         $self->pidl_hdr("#define _HEADER_RPC_$if->{NAME}");
246         $self->pidl_hdr("");
247
248         if (defined $if->{PROPERTIES}->{uuid}) {
249                 $self->pidl_hdr("extern const struct ndr_interface_table ndr_table_$if->{NAME};");
250                 $self->pidl_hdr("");
251         }
252
253         $self->pidl("/* $if->{NAME} - client functions generated by pidl */");
254         $self->pidl("");
255
256         foreach my $fn (@{$if->{FUNCTIONS}}) {
257                 next if defined($done{$fn->{NAME}});
258                 next if has_property($fn, "noopnum");
259                 next if has_property($fn, "todo");
260                 $self->ParseFunction($if, $fn);
261                 $done{$fn->{NAME}} = 1;
262         }
263
264         $self->pidl_hdr("#endif /* _HEADER_RPC_$if->{NAME} */");
265 }
266
267 sub Parse($$$$$$)
268 {
269         my($self,$ndr,$header,$ndr_header,$client_header) = @_;
270
271         $self->pidl("/* client functions auto-generated by pidl */");
272         $self->pidl("");
273         if (is_intree()) {
274                 $self->pidl("#include \"includes.h\"");
275         } else {
276                 $self->pidl("#ifndef _GNU_SOURCE");
277                 $self->pidl("#define _GNU_SOURCE");
278                 $self->pidl("#endif");
279                 $self->pidl("#include <stdio.h>");
280                 $self->pidl("#include <stdbool.h>");
281                 $self->pidl("#include <stdlib.h>");
282                 $self->pidl("#include <stdint.h>");
283                 $self->pidl("#include <stdarg.h>");
284                 $self->pidl("#include <core/ntstatus.h>");
285         }
286         $self->pidl("#include <tevent.h>");
287         $self->pidl(choose_header("lib/util/tevent_ntstatus.h", "util/tevent_ntstatus.h")."");
288         $self->pidl("#include \"$ndr_header\"");
289         $self->pidl("#include \"$client_header\"");
290         $self->pidl("");
291
292         $self->pidl_hdr(choose_header("librpc/rpc/dcerpc.h", "dcerpc.h")."");
293         $self->pidl_hdr("#include \"$header\"");
294
295         foreach my $x (@{$ndr}) {
296                 ($x->{TYPE} eq "INTERFACE") && $self->ParseInterface($x);
297         }
298
299         return ($self->{res},$self->{res_hdr});
300 }
301
302 1;