1 ###################################################
2 # Ethereal parser generator for IDL structures
3 # Copyright tpot@samba.org 2001
4 # Copyright tridge@samba.org 2000
5 # released under the GNU GPL
13 #####################################################################
14 # parse a properties list
15 sub ParseProperties($)
18 foreach my $d (@{$props}) {
19 if (ref($d) ne "HASH") {
22 foreach my $k (keys %{$d}) {
23 $res .= "[$k($d->{$k})] ";
29 #####################################################################
30 # parse an array - push side
34 my $size = util::has_property($e->{PROPERTIES}, "size_is");
35 if (util::is_scalar_type($e->{TYPE})) {
36 $res .= "\t\tNDR_CHECK(ndr_push_array_$e->{TYPE}(ndr, r->$e->{NAME}, r->$size));\n:";
38 $res .= "\t\tNDR_CHECK(ndr_push_array(ndr, ndr_flags, r->$e->{NAME}, sizeof(r->$e->{NAME}\[0]), r->$size, (ndr_push_flags_fn_t)ndr_push_$e->{TYPE}));\n";
42 #####################################################################
43 # parse an array - pull side
47 my $size = util::has_property($e->{PROPERTIES}, "size_is");
48 if (util::is_scalar_type($e->{TYPE})) {
49 $res .= "\t\tNDR_CHECK(ndr_pull_array_$e->{TYPE}(ndr, &r->$e->{NAME}, r->$size));\n:";
51 $res .= "\t\tNDR_CHECK(ndr_pull_array(ndr, ndr_flags, (void **)&r->$e->{NAME}, sizeof(r->$e->{NAME}\[0]), r->$size, (ndr_pull_flags_fn_t)ndr_pull_$e->{TYPE}));\n";
56 #####################################################################
57 # parse scalars in a structure element
58 sub ParseElementPushScalar($$$)
61 my($var_prefix) = shift;
62 my($ndr_flags) = shift;
64 if (defined $e->{VALUE}) {
65 $res .= "\tNDR_CHECK(ndr_push_$e->{TYPE}(ndr, $e->{VALUE}));\n";
66 } elsif ($e->{POINTERS} &&
67 !util::has_property($e->{PROPERTIES}, "ref")) {
68 $res .= "\tNDR_CHECK(ndr_push_ptr(ndr, $var_prefix$e->{NAME}));\n";
69 } elsif (util::is_builtin_type($e->{TYPE})) {
70 $res .= "\tNDR_CHECK(ndr_push_$e->{TYPE}(ndr, $var_prefix$e->{NAME}));\n";
72 $res .= "\tNDR_CHECK(ndr_push_$e->{TYPE}(ndr, $ndr_flags, $var_prefix$e->{NAME}));\n";
76 #####################################################################
77 # parse scalars in a structure element - pull size
78 sub ParseElementPullScalar($$)
81 my($var_prefix) = shift;
83 if (defined $e->{VALUE}) {
84 $res .= "\tNDR_CHECK(ndr_pull_$e->{TYPE}(ndr, $e->{VALUE}));\n";
85 } elsif ($e->{POINTERS} &&
86 !util::has_property($e->{PROPERTIES}, "ref")) {
87 $res .= "\tNDR_CHECK(ndr_pull_uint32(ndr, &_ptr_$e->{NAME}));\n";
88 $res .= "\tif (_ptr_$e->{NAME}) {\n";
89 $res .= "\t\tNDR_ALLOC(ndr, $var_prefix$e->{NAME});\n";
90 $res .= "\t} else {\n";
91 $res .= "\t\t$var_prefix$e->{NAME} = NULL;\n";
94 $res .= "\tNDR_CHECK(ndr_pull_$e->{TYPE}(ndr, &$var_prefix$e->{NAME}));\n";
98 #####################################################################
99 # parse buffers in a structure element
100 sub ParseElementPushBuffer($$)
103 my($var_prefix) = shift;
105 if (util::has_property($e->{PROPERTIES}, "ref")) {
109 if (util::is_scalar_type($e->{TYPE}) && !$e->{POINTERS}) {
113 if ($e->{POINTERS}) {
114 $res .= "\tif ($var_prefix$e->{NAME}) {\n";
117 if (util::has_property($e->{PROPERTIES}, "size_is")) {
120 if (util::is_scalar_type($e->{TYPE})) {
121 $res .= "\t\tNDR_CHECK(ndr_push_$e->{TYPE}(ndr, *$var_prefix$e->{NAME}));\n";
122 } elsif (util::has_property($e->{PROPERTIES}, "ref") || !$e->{POINTERS}) {
123 $res .= "\t\tNDR_CHECK(ndr_push_$e->{TYPE}(ndr, ndr_flags, *$var_prefix$e->{NAME}));\n";
124 } elsif (util::is_builtin_type($e->{TYPE})) {
125 $res .= "\t\tNDR_CHECK(ndr_push_$e->{TYPE}(ndr, $var_prefix$e->{NAME}));\n";
127 $res .= "\t\tNDR_CHECK(ndr_push_$e->{TYPE}(ndr, ndr_flags, $var_prefix$e->{NAME}));\n";
131 if ($e->{POINTERS}) {
137 #####################################################################
138 # parse buffers in a structure element - pull side
139 sub ParseElementPullBuffer($$)
142 my($var_prefix) = shift;
144 if (util::has_property($e->{PROPERTIES}, "ref")) {
148 if (util::is_scalar_type($e->{TYPE}) && !$e->{POINTERS}) {
152 if ($e->{POINTERS}) {
153 $res .= "\tif ($var_prefix$e->{NAME}) {\n";
156 if (util::has_property($e->{PROPERTIES}, "size_is")) {
159 if (util::has_property($e->{PROPERTIES}, "ref") ||
161 $e->{TYPE} =~ "unistr") {
162 $res .= "\t\tNDR_CHECK(ndr_pull_$e->{TYPE}(ndr, \&$var_prefix$e->{NAME}));\n";
163 } elsif (util::is_builtin_type($e->{TYPE})) {
164 $res .= "\t\tNDR_CHECK(ndr_pull_$e->{TYPE}(ndr, $var_prefix$e->{NAME}));\n";
166 $res .= "\t\tNDR_CHECK(ndr_pull_$e->{TYPE}(ndr, ndr_flags, $var_prefix$e->{NAME}));\n";
170 if ($e->{POINTERS}) {
175 #####################################################################
177 sub ParseStructPush($)
182 if (! defined $struct->{ELEMENTS}) {
186 # see if we have a structure length
187 foreach my $e (@{$struct->{ELEMENTS}}) {
188 if (util::has_property($e->{PROPERTIES}, "struct_len")) {
194 if (defined $struct_len) {
195 $res .= "\tstruct ndr_push_save _save1, _save2, _save3;\n";
196 $res .= "\tndr_push_save(ndr, &_save1);\n";
199 $res .= "\tif (!(ndr_flags & NDR_SCALARS)) goto buffers;\n";
201 foreach my $e (@{$struct->{ELEMENTS}}) {
202 if (defined($struct_len) && $e == $struct_len) {
203 $res .= "\tNDR_CHECK(ndr_push_align_$e->{TYPE}(ndr));\n";
204 $res .= "\tndr_push_save(ndr, &_save2);\n";
206 ParseElementPushScalar($e, "r->", "NDR_SCALARS");
209 $res .= "buffers:\n";
210 $res .= "\tif (!(ndr_flags & NDR_BUFFERS)) goto done;\n";
211 foreach my $e (@{$struct->{ELEMENTS}}) {
212 ParseElementPushBuffer($e, "r->");
215 if (defined $struct_len) {
216 $res .= "\tndr_push_save(ndr, &_save3);\n";
217 $res .= "\tndr_push_restore(ndr, &_save2);\n";
218 $struct_len->{VALUE} = "_save3.offset - _save1.offset";
219 ParseElementPushScalar($struct_len, "r->", "NDR_SCALARS");
220 $res .= "\tndr_push_restore(ndr, &_save3);\n";
226 #####################################################################
227 # parse a struct - pull side
228 sub ParseStructPull($)
233 if (! defined $struct->{ELEMENTS}) {
237 # declare any internal pointers we need
238 foreach my $e (@{$struct->{ELEMENTS}}) {
239 if ($e->{POINTERS} &&
240 !util::has_property($e->{PROPERTIES}, "ref")) {
241 $res .= "\tuint32 _ptr_$e->{NAME};\n";
246 # see if we have a structure length. If we do then we need to advance
247 # the ndr_pull offset to that length past the front of the structure
248 # when we have finished with the structure
249 # we also need to make sure that we limit the size of our parsing
250 # of this structure to the given size
251 foreach my $e (@{$struct->{ELEMENTS}}) {
252 if (util::has_property($e->{PROPERTIES}, "struct_len")) {
254 $e->{VALUE} = "&_size";
258 if (defined $struct_len) {
259 $res .= "\tuint32 _size;\n";
260 $res .= "\tstruct ndr_pull_save _save;\n";
261 $res .= "\tndr_pull_save(ndr, &_save);\n";
264 $res .= "\tif (!(ndr_flags & NDR_SCALARS)) goto buffers;\n";
265 foreach my $e (@{$struct->{ELEMENTS}}) {
266 ParseElementPullScalar($e, "r->");
267 if (defined($struct_len) && $e == $struct_len) {
268 $res .= "\tNDR_CHECK(ndr_pull_limit_size(ndr, _size, 4));\n";
272 $res .= "buffers:\n";
273 $res .= "\tif (!(ndr_flags & NDR_BUFFERS)) goto done;\n";
274 foreach my $e (@{$struct->{ELEMENTS}}) {
275 ParseElementPullBuffer($e, "r->");
278 if (defined $struct_len) {
279 $res .= "\tndr_pull_restore(ndr, &_save);\n";
280 $res .= "\tNDR_CHECK(ndr_pull_advance(ndr, _size));\n";
287 #####################################################################
288 # parse a union element
289 sub ParseUnionElementPush($)
291 die "unions not done";
294 #####################################################################
295 # parse a union - push side
296 sub ParseUnionPush($)
298 die "unions not done";
301 #####################################################################
302 # parse a union - pull side
303 sub ParseUnionPull($)
305 die "unions not done";
308 #####################################################################
314 if (ref($data) eq "HASH") {
315 ($data->{TYPE} eq "STRUCT") &&
316 ParseStructPush($data);
317 ($data->{TYPE} eq "UNION") &&
318 ParseUnionPush($data);
322 #####################################################################
328 if (ref($data) eq "HASH") {
329 ($data->{TYPE} eq "STRUCT") &&
330 ParseStructPull($data);
331 ($data->{TYPE} eq "UNION") &&
332 ParseUnionPull($data);
336 #####################################################################
337 # parse a typedef - push side
338 sub ParseTypedefPush($)
342 $res .= "static NTSTATUS ndr_push_$e->{NAME}(struct ndr_push *ndr, int ndr_flags, struct $e->{NAME} *r)";
344 ParseTypePush($e->{DATA});
345 $res .= "\treturn NT_STATUS_OK;\n";
350 #####################################################################
351 # parse a typedef - pull side
352 sub ParseTypedefPull($)
356 $res .= "static NTSTATUS ndr_pull_$e->{NAME}(struct ndr_pull *ndr, int ndr_flags, struct $e->{NAME} *r)";
358 ParseTypePull($e->{DATA});
359 $res .= "\treturn NT_STATUS_OK;\n";
366 #####################################################################
368 sub ParseFunctionPush($)
370 my($function) = shift;
373 $res .= "NTSTATUS ndr_push_$function->{NAME}(struct ndr_push *ndr, struct $function->{NAME} *r)\n{\n";
375 foreach my $arg (@{$function->{DATA}}) {
376 if (util::has_property($arg->{PROPERTIES}, "in")) {
377 ParseElementPushScalar($arg, "r->in.", "NDR_SCALARS|NDR_BUFFERS");
378 ParseElementPushBuffer($arg, "r->in.");
382 $res .= "\n\treturn NT_STATUS_OK;\n}\n\n";
385 #####################################################################
387 sub ParseFunctionPull($)
391 #####################################################################
396 ParseTypedefPush($e);
397 ParseTypedefPull($e);
400 #####################################################################
405 ParseFunctionPush($i);
406 ParseFunctionPull($i);
409 #####################################################################
410 # parse the interface definitions
411 sub ParseInterface($)
413 my($interface) = shift;
414 my($data) = $interface->{DATA};
415 foreach my $d (@{$data}) {
416 ($d->{TYPE} eq "TYPEDEF") &&
418 ($d->{TYPE} eq "FUNCTION") &&
424 #####################################################################
425 # parse a parsed IDL structure back into an IDL file
429 $res = "/* parser auto-generated by pidl */\n\n";
430 foreach my $x (@{$idl}) {
431 ($x->{TYPE} eq "INTERFACE") &&