r24522: make the "skip pointer to an array" logic a bit easier
[ira/wip.git] / source / pidl / lib / Parse / Pidl / Samba3 / ServerNDR.pm
1 ###################################################
2 # Samba3 server generator for IDL structures
3 # on top of Samba4 style NDR functions
4 # Copyright jelmer@samba.org 2005-2006
5 # released under the GNU GPL
6
7 package Parse::Pidl::Samba3::ServerNDR;
8
9 use strict;
10 use Parse::Pidl qw(warning fatal);
11 use Parse::Pidl::Typelist qw(mapTypeName scalar_is_reference);
12 use Parse::Pidl::Util qw(ParseExpr has_property is_constant);
13 use Parse::Pidl::NDR qw(GetNextLevel);
14 use Parse::Pidl::Samba4 qw(DeclLong);
15 use Parse::Pidl::Samba4::NDR::Parser qw(GenerateFunctionOutEnv);
16
17 use vars qw($VERSION);
18 $VERSION = '0.01';
19
20 my $res;
21 my $res_hdr;
22 my $tabs = "";
23 sub indent() { $tabs.="\t"; }
24 sub deindent() { $tabs = substr($tabs, 1); }
25 sub pidl($) { $res .= $tabs.(shift)."\n"; }
26 sub pidl_hdr($) { $res_hdr .= (shift)."\n"; }
27 sub fn_declare($) { my ($n) = @_; pidl $n; pidl_hdr "$n;"; }
28
29 sub DeclLevel($$) 
30 {
31         sub DeclLevel($$);
32         my ($e, $l) = @_;
33
34         my $ret = "";
35
36         if (has_property($e, "charset")) {
37                 $ret.="const char";
38         } else {
39                 $ret.=mapTypeName($e->{TYPE});
40         }
41
42         my $numstar = $e->{ORIGINAL}->{POINTERS};
43         if ($numstar >= 1) {
44                 $numstar-- if scalar_is_reference($e->{TYPE});
45         }
46         foreach (@{$e->{ORIGINAL}->{ARRAY_LEN}})
47         {
48                 next if is_constant($_) and 
49                         not has_property($e, "charset");
50                 $numstar++;
51         }
52         $numstar -= $l;
53         die ("Too few pointers") if $numstar < 0;
54         if ($numstar > 0) 
55         {
56                 $ret.=" ";
57                 $ret.="*" foreach (1..$numstar);
58         }
59
60         return $ret;
61 }
62
63 sub AllocOutVar($$$$)
64 {
65         my ($e, $mem_ctx, $name, $env) = @_;
66
67         my $l = $e->{LEVELS}[0];
68
69         # we skip pointer to arrays
70         if ($l->{TYPE} eq "POINTER") {
71                 my $nl = GetNextLevel($e, $l);
72                 $l = $nl if ($nl->{TYPE} eq "ARRAY");
73         }
74
75         if ($l->{TYPE} eq "ARRAY") {
76                 my $size = ParseExpr($l->{SIZE_IS}, $env, $e);
77                 pidl "$name = talloc_zero_array($mem_ctx, " . DeclLevel($e, 1) . ", $size);";
78         } else {
79                 pidl "$name = talloc_zero($mem_ctx, " . DeclLevel($e, 1) . ");";
80         }
81
82         pidl "if ($name == NULL) {";
83         pidl "\ttalloc_free(mem_ctx);";
84         pidl "\treturn False;";
85         pidl "}";
86         pidl "";
87 }
88
89 sub ParseFunction($$)
90 {
91         my ($if,$fn) = @_;
92
93         pidl "static BOOL api_$fn->{NAME}(pipes_struct *p)";
94         pidl "{";
95         indent;
96         pidl "struct ndr_pull *pull;";
97         pidl "struct ndr_push *push;";
98         pidl "NTSTATUS status;";
99         pidl "DATA_BLOB blob;";
100         pidl "struct $fn->{NAME} r;";
101         pidl "TALLOC_CTX *mem_ctx = talloc_init(\"api_$fn->{NAME}\");";
102         pidl "";
103         pidl "if (!prs_data_blob(&p->in_data.data, &blob, mem_ctx)) {";
104         pidl "\ttalloc_free(mem_ctx);";
105         pidl "\treturn False;";
106         pidl "}";
107         pidl "";
108         pidl "pull = ndr_pull_init_blob(&blob, mem_ctx);";
109         pidl "if (pull == NULL) {";
110         pidl "\ttalloc_free(mem_ctx);";
111         pidl "\treturn False;";
112         pidl "}";
113         pidl "";
114         pidl "pull->flags |= LIBNDR_FLAG_REF_ALLOC;";
115         pidl "status = ndr_pull_$fn->{NAME}(pull, NDR_IN, &r);";
116         pidl "if (NT_STATUS_IS_ERR(status)) {";
117         pidl "\ttalloc_free(mem_ctx);";
118         pidl "\treturn False;";
119         pidl "}";
120         pidl "";
121         pidl "if (DEBUGLEVEL >= 10)";
122         pidl "\tNDR_PRINT_IN_DEBUG($fn->{NAME}, &r);";
123         pidl "";
124
125         my $env = GenerateFunctionOutEnv($fn, "r.");
126         my $hasout = 0;
127         foreach (@{$fn->{ELEMENTS}}) {
128                 if (grep(/out/, @{$_->{DIRECTION}})) { $hasout = 1; }
129         }
130
131         pidl "ZERO_STRUCT(r.out);" if ($hasout);
132
133         my $proto = "_$fn->{NAME}(pipes_struct *p, struct $fn->{NAME} *r";
134         my $ret = "_$fn->{NAME}(p, &r";
135         foreach (@{$fn->{ELEMENTS}}) {
136                 my @dir = @{$_->{DIRECTION}};
137                 if (grep(/in/, @dir) and grep(/out/, @dir)) {
138                         pidl "r.out.$_->{NAME} = r.in.$_->{NAME};";
139                 } elsif (grep(/out/, @dir) and not 
140                                  has_property($_, "represent_as")) {
141                         AllocOutVar($_, "mem_ctx", "r.out.$_->{NAME}", $env);
142                 }
143         }
144         $ret .= ")";
145         $proto .= ");";
146
147         if ($fn->{RETURN_TYPE}) {
148                 $ret = "r.out.result = $ret";
149                 $proto = "$fn->{RETURN_TYPE} $proto";
150         } else {
151                 $proto = "void $proto";
152         }
153
154         pidl_hdr "$proto";
155         pidl "$ret;";
156
157         pidl "";
158         pidl "if (p->rng_fault_state) {";
159         pidl "\ttalloc_free(mem_ctx);";
160         pidl "\t/* Return True here, srv_pipe_hnd.c will take care */";
161         pidl "\treturn True;";
162         pidl "}";
163         pidl "";
164         pidl "if (DEBUGLEVEL >= 10)";
165         pidl "\tNDR_PRINT_OUT_DEBUG($fn->{NAME}, &r);";
166         pidl "";
167         pidl "push = ndr_push_init_ctx(mem_ctx);";
168         pidl "if (push == NULL) {";
169         pidl "\ttalloc_free(mem_ctx);";
170         pidl "\treturn False;";
171         pidl "}";
172         pidl "";
173         pidl "status = ndr_push_$fn->{NAME}(push, NDR_OUT, &r);";
174         pidl "if (NT_STATUS_IS_ERR(status)) {";
175         pidl "\ttalloc_free(mem_ctx);";
176         pidl "\treturn False;";
177         pidl "}";
178         pidl "";
179         pidl "blob = ndr_push_blob(push);";
180         pidl "if (!prs_copy_data_in(&p->out_data.rdata, (const char *)blob.data, (uint32)blob.length)) {";
181         pidl "\ttalloc_free(mem_ctx);";
182         pidl "\treturn False;";
183         pidl "}";
184         pidl "";
185         pidl "talloc_free(mem_ctx);";
186         pidl "";
187         pidl "return True;";
188         deindent;
189         pidl "}";
190         pidl "";
191 }
192
193 sub ParseInterface($)
194 {
195         my $if = shift;
196
197         my $uif = uc($if->{NAME});
198
199         pidl_hdr "#ifndef __SRV_$uif\__";
200         pidl_hdr "#define __SRV_$uif\__";
201         ParseFunction($if, $_) foreach (@{$if->{FUNCTIONS}});
202
203         pidl "";
204         pidl "/* Tables */";
205         pidl "static struct api_struct api_$if->{NAME}_cmds[] = ";
206         pidl "{";
207         indent;
208
209         foreach (@{$if->{FUNCTIONS}}) {
210                 pidl "{\"" . uc($_->{NAME}) . "\", DCERPC_" . uc($_->{NAME}) . ", api_$_->{NAME}},";
211         }
212
213         deindent;
214         pidl "};";
215
216         pidl "";
217
218         pidl_hdr "void $if->{NAME}_get_pipe_fns(struct api_struct **fns, int *n_fns);";
219         pidl "void $if->{NAME}_get_pipe_fns(struct api_struct **fns, int *n_fns)";
220         pidl "{";
221         indent;
222         pidl "*fns = api_$if->{NAME}_cmds;";
223         pidl "*n_fns = sizeof(api_$if->{NAME}_cmds) / sizeof(struct api_struct);";
224         deindent;
225         pidl "}";
226         pidl "";
227
228         pidl_hdr "NTSTATUS rpc_$if->{NAME}_init(void);";
229         pidl "NTSTATUS rpc_$if->{NAME}_init(void)";
230         pidl "{";
231         pidl "\treturn rpc_pipe_register_commands(SMB_RPC_INTERFACE_VERSION, \"$if->{NAME}\", \"$if->{NAME}\", api_$if->{NAME}_cmds, sizeof(api_$if->{NAME}_cmds) / sizeof(struct api_struct));";
232         pidl "}";
233
234         pidl_hdr "#endif /* __SRV_$uif\__ */";
235 }
236
237 sub Parse($$$)
238 {
239         my($ndr,$header,$ndr_header) = @_;
240
241         $res = "";
242         $res_hdr = "";
243
244         pidl "/*";
245         pidl " * Unix SMB/CIFS implementation.";
246         pidl " * server auto-generated by pidl. DO NOT MODIFY!";
247         pidl " */";
248         pidl "";
249         pidl "#include \"includes.h\"";
250         pidl "#include \"$header\"";
251         pidl_hdr "#include \"$ndr_header\"";
252         pidl "";
253         
254         foreach (@$ndr) {
255                 ParseInterface($_) if ($_->{TYPE} eq "INTERFACE");
256         }
257
258         return ($res, $res_hdr);
259 }
260
261 1;