1 ###################################################
2 # Samba4 parser generator for IDL structures
3 # Copyright tridge@samba.org 2000-2003
4 # Copyright tpot@samba.org 2001
5 # released under the GNU GPL
12 # the list of needed functions
21 #####################################################################
22 # parse a properties list
23 sub ParseProperties($)
26 foreach my $d (@{$props}) {
27 if (ref($d) ne "HASH") {
30 foreach my $k (keys %{$d}) {
31 pidl "[$k($d->{$k})] ";
37 ###################################
38 # find a sibling var in a structure
43 my($fn) = $e->{PARENT};
45 if ($name =~ /\*(.*)/) {
49 if ($fn->{TYPE} eq "FUNCTION") {
50 for my $e2 (@{$fn->{DATA}}) {
51 if ($e2->{NAME} eq $name) {
57 for my $e2 (@{$fn->{ELEMENTS}}) {
58 if ($e2->{NAME} eq $name) {
62 die "invalid sibling '$name'";
65 ####################################################################
66 # work out the name of a size_is() variable
71 my($fn) = $e->{PARENT};
73 if (util::is_constant($size)) {
77 if ($size =~ /ndr->|\(/) {
83 if ($size =~ /\*(.*)/) {
88 if ($fn->{TYPE} ne "FUNCTION") {
89 return $prefix . "r->$size";
92 my $e2 = find_sibling($e, $size);
94 if (util::has_property($e2, "in")) {
95 return $prefix . "r->in.$size";
97 if (util::has_property($e2, "out")) {
98 return $prefix . "r->out.$size";
101 die "invalid variable in $size for element $e->{NAME} in $fn->{NAME}\n";
105 #####################################################################
106 # work out is a parse function should be declared static or not
110 if (util::has_property($e, "public")) {
117 ###################################################################
118 # setup any special flags for an element or structure
122 my $flags = util::has_property($e, "flag");
123 if (defined $flags) {
124 pidl "\t{ uint32 _flags_save_$e->{TYPE} = ndr->flags;\n";
125 pidl "\tndr->flags |= $flags;\n";
129 ###################################################################
130 # end any special flags for an element or structure
134 my $flags = util::has_property($e, "flag");
135 if (defined $flags) {
136 pidl "\tndr->flags = _flags_save_$e->{TYPE};\n\t}\n";
141 #####################################################################
142 # work out the correct alignment for a structure
148 for my $e (@{$s->{ELEMENTS}}) {
151 if (!util::need_wire_pointer($e)
152 && defined $structs{$e->{TYPE}}) {
153 if ($structs{$e->{TYPE}}->{DATA}->{TYPE} eq "STRUCT") {
154 $a = struct_alignment($structs{$e->{TYPE}}->{DATA});
155 } elsif ($structs{$e->{TYPE}}->{DATA}->{TYPE} eq "UNION") {
156 if (defined $structs{$e->{TYPE}}->{DATA}) {
157 $a = union_alignment($structs{$e->{TYPE}}->{DATA});
161 $a = util::type_align($e);
172 #####################################################################
173 # work out the correct alignment for a union
180 foreach my $e (@{$u->{DATA}}) {
183 if ($e->{TYPE} eq "EMPTY") {
187 if (!util::need_wire_pointer($e)
188 && defined $structs{$e->{DATA}->{TYPE}}) {
189 my $s = $structs{$e->{DATA}->{TYPE}};
190 if ($s->{DATA}->{TYPE} eq "STRUCT") {
191 $a = struct_alignment($s->{DATA});
192 } elsif ($s->{DATA}->{TYPE} eq "UNION") {
193 $a = union_alignment($s->{DATA});
196 $a = util::type_align($e->{DATA});
207 #####################################################################
208 # parse an array - push side
209 sub ParseArrayPush($$$)
212 my $var_prefix = shift;
213 my $ndr_flags = shift;
215 my $size = find_size_var($e, util::array_size($e));
217 if (defined $e->{CONFORMANT_SIZE}) {
218 # the conformant size has already been pushed
219 } elsif (!util::is_inline_array($e)) {
220 # we need to emit the array size
221 pidl "\t\tNDR_CHECK(ndr_push_uint32(ndr, $size));\n";
224 if (my $length = util::has_property($e, "length_is")) {
225 $length = find_size_var($e, $length);
226 pidl "\t\tNDR_CHECK(ndr_push_uint32(ndr, 0));\n";
227 pidl "\t\tNDR_CHECK(ndr_push_uint32(ndr, $length));\n";
231 if (util::is_scalar_type($e->{TYPE})) {
232 pidl "\t\tNDR_CHECK(ndr_push_array_$e->{TYPE}(ndr, $ndr_flags, $var_prefix$e->{NAME}, $size));\n";
234 pidl "\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";
238 #####################################################################
240 sub ParseArrayPrint($$)
243 my $var_prefix = shift;
244 my $size = find_size_var($e, util::array_size($e));
245 my $length = util::has_property($e, "length_is");
247 if (defined $length) {
248 $size = find_size_var($e, $length);
251 if (util::is_scalar_type($e->{TYPE})) {
252 pidl "\t\tndr_print_array_$e->{TYPE}(ndr, \"$e->{NAME}\", $var_prefix$e->{NAME}, $size);\n";
254 pidl "\t\tndr_print_array(ndr, \"$e->{NAME}\", $var_prefix$e->{NAME}, sizeof($var_prefix$e->{NAME}\[0]), $size, (ndr_print_fn_t)ndr_print_$e->{TYPE});\n";
258 #####################################################################
259 # parse an array - pull side
260 sub ParseArrayPull($$$)
263 my $var_prefix = shift;
264 my $ndr_flags = shift;
266 my $size = find_size_var($e, util::array_size($e));
267 my $alloc_size = $size;
269 # if this is a conformant array then we use that size to allocate, and make sure
270 # we allocate enough to pull the elements
271 if (defined $e->{CONFORMANT_SIZE}) {
272 $alloc_size = $e->{CONFORMANT_SIZE};
274 pidl "\tif ($size > $alloc_size) {\n";
275 pidl "\t\treturn ndr_pull_error(ndr, NDR_ERR_CONFORMANT_SIZE, \"Bad conformant size %u should be %u\", $alloc_size, $size);\n";
277 } elsif (!util::is_inline_array($e)) {
278 # non fixed arrays encode the size just before the array
280 pidl "\t\tuint32 _array_size;\n";
281 pidl "\t\tNDR_CHECK(ndr_pull_uint32(ndr, &_array_size));\n";
282 pidl "\t\tif ($size > _array_size) {\n";
283 pidl "\t\t\treturn ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE, \"Bad array size %u should be %u\", _array_size, $size);\n";
288 if ((util::need_alloc($e) && !util::is_fixed_array($e)) ||
289 ($var_prefix eq "r->in." && util::has_property($e, "ref"))) {
290 if (!util::is_inline_array($e) || $ndr_flags eq "NDR_SCALARS") {
291 pidl "\t\tNDR_ALLOC_N_SIZE(ndr, $var_prefix$e->{NAME}, MAX(1, $alloc_size), sizeof($var_prefix$e->{NAME}\[0]));\n";
295 if (($var_prefix eq "r->out." && util::has_property($e, "ref"))) {
296 if (!util::is_inline_array($e) || $ndr_flags eq "NDR_SCALARS") {
297 pidl "\tif (ndr->flags & LIBNDR_FLAG_REF_ALLOC) {";
298 pidl "\t\tNDR_ALLOC_N_SIZE(ndr, $var_prefix$e->{NAME}, MAX(1, $alloc_size), sizeof($var_prefix$e->{NAME}\[0]));\n";
305 if (my $length = util::has_property($e, "length_is")) {
306 $length = find_size_var($e, $length);
307 pidl "\t\tuint32 _offset, _length;\n";
308 pidl "\t\tNDR_CHECK(ndr_pull_uint32(ndr, &_offset));\n";
309 pidl "\t\tNDR_CHECK(ndr_pull_uint32(ndr, &_length));\n";
310 pidl "\t\tif (_offset != 0) return ndr_pull_error(ndr, NDR_ERR_OFFSET, \"Bad array offset 0x%08x\", _offset);\n";
311 pidl "\t\tif (_length > $size || _length != $length) return ndr_pull_error(ndr, NDR_ERR_LENGTH, \"Bad array length 0x%08x > size 0x%08x\", _offset, $size);\n\n";
315 if (util::is_scalar_type($e->{TYPE})) {
316 pidl "\t\tNDR_CHECK(ndr_pull_array_$e->{TYPE}(ndr, $ndr_flags, $var_prefix$e->{NAME}, $size));\n";
318 pidl "\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";
325 #####################################################################
326 # parse scalars in a structure element
327 sub ParseElementPushScalar($$$)
330 my($var_prefix) = shift;
331 my($ndr_flags) = shift;
332 my $cprefix = util::c_push_prefix($e);
333 my $sub_size = util::has_property($e, "subcontext");
337 if (my $value = util::has_property($e, "value")) {
338 pidl "\t$cprefix$var_prefix$e->{NAME} = $value;\n";
341 if (util::has_property($e, "relative")) {
342 pidl "\tNDR_CHECK(ndr_push_relative(ndr, NDR_SCALARS, $var_prefix$e->{NAME}, (ndr_push_const_fn_t) ndr_push_$e->{TYPE}));\n";
343 } elsif (util::is_inline_array($e)) {
344 ParseArrayPush($e, "r->", "NDR_SCALARS");
345 } elsif (util::need_wire_pointer($e)) {
346 pidl "\tNDR_CHECK(ndr_push_ptr(ndr, $var_prefix$e->{NAME}));\n";
347 } elsif (util::need_alloc($e)) {
348 # no scalar component
349 } elsif (my $switch = util::has_property($e, "switch_is")) {
350 ParseElementPushSwitch($e, $var_prefix, $ndr_flags, $switch);
351 } elsif (defined $sub_size) {
352 if (util::is_builtin_type($e->{TYPE})) {
353 pidl "\tNDR_CHECK(ndr_push_subcontext_fn(ndr, $sub_size, $cprefix$var_prefix$e->{NAME}, (ndr_push_fn_t) ndr_push_$e->{TYPE}));\n";
355 pidl "\tNDR_CHECK(ndr_push_subcontext_flags_fn(ndr, $sub_size, $cprefix$var_prefix$e->{NAME}, (ndr_push_flags_fn_t) ndr_push_$e->{TYPE}));\n";
357 } elsif (util::is_builtin_type($e->{TYPE})) {
358 pidl "\tNDR_CHECK(ndr_push_$e->{TYPE}(ndr, $cprefix$var_prefix$e->{NAME}));\n";
360 pidl "\tNDR_CHECK(ndr_push_$e->{TYPE}(ndr, $ndr_flags, $cprefix$var_prefix$e->{NAME}));\n";
366 #####################################################################
367 # print scalars in a structure element
368 sub ParseElementPrintScalar($$)
371 my($var_prefix) = shift;
372 my $cprefix = util::c_push_prefix($e);
374 if (util::has_property($e, "noprint")) {
378 if (util::has_direct_buffers($e)) {
379 pidl "\tndr_print_ptr(ndr, \"$e->{NAME}\", $var_prefix$e->{NAME});\n";
380 pidl "\tndr->depth++;\n";
381 ParseElementPrintBuffer($e, $var_prefix);
382 pidl "\tndr->depth--;\n";
383 } elsif (my $switch = util::has_property($e, "switch_is")) {
384 ParseElementPrintSwitch($e, $var_prefix, $switch);
386 pidl "\tndr_print_$e->{TYPE}(ndr, \"$e->{NAME}\", $cprefix$var_prefix$e->{NAME});\n";
390 #####################################################################
391 # parse scalars in a structure element - pull size
392 sub ParseElementPullSwitch($$$$)
395 my($var_prefix) = shift;
396 my($ndr_flags) = shift;
398 my $switch_var = find_size_var($e, $switch);
400 my $cprefix = util::c_pull_prefix($e);
402 my $utype = $structs{$e->{TYPE}};
403 if (!defined $utype ||
404 !util::has_property($utype->{DATA}, "nodiscriminant")) {
405 my $e2 = find_sibling($e, $switch);
406 pidl "\tif (($ndr_flags) & NDR_SCALARS) {\n";
407 pidl "\t\t $e2->{TYPE} _level;\n";
408 pidl "\t\tNDR_CHECK(ndr_pull_$e2->{TYPE}(ndr, &_level));\n";
409 pidl "\t\tif (_level != $switch_var) return ndr_pull_error(ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value %u in $e->{NAME}\");\n";
413 my $sub_size = util::has_property($e, "subcontext");
414 if (defined $sub_size) {
415 pidl "\tNDR_CHECK(ndr_pull_subcontext_union_fn(ndr, $sub_size, $switch_var, $cprefix$var_prefix$e->{NAME}, (ndr_pull_union_fn_t) ndr_pull_$e->{TYPE}));\n";
417 pidl "\tNDR_CHECK(ndr_pull_$e->{TYPE}(ndr, $ndr_flags, $switch_var, $cprefix$var_prefix$e->{NAME}));\n";
423 #####################################################################
424 # push switch element
425 sub ParseElementPushSwitch($$$$)
428 my($var_prefix) = shift;
429 my($ndr_flags) = shift;
431 my $switch_var = find_size_var($e, $switch);
432 my $cprefix = util::c_push_prefix($e);
434 my $utype = $structs{$e->{TYPE}};
435 if (!defined $utype ||
436 !util::has_property($utype->{DATA}, "nodiscriminant")) {
437 my $e2 = find_sibling($e, $switch);
438 pidl "\tif (($ndr_flags) & NDR_SCALARS) {\n";
439 pidl "\t\tNDR_CHECK(ndr_push_$e2->{TYPE}(ndr, $switch_var));\n";
443 my $sub_size = util::has_property($e, "subcontext");
444 if (defined $sub_size) {
445 pidl "\tNDR_CHECK(ndr_push_subcontext_union_fn(ndr, $sub_size, $switch_var, $cprefix$var_prefix$e->{NAME}, (ndr_push_union_fn_t) ndr_push_$e->{TYPE}));\n";
447 pidl "\tNDR_CHECK(ndr_push_$e->{TYPE}(ndr, $ndr_flags, $switch_var, $cprefix$var_prefix$e->{NAME}));\n";
451 #####################################################################
452 # print scalars in a structure element
453 sub ParseElementPrintSwitch($$$)
456 my($var_prefix) = shift;
458 my $switch_var = find_size_var($e, $switch);
459 my $cprefix = util::c_push_prefix($e);
461 pidl "\tndr_print_$e->{TYPE}(ndr, \"$e->{NAME}\", $switch_var, $cprefix$var_prefix$e->{NAME});\n";
465 #####################################################################
466 # parse scalars in a structure element - pull size
467 sub ParseElementPullScalar($$$)
470 my($var_prefix) = shift;
471 my($ndr_flags) = shift;
472 my $cprefix = util::c_pull_prefix($e);
473 my $sub_size = util::has_property($e, "subcontext");
477 if (util::has_property($e, "relative")) {
478 pidl "\tNDR_CHECK(ndr_pull_relative(ndr, (const void **)&$var_prefix$e->{NAME}, sizeof(*$var_prefix$e->{NAME}), (ndr_pull_flags_fn_t)ndr_pull_$e->{TYPE}));\n";
479 } elsif (util::is_inline_array($e)) {
480 ParseArrayPull($e, "r->", "NDR_SCALARS");
481 } elsif (util::need_wire_pointer($e)) {
482 pidl "\tNDR_CHECK(ndr_pull_uint32(ndr, &_ptr_$e->{NAME}));\n";
483 pidl "\tif (_ptr_$e->{NAME}) {\n";
484 pidl "\t\tNDR_ALLOC(ndr, $var_prefix$e->{NAME});\n";
486 pidl "\t\t$var_prefix$e->{NAME} = NULL;\n";
488 } elsif (util::need_alloc($e)) {
489 # no scalar component
490 } elsif (my $switch = util::has_property($e, "switch_is")) {
491 ParseElementPullSwitch($e, $var_prefix, $ndr_flags, $switch);
492 } elsif (defined $sub_size) {
493 if (util::is_builtin_type($e->{TYPE})) {
494 pidl "\tNDR_CHECK(ndr_pull_subcontext_fn(ndr, $sub_size, $cprefix$var_prefix$e->{NAME}, (ndr_pull_fn_t) ndr_pull_$e->{TYPE}));\n";
496 pidl "\tNDR_CHECK(ndr_pull_subcontext_flags_fn(ndr, $sub_size, $cprefix$var_prefix$e->{NAME}, (ndr_pull_flags_fn_t) ndr_pull_$e->{TYPE}));\n";
498 } elsif (util::is_builtin_type($e->{TYPE})) {
499 pidl "\tNDR_CHECK(ndr_pull_$e->{TYPE}(ndr, $cprefix$var_prefix$e->{NAME}));\n";
501 pidl "\tNDR_CHECK(ndr_pull_$e->{TYPE}(ndr, $ndr_flags, $cprefix$var_prefix$e->{NAME}));\n";
507 #####################################################################
508 # parse buffers in a structure element
509 sub ParseElementPushBuffer($$$)
512 my($var_prefix) = shift;
513 my($ndr_flags) = shift;
514 my $cprefix = util::c_push_prefix($e);
515 my $sub_size = util::has_property($e, "subcontext");
517 if (util::is_pure_scalar($e)) {
523 if (util::need_wire_pointer($e)) {
524 pidl "\tif ($var_prefix$e->{NAME}) {\n";
527 if (util::has_property($e, "relative")) {
528 pidl "\tNDR_CHECK(ndr_push_relative(ndr, NDR_BUFFERS, $cprefix$var_prefix$e->{NAME}, (ndr_push_const_fn_t) ndr_push_$e->{TYPE}));\n";
529 } elsif (util::is_inline_array($e)) {
530 ParseArrayPush($e, "r->", "NDR_BUFFERS");
531 } elsif (util::array_size($e)) {
532 ParseArrayPush($e, "r->", "NDR_SCALARS|NDR_BUFFERS");
533 } elsif (my $switch = util::has_property($e, "switch_is")) {
534 if ($e->{POINTERS}) {
535 ParseElementPushSwitch($e, $var_prefix, "NDR_BUFFERS|NDR_SCALARS", $switch);
537 ParseElementPushSwitch($e, $var_prefix, "NDR_BUFFERS", $switch);
539 } elsif (defined $sub_size) {
540 if ($e->{POINTERS}) {
541 if (util::is_builtin_type($e->{TYPE})) {
542 pidl "\tNDR_CHECK(ndr_push_subcontext_fn(ndr, $sub_size, $cprefix$var_prefix$e->{NAME}, (ndr_push_fn_t) ndr_push_$e->{TYPE}));\n";
544 pidl "\tNDR_CHECK(ndr_push_subcontext_flags_fn(ndr, $sub_size, $cprefix$var_prefix$e->{NAME}, (ndr_push_flags_fn_t) ndr_push_$e->{TYPE}));\n";
547 } elsif (util::is_builtin_type($e->{TYPE})) {
548 pidl "\t\tNDR_CHECK(ndr_push_$e->{TYPE}(ndr, $cprefix$var_prefix$e->{NAME}));\n";
549 } elsif ($e->{POINTERS}) {
550 pidl "\t\tNDR_CHECK(ndr_push_$e->{TYPE}(ndr, NDR_SCALARS|NDR_BUFFERS, $cprefix$var_prefix$e->{NAME}));\n";
552 pidl "\t\tNDR_CHECK(ndr_push_$e->{TYPE}(ndr, $ndr_flags, $cprefix$var_prefix$e->{NAME}));\n";
555 if (util::need_wire_pointer($e)) {
562 #####################################################################
563 # print buffers in a structure element
564 sub ParseElementPrintBuffer($$)
567 my($var_prefix) = shift;
568 my $cprefix = util::c_push_prefix($e);
570 if (util::need_wire_pointer($e)) {
571 pidl "\tif ($var_prefix$e->{NAME}) {\n";
574 if (util::array_size($e)) {
575 ParseArrayPrint($e, $var_prefix);
576 } elsif (my $switch = util::has_property($e, "switch_is")) {
577 ParseElementPrintSwitch($e, $var_prefix, $switch);
579 pidl "\t\tndr_print_$e->{TYPE}(ndr, \"$e->{NAME}\", $cprefix$var_prefix$e->{NAME});\n";
582 if (util::need_wire_pointer($e)) {
588 #####################################################################
589 # parse buffers in a structure element - pull side
590 sub ParseElementPullBuffer($$$)
593 my($var_prefix) = shift;
594 my($ndr_flags) = shift;
595 my $cprefix = util::c_pull_prefix($e);
596 my $sub_size = util::has_property($e, "subcontext");
598 if (util::is_pure_scalar($e)) {
602 if (util::has_property($e, "relative")) {
608 if (util::need_wire_pointer($e)) {
609 pidl "\tif ($var_prefix$e->{NAME}) {\n";
612 if (util::is_inline_array($e)) {
613 ParseArrayPull($e, "r->", "NDR_BUFFERS");
614 } elsif (util::array_size($e)) {
615 ParseArrayPull($e, "r->", "NDR_SCALARS|NDR_BUFFERS");
616 } elsif (my $switch = util::has_property($e, "switch_is")) {
617 if ($e->{POINTERS}) {
618 ParseElementPullSwitch($e, $var_prefix, "NDR_SCALARS|NDR_BUFFERS", $switch);
620 ParseElementPullSwitch($e, $var_prefix, "NDR_BUFFERS", $switch);
622 } elsif (defined $sub_size) {
623 if ($e->{POINTERS}) {
624 if (util::is_builtin_type($e->{TYPE})) {
625 pidl "\tNDR_CHECK(ndr_pull_subcontext_fn(ndr, $sub_size, $cprefix$var_prefix$e->{NAME}, (ndr_pull_fn_t) ndr_pull_$e->{TYPE}));\n";
627 pidl "\tNDR_CHECK(ndr_pull_subcontext_flags_fn(ndr, $sub_size, $cprefix$var_prefix$e->{NAME}, (ndr_pull_flags_fn_t) ndr_pull_$e->{TYPE}));\n";
630 } elsif (util::is_builtin_type($e->{TYPE})) {
631 pidl "\t\tNDR_CHECK(ndr_pull_$e->{TYPE}(ndr, $cprefix$var_prefix$e->{NAME}));\n";
632 } elsif ($e->{POINTERS}) {
633 pidl "\t\tNDR_CHECK(ndr_pull_$e->{TYPE}(ndr, NDR_SCALARS|NDR_BUFFERS, $cprefix$var_prefix$e->{NAME}));\n";
635 pidl "\t\tNDR_CHECK(ndr_pull_$e->{TYPE}(ndr, $ndr_flags, $cprefix$var_prefix$e->{NAME}));\n";
638 if (util::need_wire_pointer($e)) {
645 #####################################################################
647 sub ParseStructPush($)
652 if (! defined $struct->{ELEMENTS}) {
656 start_flags($struct);
658 # see if the structure contains a conformant array. If it
659 # does, then it must be the last element of the structure, and
660 # we need to push the conformant length early, as it fits on
661 # the wire before the structure (and even before the structure
663 my $e = $struct->{ELEMENTS}[-1];
664 if (defined $e->{ARRAY_LEN} && $e->{ARRAY_LEN} eq "*") {
665 my $size = find_size_var($e, util::array_size($e));
666 $e->{CONFORMANT_SIZE} = $size;
668 pidl "\tNDR_CHECK(ndr_push_uint32(ndr, $size));\n";
671 pidl "\tif (!(ndr_flags & NDR_SCALARS)) goto buffers;\n";
673 pidl "\tNDR_CHECK(ndr_push_struct_start(ndr));\n";
675 my $align = struct_alignment($struct);
676 pidl "\tNDR_CHECK(ndr_push_align(ndr, $align));\n";
678 foreach my $e (@{$struct->{ELEMENTS}}) {
679 ParseElementPushScalar($e, "r->", "NDR_SCALARS");
683 pidl "\tif (!(ndr_flags & NDR_BUFFERS)) goto done;\n";
684 foreach my $e (@{$struct->{ELEMENTS}}) {
685 ParseElementPushBuffer($e, "r->", "NDR_BUFFERS");
688 pidl "\tndr_push_struct_end(ndr);\n";
695 #####################################################################
696 # generate a struct print function
697 sub ParseStructPrint($)
701 if (! defined $struct->{ELEMENTS}) {
705 pidl "\tndr->depth++;\n";
706 foreach my $e (@{$struct->{ELEMENTS}}) {
707 ParseElementPrintScalar($e, "r->");
709 pidl "\tndr->depth--;\n";
712 #####################################################################
713 # parse a struct - pull side
714 sub ParseStructPull($)
719 if (! defined $struct->{ELEMENTS}) {
723 start_flags($struct);
725 # see if the structure contains a conformant array. If it
726 # does, then it must be the last element of the structure, and
727 # we need to pull the conformant length early, as it fits on
728 # the wire before the structure (and even before the structure
730 my $e = $struct->{ELEMENTS}[-1];
731 if (defined $e->{ARRAY_LEN} && $e->{ARRAY_LEN} eq "*") {
733 pidl "\tuint32 _conformant_size;\n";
734 $conform_e->{CONFORMANT_SIZE} = "_conformant_size";
737 # declare any internal pointers we need
738 foreach my $e (@{$struct->{ELEMENTS}}) {
739 if (util::need_wire_pointer($e) &&
740 !util::has_property($e, "relative")) {
741 pidl "\tuint32 _ptr_$e->{NAME};\n";
745 pidl "\tif (!(ndr_flags & NDR_SCALARS)) goto buffers;\n";
747 pidl "\tNDR_CHECK(ndr_pull_struct_start(ndr));\n";
749 if (defined $conform_e) {
750 pidl "\tNDR_CHECK(ndr_pull_uint32(ndr, &$conform_e->{CONFORMANT_SIZE}));\n";
753 my $align = struct_alignment($struct);
754 pidl "\tNDR_CHECK(ndr_pull_align(ndr, $align));\n";
756 foreach my $e (@{$struct->{ELEMENTS}}) {
757 ParseElementPullScalar($e, "r->", "NDR_SCALARS");
761 pidl "\tif (!(ndr_flags & NDR_BUFFERS)) goto done;\n";
762 foreach my $e (@{$struct->{ELEMENTS}}) {
763 ParseElementPullBuffer($e, "r->", "NDR_BUFFERS");
766 pidl "\tndr_pull_struct_end(ndr);\n";
774 #####################################################################
775 # parse a union - push side
776 sub ParseUnionPush($)
779 my $have_default = 0;
783 pidl "\tif (!(ndr_flags & NDR_SCALARS)) goto buffers;\n";
785 pidl "\tNDR_CHECK(ndr_push_struct_start(ndr));\n";
787 # my $align = union_alignment($e);
788 # pidl "\tNDR_CHECK(ndr_push_align(ndr, $align));\n";
790 pidl "\tswitch (level) {\n";
791 foreach my $el (@{$e->{DATA}}) {
792 if ($el->{CASE} eq "default") {
796 pidl "\tcase $el->{CASE}:\n";
798 if ($el->{TYPE} eq "UNION_ELEMENT") {
799 ParseElementPushScalar($el->{DATA}, "r->", "NDR_SCALARS");
803 if (! $have_default) {
805 pidl "\t\treturn ndr_push_error(ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value \%u\", level);\n";
809 pidl "\tif (!(ndr_flags & NDR_BUFFERS)) goto done;\n";
810 pidl "\tswitch (level) {\n";
811 foreach my $el (@{$e->{DATA}}) {
812 if ($el->{CASE} eq "default") {
815 pidl "\tcase $el->{CASE}:\n";
817 if ($el->{TYPE} eq "UNION_ELEMENT") {
818 ParseElementPushBuffer($el->{DATA}, "r->", "NDR_BUFFERS");
822 if (! $have_default) {
824 pidl "\t\treturn ndr_push_error(ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value \%u\", level);\n";
827 pidl "\tndr_push_struct_end(ndr);\n";
832 #####################################################################
834 sub ParseUnionPrint($)
837 my $have_default = 0;
839 pidl "\tswitch (level) {\n";
840 foreach my $el (@{$e->{DATA}}) {
841 if ($el->{CASE} eq "default") {
845 pidl "\tcase $el->{CASE}:\n";
847 if ($el->{TYPE} eq "UNION_ELEMENT") {
848 ParseElementPrintScalar($el->{DATA}, "r->");
852 if (! $have_default) {
853 pidl "\tdefault:\n\t\tndr_print_bad_level(ndr, name, level);\n";
858 #####################################################################
859 # parse a union - pull side
860 sub ParseUnionPull($)
863 my $have_default = 0;
867 pidl "\tif (!(ndr_flags & NDR_SCALARS)) goto buffers;\n";
869 pidl "\tNDR_CHECK(ndr_pull_struct_start(ndr));\n";
871 # my $align = union_alignment($e);
872 # pidl "\tNDR_CHECK(ndr_pull_align(ndr, $align));\n";
874 pidl "\tswitch (level) {\n";
875 foreach my $el (@{$e->{DATA}}) {
876 if ($el->{CASE} eq "default") {
877 pidl "\tdefault: {\n";
880 pidl "\tcase $el->{CASE}: {\n";
882 if ($el->{TYPE} eq "UNION_ELEMENT") {
883 my $e2 = $el->{DATA};
884 if ($e2->{POINTERS}) {
885 pidl "\t\tuint32 _ptr_$e2->{NAME};\n";
887 ParseElementPullScalar($el->{DATA}, "r->", "NDR_SCALARS");
889 pidl "\tbreak; }\n\n";
891 if (! $have_default) {
893 pidl "\t\treturn ndr_pull_error(ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value \%u\", level);\n";
897 pidl "\tif (!(ndr_flags & NDR_BUFFERS)) goto done;\n";
898 pidl "\tswitch (level) {\n";
899 foreach my $el (@{$e->{DATA}}) {
900 if ($el->{CASE} eq "default") {
903 pidl "\tcase $el->{CASE}:\n";
905 if ($el->{TYPE} eq "UNION_ELEMENT") {
906 ParseElementPullBuffer($el->{DATA}, "r->", "NDR_BUFFERS");
910 if (! $have_default) {
912 pidl "\t\treturn ndr_pull_error(ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value \%u\", level);\n";
915 pidl "\tndr_pull_struct_end(ndr);\n";
920 #####################################################################
926 if (ref($data) eq "HASH") {
927 ($data->{TYPE} eq "STRUCT") &&
928 ParseStructPush($data);
929 ($data->{TYPE} eq "UNION") &&
930 ParseUnionPush($data);
934 #####################################################################
935 # generate a print function for a type
936 sub ParseTypePrint($)
940 if (ref($data) eq "HASH") {
941 ($data->{TYPE} eq "STRUCT") &&
942 ParseStructPrint($data);
943 ($data->{TYPE} eq "UNION") &&
944 ParseUnionPrint($data);
948 #####################################################################
954 if (ref($data) eq "HASH") {
955 ($data->{TYPE} eq "STRUCT") &&
956 ParseStructPull($data);
957 ($data->{TYPE} eq "UNION") &&
958 ParseUnionPull($data);
962 #####################################################################
963 # parse a typedef - push side
964 sub ParseTypedefPush($)
967 my $static = fn_prefix($e);
969 if (! $needed{"push_$e->{NAME}"}) {
970 # print "push_$e->{NAME} not needed\n";
974 if ($e->{DATA}->{TYPE} eq "STRUCT") {
975 pidl "$static" . "NTSTATUS ndr_push_$e->{NAME}(struct ndr_push *ndr, int ndr_flags, struct $e->{NAME} *r)";
977 ParseTypePush($e->{DATA});
978 pidl "\treturn NT_STATUS_OK;\n";
982 if ($e->{DATA}->{TYPE} eq "UNION") {
983 pidl "$static" . "NTSTATUS ndr_push_$e->{NAME}(struct ndr_push *ndr, int ndr_flags, uint16 level, union $e->{NAME} *r)";
985 ParseTypePush($e->{DATA});
986 pidl "\treturn NT_STATUS_OK;\n";
992 #####################################################################
993 # parse a typedef - pull side
994 sub ParseTypedefPull($)
997 my $static = fn_prefix($e);
999 if (! $needed{"pull_$e->{NAME}"}) {
1000 # print "pull_$e->{NAME} not needed\n";
1004 if ($e->{DATA}->{TYPE} eq "STRUCT") {
1005 pidl "$static" . "NTSTATUS ndr_pull_$e->{NAME}(struct ndr_pull *ndr, int ndr_flags, struct $e->{NAME} *r)";
1007 ParseTypePull($e->{DATA});
1008 pidl "\treturn NT_STATUS_OK;\n";
1012 if ($e->{DATA}->{TYPE} eq "UNION") {
1013 pidl "$static" . "NTSTATUS ndr_pull_$e->{NAME}(struct ndr_pull *ndr, int ndr_flags, uint16 level, union $e->{NAME} *r)";
1015 ParseTypePull($e->{DATA});
1016 pidl "\treturn NT_STATUS_OK;\n";
1022 #####################################################################
1023 # parse a typedef - print side
1024 sub ParseTypedefPrint($)
1028 if ($e->{DATA}->{TYPE} eq "STRUCT") {
1029 pidl "void ndr_print_$e->{NAME}(struct ndr_print *ndr, const char *name, struct $e->{NAME} *r)";
1031 pidl "\tndr_print_struct(ndr, name, \"$e->{NAME}\");\n";
1032 ParseTypePrint($e->{DATA});
1036 if ($e->{DATA}->{TYPE} eq "UNION") {
1037 pidl "void ndr_print_$e->{NAME}(struct ndr_print *ndr, const char *name, uint16 level, union $e->{NAME} *r)";
1039 pidl "\tndr_print_union(ndr, name, level, \"$e->{NAME}\");\n";
1040 ParseTypePrint($e->{DATA});
1045 #####################################################################
1046 # parse a function - print side
1047 sub ParseFunctionPrint($)
1051 pidl "void ndr_print_$fn->{NAME}(struct ndr_print *ndr, const char *name, int flags, struct $fn->{NAME} *r)";
1053 pidl "\tndr_print_struct(ndr, name, \"$fn->{NAME}\");\n";
1054 pidl "\tndr->depth++;\n";
1056 pidl "\tif (flags & NDR_IN) {\n";
1057 pidl "\t\tndr_print_struct(ndr, \"in\", \"$fn->{NAME}\");\n";
1058 pidl "\tndr->depth++;\n";
1059 foreach my $e (@{$fn->{DATA}}) {
1060 if (util::has_property($e, "in")) {
1061 ParseElementPrintScalar($e, "r->in.");
1064 pidl "\tndr->depth--;\n";
1067 pidl "\tif (flags & NDR_OUT) {\n";
1068 pidl "\t\tndr_print_struct(ndr, \"out\", \"$fn->{NAME}\");\n";
1069 pidl "\tndr->depth++;\n";
1070 foreach my $e (@{$fn->{DATA}}) {
1071 if (util::has_property($e, "out")) {
1072 ParseElementPrintScalar($e, "r->out.");
1075 if ($fn->{RETURN_TYPE} && $fn->{RETURN_TYPE} ne "void") {
1076 pidl "\tndr_print_$fn->{RETURN_TYPE}(ndr, \"result\", &r->out.result);\n";
1078 pidl "\tndr->depth--;\n";
1081 pidl "\tndr->depth--;\n";
1086 #####################################################################
1087 # parse a function element
1088 sub ParseFunctionElementPush($$)
1093 if (util::array_size($e)) {
1094 if (util::need_wire_pointer($e)) {
1095 pidl "\tNDR_CHECK(ndr_push_ptr(ndr, r->$inout.$e->{NAME}));\n";
1097 pidl "\tif (r->$inout.$e->{NAME}) {\n";
1098 ParseArrayPush($e, "r->$inout.", "NDR_SCALARS|NDR_BUFFERS");
1101 ParseElementPushScalar($e, "r->$inout.", "NDR_SCALARS|NDR_BUFFERS");
1102 if ($e->{POINTERS}) {
1103 ParseElementPushBuffer($e, "r->$inout.", "NDR_SCALARS|NDR_BUFFERS");
1108 #####################################################################
1110 sub ParseFunctionPush($)
1114 pidl "NTSTATUS ndr_push_$fn->{NAME}(struct ndr_push *ndr, int flags, struct $fn->{NAME} *r)\n{\n";
1116 pidl "\n\tif (!(flags & NDR_IN)) goto ndr_out;\n\n";
1117 foreach my $e (@{$fn->{DATA}}) {
1118 if (util::has_property($e, "in")) {
1119 ParseFunctionElementPush($e, "in");
1123 pidl "\nndr_out:\n";
1124 pidl "\tif (!(flags & NDR_OUT)) goto done;\n\n";
1125 foreach my $e (@{$fn->{DATA}}) {
1126 if (util::has_property($e, "out")) {
1127 ParseFunctionElementPush($e, "out");
1131 if ($fn->{RETURN_TYPE} && $fn->{RETURN_TYPE} ne "void") {
1132 pidl "\tNDR_CHECK(ndr_push_$fn->{RETURN_TYPE}(ndr, r->out.result));\n";
1136 pidl "\n\treturn NT_STATUS_OK;\n}\n\n";
1139 #####################################################################
1140 # parse a function element
1141 sub ParseFunctionElementPull($$)
1146 if (util::array_size($e)) {
1147 if (util::need_wire_pointer($e)) {
1148 pidl "\tNDR_CHECK(ndr_pull_uint32(ndr, _ptr_$e->{NAME}));\n";
1149 pidl "\tif (_ptr_$e->{NAME}) {\n";
1150 } elsif ($inout eq "in" && util::has_property($e, "ref")) {
1153 pidl "\tif (r->$inout.$e->{NAME}) {\n";
1155 ParseArrayPull($e, "r->$inout.", "NDR_SCALARS|NDR_BUFFERS");
1158 if ($inout eq "out" && util::has_property($e, "ref")) {
1159 pidl "\tif (ndr->flags & LIBNDR_FLAG_REF_ALLOC) {\n";
1160 pidl "\tNDR_ALLOC(ndr, r->out.$e->{NAME});\n";
1163 if ($inout eq "in" && util::has_property($e, "ref")) {
1164 pidl "\tNDR_ALLOC(ndr, r->in.$e->{NAME});\n";
1167 ParseElementPullScalar($e, "r->$inout.", "NDR_SCALARS|NDR_BUFFERS");
1168 if ($e->{POINTERS}) {
1169 ParseElementPullBuffer($e, "r->$inout.", "NDR_SCALARS|NDR_BUFFERS");
1174 #####################################################################
1176 sub ParseFunctionPull($)
1180 # pull function args
1181 pidl "NTSTATUS ndr_pull_$fn->{NAME}(struct ndr_pull *ndr, int flags, struct $fn->{NAME} *r)\n{\n";
1183 # declare any internal pointers we need
1184 foreach my $e (@{$fn->{DATA}}) {
1185 if (util::need_wire_pointer($e)) {
1186 pidl "\tuint32 _ptr_$e->{NAME};\n";
1190 pidl "\n\tif (!(flags & NDR_IN)) goto ndr_out;\n\n";
1191 foreach my $e (@{$fn->{DATA}}) {
1192 if (util::has_property($e, "in")) {
1193 ParseFunctionElementPull($e, "in");
1197 pidl "\nndr_out:\n";
1198 pidl "\tif (!(flags & NDR_OUT)) goto done;\n\n";
1199 foreach my $e (@{$fn->{DATA}}) {
1200 if (util::has_property($e, "out")) {
1201 ParseFunctionElementPull($e, "out");
1205 if ($fn->{RETURN_TYPE} && $fn->{RETURN_TYPE} ne "void") {
1206 pidl "\tNDR_CHECK(ndr_pull_$fn->{RETURN_TYPE}(ndr, &r->out.result));\n";
1210 pidl "\n\treturn NT_STATUS_OK;\n}\n\n";
1213 #####################################################################
1214 # parse the interface definitions
1215 sub ParseInterface($)
1217 my($interface) = shift;
1218 my($data) = $interface->{DATA};
1220 foreach my $d (@{$data}) {
1221 if ($d->{TYPE} eq "TYPEDEF") {
1222 $structs{$d->{NAME}} = $d;
1228 foreach my $d (@{$data}) {
1229 ($d->{TYPE} eq "TYPEDEF") &&
1230 ParseTypedefPush($d);
1231 ($d->{TYPE} eq "FUNCTION") &&
1232 ParseFunctionPush($d);
1234 foreach my $d (@{$data}) {
1235 ($d->{TYPE} eq "TYPEDEF") &&
1236 ParseTypedefPull($d);
1237 ($d->{TYPE} eq "FUNCTION") &&
1238 ParseFunctionPull($d);
1240 foreach my $d (@{$data}) {
1241 if ($d->{TYPE} eq "TYPEDEF" &&
1242 !util::has_property($d->{DATA}, "noprint")) {
1243 ParseTypedefPrint($d);
1245 if ($d->{TYPE} eq "FUNCTION" &&
1246 !util::has_property($d, "noprint")) {
1247 ParseFunctionPrint($d);
1252 sub NeededFunction($)
1255 $needed{"pull_$fn->{NAME}"} = 1;
1256 $needed{"push_$fn->{NAME}"} = 1;
1257 foreach my $e (@{$fn->{DATA}}) {
1259 $needed{"pull_$e->{TYPE}"} = 1;
1260 $needed{"push_$e->{TYPE}"} = 1;
1264 sub NeededTypedef($)
1267 if (util::has_property($t->{DATA}, "public")) {
1268 $needed{"pull_$t->{NAME}"} = 1;
1269 $needed{"push_$t->{NAME}"} = 1;
1271 if ($t->{DATA}->{TYPE} eq "STRUCT") {
1272 for my $e (@{$t->{DATA}->{ELEMENTS}}) {
1273 $e->{PARENT} = $t->{DATA};
1274 if ($needed{"pull_$t->{NAME}"}) {
1275 $needed{"pull_$e->{TYPE}"} = 1;
1277 if ($needed{"push_$t->{NAME}"}) {
1278 $needed{"push_$e->{TYPE}"} = 1;
1282 if ($t->{DATA}->{TYPE} eq "UNION") {
1283 for my $e (@{$t->{DATA}->{DATA}}) {
1284 $e->{PARENT} = $t->{DATA};
1285 if ($e->{TYPE} eq "UNION_ELEMENT") {
1286 if ($needed{"pull_$t->{NAME}"}) {
1287 $needed{"pull_$e->{DATA}->{TYPE}"} = 1;
1289 if ($needed{"push_$t->{NAME}"}) {
1290 $needed{"push_$e->{DATA}->{TYPE}"} = 1;
1297 #####################################################################
1298 # work out what parse functions are needed
1301 my($interface) = shift;
1302 my($data) = $interface->{DATA};
1303 foreach my $d (@{$data}) {
1304 ($d->{TYPE} eq "FUNCTION") &&
1307 foreach my $d (reverse @{$data}) {
1308 ($d->{TYPE} eq "TYPEDEF") &&
1314 #####################################################################
1315 # parse a parsed IDL structure back into an IDL file
1319 my($filename) = shift;
1321 open(IDL, ">$filename") || die "can't open $filename";
1323 pidl "/* parser auto-generated by pidl */\n\n";
1324 pidl "#include \"includes.h\"\n\n";
1325 foreach my $x (@{$idl}) {
1326 if ($x->{TYPE} eq "INTERFACE") {