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 # work out the name of a size_is() variable
34 my($fn) = $e->{PARENT};
35 my($size) = util::has_property($e, "size_is");
37 if ($fn->{TYPE} ne "FUNCTION") {
41 for my $e2 (@{$fn->{DATA}}) {
42 if ($e2->{NAME} eq $size) {
43 if (util::has_property($e2, "in")) {
46 if (util::has_property($e2, "out")) {
47 return "r->out.$size";
51 die "invalid variable in size_is($size) for element $e->{NAME} in $fn->{NAME}\n";
55 #####################################################################
56 # parse an array - push side
57 sub ParseArrayPush($$)
60 my $var_prefix = shift;
61 my $size = find_size_var($e);
63 if (util::is_scalar_type($e->{TYPE})) {
64 $res .= "\t\tNDR_CHECK(ndr_push_array_$e->{TYPE}(ndr, $var_prefix$e->{NAME}, $size));\n";
66 $res .= "\t\tNDR_CHECK(ndr_push_array(ndr, ndr_flags, $var_prefix$e->{NAME}, sizeof($var_prefix$e->{NAME}\[0]), $size, (ndr_push_flags_fn_t)ndr_push_$e->{TYPE}));\n";
70 #####################################################################
71 # parse an array - pull side
72 sub ParseArrayPull($$)
75 my $var_prefix = shift;
76 my $size = find_size_var($e);
78 if (!util::has_property($e, "ref")) {
79 $res .= "\t\tNDR_ALLOC_N_SIZE(ndr, $var_prefix$e->{NAME}, $size, sizeof($var_prefix$e->{NAME}\[0]));\n";
81 if (util::is_scalar_type($e->{TYPE})) {
82 $res .= "\t\tNDR_CHECK(ndr_pull_array_$e->{TYPE}(ndr, $var_prefix$e->{NAME}, $size));\n";
84 $res .= "\t\tNDR_CHECK(ndr_pull_array(ndr, ndr_flags, (void **)$var_prefix$e->{NAME}, sizeof($var_prefix$e->{NAME}\[0]), $size, (ndr_pull_flags_fn_t)ndr_pull_$e->{TYPE}));\n";
89 #####################################################################
90 # parse scalars in a structure element
91 sub ParseElementPushScalar($$$)
94 my($var_prefix) = shift;
95 my($ndr_flags) = shift;
97 if (defined $e->{VALUE}) {
98 $res .= "\tNDR_CHECK(ndr_push_$e->{TYPE}(ndr, $e->{VALUE}));\n";
99 } elsif ($e->{POINTERS} &&
100 !util::has_property($e, "ref")) {
101 $res .= "\tNDR_CHECK(ndr_push_ptr(ndr, $var_prefix$e->{NAME}));\n";
102 } elsif (util::is_builtin_type($e->{TYPE})) {
103 if (util::is_scalar_type($e->{TYPE}) &&
104 util::has_property($e, "ref")) {
105 $res .= "\tNDR_CHECK(ndr_push_$e->{TYPE}(ndr, *$var_prefix$e->{NAME}));\n";
107 $res .= "\tNDR_CHECK(ndr_push_$e->{TYPE}(ndr, $var_prefix$e->{NAME}));\n";
110 if (util::is_scalar_type($e->{TYPE}) ||
112 $res .= "\tNDR_CHECK(ndr_push_$e->{TYPE}(ndr, $ndr_flags, $var_prefix$e->{NAME}));\n";
114 $res .= "\tNDR_CHECK(ndr_push_$e->{TYPE}(ndr, $ndr_flags, &$var_prefix$e->{NAME}));\n";
119 #####################################################################
120 # parse scalars in a structure element - pull size
121 sub ParseElementPullScalar($$$)
124 my($var_prefix) = shift;
125 my($ndr_flags) = shift;
127 if (defined $e->{VALUE}) {
128 $res .= "\tNDR_CHECK(ndr_pull_$e->{TYPE}(ndr, $e->{VALUE}));\n";
129 } elsif ($e->{POINTERS} &&
130 !util::has_property($e, "ref")) {
131 $res .= "\tNDR_CHECK(ndr_pull_uint32(ndr, &_ptr_$e->{NAME}));\n";
132 $res .= "\tif (_ptr_$e->{NAME}) {\n";
133 $res .= "\t\tNDR_ALLOC(ndr, $var_prefix$e->{NAME});\n";
134 $res .= "\t} else {\n";
135 $res .= "\t\t$var_prefix$e->{NAME} = NULL;\n";
137 } elsif (!util::is_scalar_type($e->{TYPE}) &&
138 util::has_property($e, "ref")) {
139 if (util::is_builtin_type($e->{TYPE})) {
140 $res .= "\tNDR_CHECK(ndr_pull_$e->{TYPE}(ndr, $var_prefix$e->{NAME}));\n";
142 $res .= "\tNDR_CHECK(ndr_pull_$e->{TYPE}(ndr, $ndr_flags, $var_prefix$e->{NAME}));\n";
145 if (util::is_builtin_type($e->{TYPE})) {
146 if (!util::has_property($e, "ref")) {
147 $res .= "\tNDR_CHECK(ndr_pull_$e->{TYPE}(ndr, &$var_prefix$e->{NAME}));\n";
149 $res .= "\tNDR_CHECK(ndr_pull_$e->{TYPE}(ndr, $var_prefix$e->{NAME}));\n";
152 $res .= "\tNDR_CHECK(ndr_pull_$e->{TYPE}(ndr, $ndr_flags, &$var_prefix$e->{NAME}));\n";
157 #####################################################################
158 # parse buffers in a structure element
159 sub ParseElementPushBuffer($$)
162 my($var_prefix) = shift;
164 if (util::has_property($e, "ref")) {
168 if (util::is_scalar_type($e->{TYPE}) && !$e->{POINTERS}) {
172 if ($e->{POINTERS}) {
173 $res .= "\tif ($var_prefix$e->{NAME}) {\n";
176 if (util::has_property($e, "size_is")) {
177 ParseArrayPush($e, "r->");
179 if (util::is_scalar_type($e->{TYPE})) {
180 $res .= "\t\tNDR_CHECK(ndr_push_$e->{TYPE}(ndr, *$var_prefix$e->{NAME}));\n";
181 } elsif (!$e->{POINTERS}) {
182 $res .= "\t\tNDR_CHECK(ndr_push_$e->{TYPE}(ndr, ndr_flags, &$var_prefix$e->{NAME}));\n";
183 } elsif (util::is_builtin_type($e->{TYPE})) {
184 $res .= "\t\tNDR_CHECK(ndr_push_$e->{TYPE}(ndr, $var_prefix$e->{NAME}));\n";
186 $res .= "\t\tNDR_CHECK(ndr_push_$e->{TYPE}(ndr, ndr_flags, $var_prefix$e->{NAME}));\n";
190 if ($e->{POINTERS}) {
196 #####################################################################
197 # parse buffers in a structure element - pull side
198 sub ParseElementPullBuffer($$$)
201 my($var_prefix) = shift;
202 my($ndr_flags) = shift;
204 if (util::has_property($e, "ref")) {
208 if (util::is_scalar_type($e->{TYPE}) && !$e->{POINTERS}) {
212 if ($e->{POINTERS}) {
213 $res .= "\tif ($var_prefix$e->{NAME}) {\n";
216 if (util::has_property($e, "size_is")) {
217 ParseArrayPull($e, "r->");
219 if (!$e->{POINTERS} ||
220 $e->{TYPE} =~ "unistr.*") {
221 if (util::is_builtin_type($e->{TYPE})) {
222 $res .= "\t\tNDR_CHECK(ndr_pull_$e->{TYPE}(ndr, &$var_prefix$e->{NAME}));\n";
224 $res .= "\t\tNDR_CHECK(ndr_pull_$e->{TYPE}(ndr, $ndr_flags, &$var_prefix$e->{NAME}));\n";
226 } elsif (util::is_builtin_type($e->{TYPE})) {
227 $res .= "\t\tNDR_CHECK(ndr_pull_$e->{TYPE}(ndr, $var_prefix$e->{NAME}));\n";
229 $res .= "\t\tNDR_CHECK(ndr_pull_$e->{TYPE}(ndr, $ndr_flags, $var_prefix$e->{NAME}));\n";
233 if ($e->{POINTERS}) {
238 #####################################################################
240 sub ParseStructPush($)
245 if (! defined $struct->{ELEMENTS}) {
249 # see if we have a structure length
250 foreach my $e (@{$struct->{ELEMENTS}}) {
251 $e->{PARENT} = $struct;
252 if (util::has_property($e, "struct_len")) {
258 if (defined $struct_len) {
259 $res .= "\tstruct ndr_push_save _save1, _save2, _save3;\n";
260 $res .= "\tndr_push_save(ndr, &_save1);\n";
263 $res .= "\tif (!(ndr_flags & NDR_SCALARS)) goto buffers;\n";
265 foreach my $e (@{$struct->{ELEMENTS}}) {
266 if (defined($struct_len) && $e == $struct_len) {
267 $res .= "\tNDR_CHECK(ndr_push_align_$e->{TYPE}(ndr));\n";
268 $res .= "\tndr_push_save(ndr, &_save2);\n";
270 ParseElementPushScalar($e, "r->", "NDR_SCALARS");
273 $res .= "buffers:\n";
274 $res .= "\tif (!(ndr_flags & NDR_BUFFERS)) goto done;\n";
275 foreach my $e (@{$struct->{ELEMENTS}}) {
276 ParseElementPushBuffer($e, "r->");
279 if (defined $struct_len) {
280 $res .= "\tndr_push_save(ndr, &_save3);\n";
281 $res .= "\tndr_push_restore(ndr, &_save2);\n";
282 $struct_len->{VALUE} = "_save3.offset - _save1.offset";
283 ParseElementPushScalar($struct_len, "r->", "NDR_SCALARS");
284 $res .= "\tndr_push_restore(ndr, &_save3);\n";
290 #####################################################################
291 # parse a struct - pull side
292 sub ParseStructPull($)
297 if (! defined $struct->{ELEMENTS}) {
301 # declare any internal pointers we need
302 foreach my $e (@{$struct->{ELEMENTS}}) {
303 $e->{PARENT} = $struct;
304 if ($e->{POINTERS} &&
305 !util::has_property($e, "ref")) {
306 $res .= "\tuint32 _ptr_$e->{NAME};\n";
311 # see if we have a structure length. If we do then we need to advance
312 # the ndr_pull offset to that length past the front of the structure
313 # when we have finished with the structure
314 # we also need to make sure that we limit the size of our parsing
315 # of this structure to the given size
316 foreach my $e (@{$struct->{ELEMENTS}}) {
317 if (util::has_property($e, "struct_len")) {
319 $e->{VALUE} = "&_size";
323 if (defined $struct_len) {
324 $res .= "\tuint32 _size;\n";
325 $res .= "\tstruct ndr_pull_save _save;\n";
326 $res .= "\tndr_pull_save(ndr, &_save);\n";
329 $res .= "\tif (!(ndr_flags & NDR_SCALARS)) goto buffers;\n";
330 foreach my $e (@{$struct->{ELEMENTS}}) {
331 ParseElementPullScalar($e, "r->", "NDR_SCALARS");
332 if (defined($struct_len) && $e == $struct_len) {
333 $res .= "\tNDR_CHECK(ndr_pull_limit_size(ndr, _size, 4));\n";
337 $res .= "buffers:\n";
338 $res .= "\tif (!(ndr_flags & NDR_BUFFERS)) goto done;\n";
339 foreach my $e (@{$struct->{ELEMENTS}}) {
340 ParseElementPullBuffer($e, "r->", "ndr_flags");
343 if (defined $struct_len) {
344 $res .= "\tndr_pull_restore(ndr, &_save);\n";
345 $res .= "\tNDR_CHECK(ndr_pull_advance(ndr, _size));\n";
352 #####################################################################
353 # parse a union element
354 sub ParseUnionElementPush($)
356 die "unions not done";
359 #####################################################################
360 # parse a union - push side
361 sub ParseUnionPush($)
363 die "unions not done";
366 #####################################################################
367 # parse a union - pull side
368 sub ParseUnionPull($)
370 die "unions not done";
373 #####################################################################
379 if (ref($data) eq "HASH") {
380 ($data->{TYPE} eq "STRUCT") &&
381 ParseStructPush($data);
382 ($data->{TYPE} eq "UNION") &&
383 ParseUnionPush($data);
387 #####################################################################
393 if (ref($data) eq "HASH") {
394 ($data->{TYPE} eq "STRUCT") &&
395 ParseStructPull($data);
396 ($data->{TYPE} eq "UNION") &&
397 ParseUnionPull($data);
401 #####################################################################
402 # parse a typedef - push side
403 sub ParseTypedefPush($)
407 $res .= "static NTSTATUS ndr_push_$e->{NAME}(struct ndr_push *ndr, int ndr_flags, struct $e->{NAME} *r)";
409 ParseTypePush($e->{DATA});
410 $res .= "\treturn NT_STATUS_OK;\n";
415 #####################################################################
416 # parse a typedef - pull side
417 sub ParseTypedefPull($)
421 $res .= "static NTSTATUS ndr_pull_$e->{NAME}(struct ndr_pull *ndr, int ndr_flags, struct $e->{NAME} *r)";
423 ParseTypePull($e->{DATA});
424 $res .= "\treturn NT_STATUS_OK;\n";
431 #####################################################################
433 sub ParseFunctionPush($)
435 my($function) = shift;
438 $res .= "NTSTATUS ndr_push_$function->{NAME}(struct ndr_push *ndr, struct $function->{NAME} *r)\n{\n";
440 foreach my $e (@{$function->{DATA}}) {
441 if (util::has_property($e, "in")) {
442 $e->{PARENT} = $function;
443 if (util::has_property($e, "size_is")) {
444 $res .= "\tif (r->in.$e->{NAME}) {\n";
445 if (!util::is_scalar_type($e->{TYPE})) {
446 $res .= "\t\tint ndr_flags = NDR_SCALARS|NDR_BUFFERS;\n";
448 ParseArrayPush($e, "r->in.");
451 ParseElementPushScalar($e, "r->in.", "NDR_SCALARS|NDR_BUFFERS");
452 ParseElementPushBuffer($e, "r->in.");
457 $res .= "\n\treturn NT_STATUS_OK;\n}\n\n";
460 #####################################################################
462 sub ParseFunctionPull($)
467 $res .= "NTSTATUS ndr_pull_$fn->{NAME}(struct ndr_pull *ndr, struct $fn->{NAME} *r)\n{\n";
469 # declare any internal pointers we need
470 foreach my $e (@{$fn->{DATA}}) {
471 if (util::has_property($e, "out") &&
473 !util::is_scalar_type($e->{TYPE}) &&
474 !util::has_property($e, "ref")) {
475 $res .= "\tuint32 _ptr_$e->{NAME};\n";
479 foreach my $e (@{$fn->{DATA}}) {
480 if (util::has_property($e, "out")) {
482 if (util::has_property($e, "size_is")) {
483 $res .= "\tif (r->out.$e->{NAME}) {\n";
484 if (!util::is_scalar_type($e->{TYPE})) {
485 $res .= "\t\tint ndr_flags = NDR_SCALARS|NDR_BUFFERS;\n";
487 ParseArrayPull($e, "r->out.");
490 if ($e->{POINTERS} &&
491 !util::has_property($e, "ref")) {
492 $res .= "\tNDR_ALLOC(ndr, r->out.$e->{NAME});\n";
494 ParseElementPullScalar($e, "r->out.", "NDR_SCALARS|NDR_BUFFERS");
495 ParseElementPullBuffer($e, "r->out.", "NDR_SCALARS|NDR_BUFFERS");
500 if ($fn->{RETURN_TYPE} && $fn->{RETURN_TYPE} ne "void") {
501 $res .= "\tNDR_CHECK(ndr_pull_$fn->{RETURN_TYPE}(ndr, &r->out.result));\n";
505 $res .= "\n\treturn NT_STATUS_OK;\n}\n\n";
508 #####################################################################
513 ParseTypedefPush($e);
514 ParseTypedefPull($e);
517 #####################################################################
522 ParseFunctionPush($i);
523 ParseFunctionPull($i);
526 #####################################################################
527 # parse the interface definitions
528 sub ParseInterface($)
530 my($interface) = shift;
531 my($data) = $interface->{DATA};
532 foreach my $d (@{$data}) {
533 ($d->{TYPE} eq "TYPEDEF") &&
535 ($d->{TYPE} eq "FUNCTION") &&
541 #####################################################################
542 # parse a parsed IDL structure back into an IDL file
546 $res = "/* parser auto-generated by pidl */\n\n";
547 $res .= "#include \"includes.h\"\n\n";
548 foreach my $x (@{$idl}) {
549 ($x->{TYPE} eq "INTERFACE") &&