1 ###################################################
2 # Samba4 NDR parser generator for IDL structures
3 # Copyright tridge@samba.org 2000-2003
4 # Copyright tpot@samba.org 2001
5 # Copyright jelmer@samba.org 2004-2005
6 # released under the GNU GPL
17 sub RegisterPrimitives()
37 "error_status_t" => 4,
46 foreach my $k (keys %type_alignments) {
52 ALIGN => $type_alignments{$k}
62 if (my $dt = $typedefs{$type}->{DATA}->{TYPE}) {
63 return 1 if ($dt eq "SCALAR" or $dt eq "ENUM" or $dt eq "BITMAP");
73 return undef unless $e->{POINTERS};
75 return "ref" if (util::has_property($e, "ref"));
76 return "ptr" if (util::has_property($e, "ptr"));
77 return "unique" if (util::has_property($e, "unique"));
78 return "relative" if (util::has_property($e, "relative"));
83 # determine if an element needs a reference pointer on the wire
84 # in its NDR representation
85 sub need_wire_pointer($)
90 return 0 unless ($pt = pointer_type($e));
99 # determine if an element is a pure scalar. pure scalars do not
100 # have a "buffers" section in NDR
101 sub is_pure_scalar($)
104 if (util::has_property($e, "ref")) {
107 if (is_scalar_type($e->{TYPE}) &&
109 !util::array_size($e)) {
115 # see if a variable needs to be allocated by the NDR subsystem on pull
120 if (util::has_property($e, "ref")) {
124 if ($e->{POINTERS} || util::array_size($e)) {
132 # determine the C prefix used to refer to a variable when passing to a push
133 # function. This will be '*' for pointers to scalar types, '' for scalar
134 # types and normal pointers and '&' for pass-by-reference structures
139 if ($e->{TYPE} =~ "string") {
143 if (is_scalar_type($e->{TYPE}) &&
147 if (!is_scalar_type($e->{TYPE}) &&
149 !util::array_size($e)) {
156 # determine the C prefix used to refer to a variable when passing to a pull
162 if (!$e->{POINTERS} && !util::array_size($e)) {
166 if ($e->{TYPE} =~ "string") {
191 $tabs = substr($tabs, 0, -1);
194 ###################################
195 # find a sibling var in a structure
200 my($fn) = $e->{PARENT};
202 if ($name =~ /\*(.*)/) {
206 if ($fn->{TYPE} eq "FUNCTION") {
207 for my $e2 (@{$fn->{ELEMENTS}}) {
208 if ($e2->{NAME} eq $name) {
214 for my $e2 (@{$fn->{ELEMENTS}}) {
215 if ($e2->{NAME} eq $name) {
219 die "invalid sibling '$name'";
222 ####################################################################
223 # work out the name of a size_is() variable
228 my($var_prefix) = shift;
230 my($fn) = $e->{PARENT};
232 if (util::is_constant($size)) {
236 if ($size =~ /ndr->|\(/) {
242 if ($size =~ /\*(.*)/) {
247 if ($fn->{TYPE} ne "FUNCTION") {
248 return $prefix . "r->$size";
251 my $e2 = find_sibling($e, $size);
253 if (util::has_property($e2, "in") && util::has_property($e2, "out")) {
254 return $prefix . "$var_prefix$size";
256 if (util::has_property($e2, "in")) {
257 return $prefix . "r->in.$size";
259 if (util::has_property($e2, "out")) {
260 return $prefix . "r->out.$size";
263 die "invalid variable in $size for element $e->{NAME} in $fn->{NAME}\n";
266 #####################################################################
267 # check that a variable we get from ParseExpr isn't a null pointer
268 sub check_null_pointer($)
271 if ($size =~ /^\*/) {
272 my $size2 = substr($size, 1);
273 pidl "if ($size2 == NULL) return NT_STATUS_INVALID_PARAMETER_MIX;";
277 #####################################################################
278 # check that a variable we get from ParseExpr isn't a null pointer
279 # void return varient
280 sub check_null_pointer_void($)
283 if ($size =~ /^\*/) {
284 my $size2 = substr($size, 1);
285 pidl "if ($size2 == NULL) return;";
290 #####################################################################
291 # work out is a parse function should be declared static or not
295 if ($fn->{TYPE} eq "TYPEDEF") {
296 if (util::has_property($fn, "public")) {
301 if ($fn->{TYPE} eq "FUNCTION") {
302 if (util::has_property($fn, "public")) {
310 ###################################################################
311 # setup any special flags for an element or structure
315 my $flags = util::has_property($e, "flag");
316 if (defined $flags) {
317 pidl "{ uint32_t _flags_save_$e->{TYPE} = ndr->flags;";
318 pidl "ndr_set_flags(&ndr->flags, $flags);";
322 ###################################################################
323 # end any special flags for an element or structure
327 my $flags = util::has_property($e, "flag");
328 if (defined $flags) {
329 pidl "ndr->flags = _flags_save_$e->{TYPE};\n\t}";
333 #####################################################################
334 # work out the correct alignment for a structure or union
335 sub find_largest_alignment($)
340 for my $e (@{$s->{ELEMENTS}}) {
343 if (need_wire_pointer($e)) {
346 $a = align_type($e->{TYPE});
349 $align = $a if ($align < $a);
355 #####################################################################
361 unless (defined($typedefs{$e}) && defined($typedefs{$e}->{DATA}->{TYPE})) {
362 # it must be an external type - all we can do is guess
363 # print "Warning: assuming alignment of unknown type '$e' is 4\n";
367 my $dt = $typedefs{$e}->{DATA};
369 return $dt->{ALIGN} if ($dt->{ALIGN});
370 return $typefamily{$dt->{TYPE}}->{ALIGN}($dt);
373 #####################################################################
374 # parse an array - push side
375 sub ParseArrayPush($$$)
378 my $var_prefix = shift;
379 my $ndr_flags = shift;
381 my $size = ParseExpr($e, util::array_size($e), $var_prefix);
383 if (defined $e->{CONFORMANT_SIZE}) {
384 # the conformant size has already been pushed
385 } elsif (!util::is_inline_array($e)) {
386 # we need to emit the array size
387 pidl "NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, $size));";
390 if (my $length = util::has_property($e, "length_is")) {
391 $length = ParseExpr($e, $length, $var_prefix);
392 pidl "NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0));";
393 pidl "NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, $length));";
397 if (is_scalar_type($e->{TYPE})) {
398 pidl "NDR_CHECK(ndr_push_array_$e->{TYPE}(ndr, $ndr_flags, $var_prefix$e->{NAME}, $size));";
400 pidl "NDR_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}));";
404 #####################################################################
406 sub ParseArrayPrint($$)
409 my $var_prefix = shift;
410 my $size = ParseExpr($e, util::array_size($e), $var_prefix);
411 my $length = util::has_property($e, "length_is");
413 if (defined $length) {
414 $size = ParseExpr($e, $length, $var_prefix);
417 if (is_scalar_type($e->{TYPE})) {
418 pidl "ndr_print_array_$e->{TYPE}(ndr, \"$e->{NAME}\", $var_prefix$e->{NAME}, $size);";
420 pidl "ndr_print_array(ndr, \"$e->{NAME}\", $var_prefix$e->{NAME}, sizeof($var_prefix$e->{NAME}\[0]), $size, (ndr_print_fn_t)ndr_print_$e->{TYPE});";
424 #####################################################################
425 # check the size_is and length_is constraints
426 sub CheckArraySizes($$)
429 my $var_prefix = shift;
431 if (!defined $e->{CONFORMANT_SIZE} &&
432 util::has_property($e, "size_is")) {
433 my $size = ParseExpr($e, util::array_size($e), $var_prefix);
434 pidl "if ($var_prefix$e->{NAME}) {";
436 check_null_pointer($size);
437 pidl "NDR_CHECK(ndr_check_array_size(ndr, (void*)&$var_prefix$e->{NAME}, $size));";
442 if (my $length = util::has_property($e, "length_is")) {
443 $length = ParseExpr($e, $length, $var_prefix);
444 pidl "if ($var_prefix$e->{NAME}) {";
446 check_null_pointer($length);
447 pidl "NDR_CHECK(ndr_check_array_length(ndr, (void*)&$var_prefix$e->{NAME}, $length));";
453 #####################################################################
454 # parse an array - pull side
455 sub ParseArrayPull($$$)
458 my $var_prefix = shift;
459 my $ndr_flags = shift;
461 my $size = ParseExpr($e, util::array_size($e), $var_prefix);
462 my $alloc_size = $size;
464 # if this is a conformant array then we use that size to allocate, and make sure
465 # we allocate enough to pull the elements
466 if (defined $e->{CONFORMANT_SIZE}) {
467 $alloc_size = $e->{CONFORMANT_SIZE};
468 check_null_pointer($size);
469 pidl "if ($size > $alloc_size) {";
471 pidl "return ndr_pull_error(ndr, NDR_ERR_CONFORMANT_SIZE, \"Bad conformant size %u should be %u\", $alloc_size, $size);";
474 } elsif (!util::is_inline_array($e)) {
475 if ($var_prefix =~ /^r->out/ && $size =~ /^\*r->in/) {
476 my $size2 = substr($size, 1);
477 pidl "if (ndr->flags & LIBNDR_FLAG_REF_ALLOC) { NDR_ALLOC(ndr, $size2); }";
480 # non fixed arrays encode the size just before the array
481 pidl "NDR_CHECK(ndr_pull_array_size(ndr, &$var_prefix$e->{NAME}));";
482 $alloc_size = "ndr_get_array_size(ndr, &$var_prefix$e->{NAME})";
485 if ((need_alloc($e) && !util::is_fixed_array($e)) ||
486 ($var_prefix eq "r->in." && util::has_property($e, "ref"))) {
487 if (!util::is_inline_array($e) || $ndr_flags eq "NDR_SCALARS") {
488 pidl "NDR_ALLOC_N(ndr, $var_prefix$e->{NAME}, $alloc_size);";
492 if (($var_prefix eq "r->out." && util::has_property($e, "ref"))) {
493 if (!util::is_inline_array($e) || $ndr_flags eq "NDR_SCALARS") {
494 pidl "if (ndr->flags & LIBNDR_FLAG_REF_ALLOC) {";
496 pidl "NDR_ALLOC_N(ndr, $var_prefix$e->{NAME}, $alloc_size);";
502 if (my $length = util::has_property($e, "length_is")) {
503 pidl "NDR_CHECK(ndr_pull_array_length(ndr, &$var_prefix$e->{NAME}));";
504 $size = "ndr_get_array_length(ndr, &$var_prefix$e->{NAME})";
507 check_null_pointer($size);
508 if (is_scalar_type($e->{TYPE})) {
509 pidl "NDR_CHECK(ndr_pull_array_$e->{TYPE}(ndr, $ndr_flags, $var_prefix$e->{NAME}, $size));";
511 pidl "NDR_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}));";
515 #####################################################################
516 # parse scalars in a structure element
517 sub ParseElementPushScalar($$$)
520 my($var_prefix) = shift;
521 my($ndr_flags) = shift;
522 my $cprefix = c_push_prefix($e);
523 my $sub_size = util::has_property($e, "subcontext");
527 if (my $value = util::has_property($e, "value")) {
528 pidl "$cprefix$var_prefix$e->{NAME} = $value;";
531 if (util::has_property($e, "relative")) {
532 pidl "NDR_CHECK(ndr_push_relative_ptr1(ndr, $var_prefix$e->{NAME}));";
533 } elsif (util::is_inline_array($e)) {
534 ParseArrayPush($e, "r->", "NDR_SCALARS");
535 } elsif (need_wire_pointer($e)) {
536 pidl "NDR_CHECK(ndr_push_unique_ptr(ndr, $var_prefix$e->{NAME}));";
537 } elsif (need_alloc($e)) {
538 # no scalar component
539 } elsif (my $switch = util::has_property($e, "switch_is")) {
540 ParseElementPushSwitch($e, $var_prefix, $ndr_flags, $switch);
541 } elsif (defined $sub_size) {
542 pidl "NDR_CHECK(ndr_push_subcontext_flags_fn(ndr, $sub_size, $cprefix$var_prefix$e->{NAME}, (ndr_push_flags_fn_t) ndr_push_$e->{TYPE}));";
544 pidl "NDR_CHECK(ndr_push_$e->{TYPE}(ndr, $ndr_flags, $cprefix$var_prefix$e->{NAME}));";
550 #####################################################################
551 # print scalars in a structure element
552 sub ParseElementPrintScalar($$)
555 my($var_prefix) = shift;
556 my $cprefix = c_push_prefix($e);
558 if (util::has_property($e, "noprint")) {
562 if (my $value = util::has_property($e, "value")) {
563 pidl "if (ndr->flags & LIBNDR_PRINT_SET_VALUES) {";
565 pidl "$cprefix$var_prefix$e->{NAME} = $value;";
570 if (util::is_fixed_array($e)) {
571 ParseElementPrintBuffer($e, $var_prefix);
572 } elsif ($e->{POINTERS} || util::array_size($e)) {
573 pidl "ndr_print_ptr(ndr, \"$e->{NAME}\", $var_prefix$e->{NAME});";
574 pidl "ndr->depth++;";
575 ParseElementPrintBuffer($e, $var_prefix);
576 pidl "ndr->depth--;";
577 } elsif (my $switch = util::has_property($e, "switch_is")) {
578 ParseElementPrintSwitch($e, $var_prefix, $switch);
580 pidl "ndr_print_$e->{TYPE}(ndr, \"$e->{NAME}\", $cprefix$var_prefix$e->{NAME});";
584 #####################################################################
585 # parse scalars in a structure element - pull size
586 sub ParseElementPullSwitch($$$$)
589 my($var_prefix) = shift;
590 my($ndr_flags) = shift;
592 my $switch_var = ParseExpr($e, $switch, $var_prefix);
594 my $cprefix = c_pull_prefix($e);
596 my $utype = $typedefs{$e->{TYPE}};
598 check_null_pointer($switch_var);
600 if (!defined $utype ||
601 !util::has_property($utype, "nodiscriminant")) {
602 my $e2 = find_sibling($e, $switch);
603 my $type_decl = util::map_type($e2->{TYPE});
604 pidl "if (($ndr_flags) & NDR_SCALARS) {";
606 if ($typedefs{$e2->{TYPE}}->{DATA}->{TYPE} eq "ENUM") {
607 $type_decl = util::enum_type_decl($e2);
608 } elsif ($typedefs{$e2->{TYPE}}->{DATA}->{TYPE} eq "BITMAP") {
609 $type_decl = util::bitmap_type_decl($e2);
611 pidl "$type_decl _level;";
612 pidl "NDR_CHECK(ndr_pull_$e2->{TYPE}(ndr, NDR_SCALARS, &_level));";
613 if ($switch_var =~ /r->in/) {
614 pidl "if (!(ndr->flags & LIBNDR_FLAG_REF_ALLOC) && _level != $switch_var) {";
617 pidl "if (_level != $switch_var) {";
620 pidl "return ndr_pull_error(ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value %u in $e->{NAME}\", _level);";
622 if ($switch_var =~ /r->/) {
623 pidl "} else { $switch_var = _level; }";
631 my $sub_size = util::has_property($e, "subcontext");
632 if (defined $sub_size) {
633 pidl "if (($ndr_flags) & NDR_SCALARS) {";
635 pidl "NDR_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}));";
639 pidl "NDR_CHECK(ndr_pull_$e->{TYPE}(ndr, $ndr_flags, $switch_var, $cprefix$var_prefix$e->{NAME}));";
645 #####################################################################
646 # push switch element
647 sub ParseElementPushSwitch($$$$)
650 my($var_prefix) = shift;
651 my($ndr_flags) = shift;
653 my $switch_var = ParseExpr($e, $switch, $var_prefix);
654 my $cprefix = c_push_prefix($e);
656 check_null_pointer($switch_var);
658 my $utype = $typedefs{$e->{TYPE}};
659 if (!defined $utype ||
660 !util::has_property($utype, "nodiscriminant")) {
661 my $e2 = find_sibling($e, $switch);
662 pidl "if (($ndr_flags) & NDR_SCALARS) {";
664 pidl "NDR_CHECK(ndr_push_$e2->{TYPE}(ndr, NDR_SCALARS, $switch_var));";
669 my $sub_size = util::has_property($e, "subcontext");
670 if (defined $sub_size) {
671 pidl "if(($ndr_flags) & NDR_SCALARS) {";
673 pidl "NDR_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}));";
677 pidl "NDR_CHECK(ndr_push_$e->{TYPE}(ndr, $ndr_flags, $switch_var, $cprefix$var_prefix$e->{NAME}));";
681 #####################################################################
682 # print scalars in a structure element
683 sub ParseElementPrintSwitch($$$)
686 my($var_prefix) = shift;
688 my $switch_var = ParseExpr($e, $switch, $var_prefix);
689 my $cprefix = c_push_prefix($e);
691 check_null_pointer_void($switch_var);
693 pidl "ndr_print_$e->{TYPE}(ndr, \"$e->{NAME}\", $switch_var, $cprefix$var_prefix$e->{NAME});";
697 #####################################################################
698 # parse scalars in a structure element - pull size
699 sub ParseElementPullScalar($$$)
702 my($var_prefix) = shift;
703 my($ndr_flags) = shift;
704 my $cprefix = c_pull_prefix($e);
705 my $sub_size = util::has_property($e, "subcontext");
709 if (util::is_inline_array($e)) {
710 ParseArrayPull($e, "r->", "NDR_SCALARS");
711 } elsif (need_wire_pointer($e)) {
712 pidl "NDR_CHECK(ndr_pull_unique_ptr(ndr, &_ptr_$e->{NAME}));";
713 pidl "if (_ptr_$e->{NAME}) {";
715 pidl "NDR_ALLOC(ndr, $var_prefix$e->{NAME});";
716 if (util::has_property($e, "relative")) {
717 pidl "NDR_CHECK(ndr_pull_relative_ptr1(ndr, $var_prefix$e->{NAME}, _ptr_$e->{NAME}));";
722 pidl "$var_prefix$e->{NAME} = NULL;";
725 } elsif (need_alloc($e)) {
726 # no scalar component
727 } elsif (my $switch = util::has_property($e, "switch_is")) {
728 ParseElementPullSwitch($e, $var_prefix, $ndr_flags, $switch);
729 } elsif (defined $sub_size) {
730 pidl "NDR_CHECK(ndr_pull_subcontext_flags_fn(ndr, $sub_size, $cprefix$var_prefix$e->{NAME}, (ndr_pull_flags_fn_t) ndr_pull_$e->{TYPE}));";
732 pidl "NDR_CHECK(ndr_pull_$e->{TYPE}(ndr, $ndr_flags, $cprefix$var_prefix$e->{NAME}));";
734 if (my $range = util::has_property($e, "range")) {
735 my ($low, $high) = split(/ /, $range, 2);
736 pidl "if ($var_prefix$e->{NAME} < $low || $var_prefix$e->{NAME} > $high) {";
738 pidl "return ndr_pull_error(ndr, NDR_ERR_RANGE, \"value out of range\");";
746 #####################################################################
747 # parse buffers in a structure element
748 sub ParseElementPushBuffer($$$)
751 my($var_prefix) = shift;
752 my($ndr_flags) = shift;
753 my $cprefix = c_push_prefix($e);
754 my $sub_size = util::has_property($e, "subcontext");
756 if (is_pure_scalar($e)) {
762 if (need_wire_pointer($e)) {
763 pidl "if ($var_prefix$e->{NAME}) {";
765 if (util::has_property($e, "relative")) {
766 pidl "NDR_CHECK(ndr_push_relative_ptr2(ndr, $var_prefix$e->{NAME}));";
770 if (util::is_inline_array($e)) {
771 ParseArrayPush($e, "r->", "NDR_BUFFERS");
772 } elsif (util::array_size($e)) {
773 ParseArrayPush($e, "r->", "NDR_SCALARS|NDR_BUFFERS");
774 } elsif (my $switch = util::has_property($e, "switch_is")) {
775 if ($e->{POINTERS}) {
776 ParseElementPushSwitch($e, $var_prefix, "NDR_BUFFERS|NDR_SCALARS", $switch);
778 ParseElementPushSwitch($e, $var_prefix, "NDR_BUFFERS", $switch);
780 } elsif (defined $sub_size) {
781 if ($e->{POINTERS}) {
782 pidl "NDR_CHECK(ndr_push_subcontext_flags_fn(ndr, $sub_size, $cprefix$var_prefix$e->{NAME}, (ndr_push_flags_fn_t) ndr_push_$e->{TYPE}));";
784 } elsif ($e->{POINTERS}) {
785 pidl "NDR_CHECK(ndr_push_$e->{TYPE}(ndr, NDR_SCALARS|NDR_BUFFERS, $cprefix$var_prefix$e->{NAME}));";
787 pidl "NDR_CHECK(ndr_push_$e->{TYPE}(ndr, $ndr_flags, $cprefix$var_prefix$e->{NAME}));";
790 if (need_wire_pointer($e)) {
798 #####################################################################
799 # print buffers in a structure element
800 sub ParseElementPrintBuffer($$)
803 my($var_prefix) = shift;
804 my $cprefix = c_push_prefix($e);
806 if (need_wire_pointer($e)) {
807 pidl "if ($var_prefix$e->{NAME}) {";
811 if (util::array_size($e)) {
812 ParseArrayPrint($e, $var_prefix)
813 } elsif (my $switch = util::has_property($e, "switch_is")) {
814 ParseElementPrintSwitch($e, $var_prefix, $switch);
816 pidl "ndr_print_$e->{TYPE}(ndr, \"$e->{NAME}\", $cprefix$var_prefix$e->{NAME});";
819 if (need_wire_pointer($e)) {
826 #####################################################################
827 # parse buffers in a structure element - pull side
828 sub ParseElementPullBuffer($$$)
831 my($var_prefix) = shift;
832 my($ndr_flags) = shift;
833 my $cprefix = c_pull_prefix($e);
834 my $sub_size = util::has_property($e, "subcontext");
836 if (is_pure_scalar($e)) {
842 if (need_wire_pointer($e)) {
843 pidl "if ($var_prefix$e->{NAME}) {";
845 if (util::has_property($e, "relative")) {
846 pidl "struct ndr_pull_save _relative_save;";
847 pidl "ndr_pull_save(ndr, &_relative_save);";
848 pidl "NDR_CHECK(ndr_pull_relative_ptr2(ndr, $var_prefix$e->{NAME}));";
852 if (util::is_inline_array($e)) {
853 ParseArrayPull($e, "r->", "NDR_BUFFERS");
854 } elsif (util::array_size($e)) {
855 ParseArrayPull($e, "r->", "NDR_SCALARS|NDR_BUFFERS");
856 } elsif (my $switch = util::has_property($e, "switch_is")) {
857 if ($e->{POINTERS}) {
858 ParseElementPullSwitch($e, $var_prefix, "NDR_SCALARS|NDR_BUFFERS", $switch);
860 ParseElementPullSwitch($e, $var_prefix, "NDR_BUFFERS", $switch);
862 } elsif (defined $sub_size) {
863 if ($e->{POINTERS}) {
864 pidl "NDR_CHECK(ndr_pull_subcontext_flags_fn(ndr, $sub_size, $cprefix$var_prefix$e->{NAME}, (ndr_pull_flags_fn_t) ndr_pull_$e->{TYPE}));";
866 } elsif ($e->{POINTERS}) {
867 pidl "NDR_CHECK(ndr_pull_$e->{TYPE}(ndr, NDR_SCALARS|NDR_BUFFERS, $cprefix$var_prefix$e->{NAME}));";
869 pidl "NDR_CHECK(ndr_pull_$e->{TYPE}(ndr, $ndr_flags, $cprefix$var_prefix$e->{NAME}));";
872 if (need_wire_pointer($e)) {
873 if (util::has_property($e, "relative")) {
874 pidl "ndr_pull_restore(ndr, &_relative_save);";
883 #####################################################################
885 sub ParseStructPush($)
889 if (! defined $struct->{ELEMENTS}) {
893 start_flags($struct);
895 # see if the structure contains a conformant array. If it
896 # does, then it must be the last element of the structure, and
897 # we need to push the conformant length early, as it fits on
898 # the wire before the structure (and even before the structure
900 my $e = $struct->{ELEMENTS}[-1];
901 if (defined $e->{ARRAY_LEN} && $e->{ARRAY_LEN} eq "*") {
902 my $size = ParseExpr($e, util::array_size($e), "r->");
903 $e->{CONFORMANT_SIZE} = $size;
904 check_null_pointer($size);
905 pidl "NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, $size));";
908 if (defined $e->{TYPE} && $e->{TYPE} eq "string"
909 && util::property_matches($e, "flag", ".*LIBNDR_FLAG_STR_CONFORMANT.*")) {
910 pidl "NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_string_array_size(ndr, r->$e->{NAME})));";
913 pidl "if (!(ndr_flags & NDR_SCALARS)) goto buffers;";
915 pidl "NDR_CHECK(ndr_push_struct_start(ndr));";
917 my $align = find_largest_alignment($struct);
918 pidl "NDR_CHECK(ndr_push_align(ndr, $align));";
920 foreach my $e (@{$struct->{ELEMENTS}}) {
921 ParseElementPushScalar($e, "r->", "NDR_SCALARS");
925 pidl "if (!(ndr_flags & NDR_BUFFERS)) goto done;";
926 foreach my $e (@{$struct->{ELEMENTS}}) {
927 ParseElementPushBuffer($e, "r->", "NDR_BUFFERS");
930 pidl "ndr_push_struct_end(ndr);";
938 #####################################################################
939 # generate a push function for an enum
943 my($type_fn) = util::enum_type_fn($enum);
947 pidl "NDR_CHECK(ndr_push_$type_fn(ndr, NDR_SCALARS, r));";
952 #####################################################################
953 # generate a pull function for an enum
957 my($type_fn) = util::enum_type_fn($enum);
958 my($type_v_decl) = util::map_type(util::enum_type_fn($enum));
960 pidl "$type_v_decl v;";
962 pidl "NDR_CHECK(ndr_pull_$type_fn(ndr, NDR_SCALARS, &v));";
968 #####################################################################
969 # generate a print function for an enum
970 sub ParseEnumPrint($)
974 pidl "const char *val = NULL;";
981 my $els = \@{$enum->{ELEMENTS}};
982 foreach my $i (0 .. $#{$els}) {
985 if ($e =~ /^(.*)=/) {
988 pidl "case $e: val = \"$e\"; break;";
994 pidl "ndr_print_enum(ndr, name, \"$enum->{TYPE}\", val, r);";
999 $typefamily{ENUM} = {
1000 PUSH_FN_BODY => \&ParseEnumPush,
1001 PULL_FN_BODY => \&ParseEnumPull,
1002 PRINT_FN_BODY => \&ParseEnumPrint,
1003 ALIGN => sub { return align_type(util::enum_type_fn(shift)); }
1006 #####################################################################
1007 # generate a push function for a bitmap
1008 sub ParseBitmapPush($)
1010 my($bitmap) = shift;
1011 my($type_fn) = util::bitmap_type_fn($bitmap);
1013 start_flags($bitmap);
1015 pidl "NDR_CHECK(ndr_push_$type_fn(ndr, NDR_SCALARS, r));";
1020 #####################################################################
1021 # generate a pull function for an bitmap
1022 sub ParseBitmapPull($)
1024 my($bitmap) = shift;
1025 my($type_fn) = util::bitmap_type_fn($bitmap);
1026 my($type_decl) = util::bitmap_type_decl($bitmap);
1028 pidl "$type_decl v;";
1029 start_flags($bitmap);
1030 pidl "NDR_CHECK(ndr_pull_$type_fn(ndr, NDR_SCALARS, &v));";
1036 #####################################################################
1037 # generate a print function for an bitmap
1038 sub ParseBitmapPrintElement($$)
1041 my($bitmap) = shift;
1042 my($type_decl) = util::bitmap_type_decl($bitmap);
1043 my($type_fn) = util::bitmap_type_fn($bitmap);
1044 my($name) = $bitmap->{PARENT}->{NAME};
1047 if ($e =~ /^(\w+) .*$/) {
1050 die "Bitmap: \"$name\" invalid Flag: \"$e\"";
1053 pidl "ndr_print_bitmap_flag(ndr, sizeof($type_decl), \"$flag\", $flag, r);";
1056 #####################################################################
1057 # generate a print function for an bitmap
1058 sub ParseBitmapPrint($)
1060 my($bitmap) = shift;
1061 my($type_decl) = util::bitmap_type_decl($bitmap);
1062 my($type_fn) = util::bitmap_type_fn($bitmap);
1064 start_flags($bitmap);
1066 pidl "ndr_print_$type_fn(ndr, name, r);";
1068 pidl "ndr->depth++;";
1069 foreach my $e (@{$bitmap->{ELEMENTS}}) {
1070 ParseBitmapPrintElement($e, $bitmap);
1072 pidl "ndr->depth--;";
1077 $typefamily{BITMAP} = {
1078 PUSH_FN_BODY => \&ParseBitmapPush,
1079 PULL_FN_BODY => \&ParseBitmapPull,
1080 PRINT_FN_BODY => \&ParseBitmapPrint,
1081 ALIGN => sub { return align_type(util::bitmap_type_fn(shift)); }
1084 #####################################################################
1085 # generate a struct print function
1086 sub ParseStructPrint($)
1088 my($struct) = shift;
1090 if (! defined $struct->{ELEMENTS}) {
1094 start_flags($struct);
1096 pidl "ndr->depth++;";
1097 foreach my $e (@{$struct->{ELEMENTS}}) {
1098 ParseElementPrintScalar($e, "r->");
1100 pidl "ndr->depth--;";
1105 #####################################################################
1106 # parse a struct - pull side
1107 sub ParseStructPull($)
1109 my($struct) = shift;
1112 if (! defined $struct->{ELEMENTS}) {
1116 # see if the structure contains a conformant array. If it
1117 # does, then it must be the last element of the structure, and
1118 # we need to pull the conformant length early, as it fits on
1119 # the wire before the structure (and even before the structure
1121 my $e = $struct->{ELEMENTS}[-1];
1122 if (defined $e->{ARRAY_LEN} && $e->{ARRAY_LEN} eq "*") {
1126 if (defined $e->{TYPE} && $e->{TYPE} eq "string"
1127 && util::property_matches($e, "flag", ".*LIBNDR_FLAG_STR_CONFORMANT.*")) {
1131 if (defined $conform_e) {
1133 pidl "uint32_t _conformant_size;";
1134 $conform_e->{CONFORMANT_SIZE} = "_conformant_size";
1137 # declare any internal pointers we need
1138 foreach my $e (@{$struct->{ELEMENTS}}) {
1139 if (need_wire_pointer($e)) {
1140 pidl "uint32_t _ptr_$e->{NAME};";
1144 start_flags($struct);
1146 pidl "if (!(ndr_flags & NDR_SCALARS)) goto buffers;";
1148 pidl "NDR_CHECK(ndr_pull_struct_start(ndr));";
1150 if (defined $conform_e) {
1151 pidl "NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &$conform_e->{CONFORMANT_SIZE}));";
1154 my $align = find_largest_alignment($struct);
1155 pidl "NDR_CHECK(ndr_pull_align(ndr, $align));";
1157 foreach my $e (@{$struct->{ELEMENTS}}) {
1158 ParseElementPullScalar($e, "r->", "NDR_SCALARS");
1162 pidl "if (!(ndr_flags & NDR_BUFFERS)) goto done;";
1163 foreach my $e (@{$struct->{ELEMENTS}}) {
1164 ParseElementPullBuffer($e, "r->", "NDR_BUFFERS");
1167 foreach my $e (@{$struct->{ELEMENTS}}) {
1168 CheckArraySizes($e, "r->");
1171 pidl "ndr_pull_struct_end(ndr);";
1178 #####################################################################
1179 # calculate size of ndr struct
1180 sub ParseStructNdrSize($)
1183 my $static = fn_prefix($t);
1186 pidl "size_t ndr_size_$t->{NAME}(const struct $t->{NAME} *r, int flags)";
1189 if (my $flags = util::has_property($t, "flag")) {
1190 pidl "flags |= $flags;";
1192 pidl "return ndr_size_struct(r, flags, (ndr_push_flags_fn_t)ndr_push_$t->{NAME});";
1198 $typefamily{STRUCT} = {
1199 PUSH_FN_BODY => \&ParseStructPush,
1200 PULL_FN_BODY => \&ParseStructPull,
1201 PRINT_FN_BODY => \&ParseStructPrint,
1202 SIZE_FN => \&ParseStructNdrSize,
1203 ALIGN => \&find_largest_alignment
1206 #####################################################################
1207 # calculate size of ndr struct
1208 sub ParseUnionNdrSize($)
1211 my $static = fn_prefix($t);
1214 pidl "size_t ndr_size_$t->{NAME}(const union $t->{NAME} *r, int level, int flags)";
1217 if (my $flags = util::has_property($t, "flag")) {
1218 pidl "flags |= $flags;";
1220 pidl "return ndr_size_union(r, flags, level, (ndr_push_union_fn_t)ndr_push_$t->{NAME});";
1226 #####################################################################
1227 # parse a union - push side
1228 sub ParseUnionPush($)
1231 my $have_default = 0;
1235 pidl "if (!(ndr_flags & NDR_SCALARS)) goto buffers;";
1237 pidl "NDR_CHECK(ndr_push_struct_start(ndr));";
1239 # my $align = union_alignment($e);
1240 # pidl "NDR_CHECK(ndr_push_align(ndr, $align));";
1242 pidl "switch (level) {";
1244 foreach my $el (@{$e->{ELEMENTS}}) {
1245 if (util::has_property($el, "default")) {
1249 pidl "case $el->{PROPERTIES}->{case}:";
1252 if ($el->{TYPE} ne "EMPTY") {
1254 ParseElementPushScalar($el, "r->", "NDR_SCALARS");
1260 if (! $have_default) {
1262 pidl "\treturn ndr_push_error(ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value \%u\", level);";
1267 pidl "if (!(ndr_flags & NDR_BUFFERS)) goto done;";
1268 pidl "switch (level) {";
1270 foreach my $el (@{$e->{ELEMENTS}}) {
1271 if (util::has_property($el, "default")) {
1274 pidl "case $el->{PROPERTIES}->{case}:";
1276 if ($el->{TYPE} ne "EMPTY") {
1278 ParseElementPushBuffer($el, "r->", "NDR_BUFFERS");
1284 if (! $have_default) {
1286 pidl "\treturn ndr_push_error(ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value \%u\", level);";
1290 pidl "ndr_push_struct_end(ndr);";
1295 #####################################################################
1297 sub ParseUnionPrint($)
1300 my $have_default = 0;
1304 pidl "switch (level) {";
1306 foreach my $el (@{$e->{ELEMENTS}}) {
1307 if (util::has_property($el, "default")) {
1311 pidl "case $el->{PROPERTIES}->{case}:";
1313 if ($el->{TYPE} ne "EMPTY") {
1315 ParseElementPrintScalar($el, "r->");
1321 if (! $have_default) {
1323 pidl "\tndr_print_bad_level(ndr, name, level);";
1331 #####################################################################
1332 # parse a union - pull side
1333 sub ParseUnionPull($)
1336 my $have_default = 0;
1340 pidl "if (!(ndr_flags & NDR_SCALARS)) goto buffers;";
1342 pidl "NDR_CHECK(ndr_pull_struct_start(ndr));";
1344 # my $align = union_alignment($e);
1345 # pidl "\tNDR_CHECK(ndr_pull_align(ndr, $align));\n";
1347 pidl "switch (level) {";
1349 foreach my $el (@{$e->{ELEMENTS}}) {
1350 if (util::has_property($el, "default")) {
1354 pidl "case $el->{PROPERTIES}->{case}: {";
1356 if ($el->{TYPE} ne "EMPTY") {
1358 if ($el->{POINTERS}) {
1359 pidl "uint32_t _ptr_$el->{NAME};";
1361 ParseElementPullScalar($el, "r->", "NDR_SCALARS");
1367 if (! $have_default) {
1369 pidl "\treturn ndr_pull_error(ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value \%u\", level);";
1374 pidl "if (!(ndr_flags & NDR_BUFFERS)) goto done;";
1375 pidl "switch (level) {";
1377 foreach my $el (@{$e->{ELEMENTS}}) {
1378 if (util::has_property($el, "default")) {
1381 pidl "case $el->{PROPERTIES}->{case}:";
1383 if ($el->{TYPE} ne "EMPTY") {
1385 ParseElementPullBuffer($el, "r->", "NDR_BUFFERS");
1391 if (! $have_default) {
1393 pidl "\treturn ndr_pull_error(ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value \%u\", level);";
1397 pidl "ndr_pull_struct_end(ndr);";
1402 $typefamily{UNION} = {
1403 PUSH_FN_BODY => \&ParseUnionPush,
1404 PULL_FN_BODY => \&ParseUnionPull,
1405 PRINT_FN_BODY => \&ParseUnionPrint,
1406 SIZE_FN => \&ParseUnionNdrSize,
1407 ALIGN => \&find_largest_alignment
1411 #####################################################################
1412 # parse a typedef - push side
1413 sub ParseTypedefPush($)
1416 my $static = fn_prefix($e);
1418 if (! needed::is_needed("push_$e->{NAME}")) {
1419 # print "push_$e->{NAME} not needed\n";
1424 if ($e->{DATA}->{TYPE} eq "STRUCT") {
1425 $args = "struct ndr_push *ndr, int ndr_flags, struct $e->{NAME} *r";
1428 if ($e->{DATA}->{TYPE} eq "UNION") {
1429 $args = "struct ndr_push *ndr, int ndr_flags, int level, union $e->{NAME} *r";
1432 if ($e->{DATA}->{TYPE} eq "ENUM") {
1433 $args = "struct ndr_push *ndr, int ndr_flags, enum $e->{NAME} r";
1436 if ($e->{DATA}->{TYPE} eq "BITMAP") {
1437 my $type_decl = util::bitmap_type_decl($e->{DATA});
1438 $args = "struct ndr_push *ndr, int ndr_flags, $type_decl r";
1441 pidl $static . "NTSTATUS ndr_push_$e->{NAME}($args)";
1445 $typefamily{$e->{DATA}->{TYPE}}->{PUSH_FN_BODY}($e->{DATA});
1446 pidl "return NT_STATUS_OK;";
1452 #####################################################################
1453 # parse a typedef - pull side
1454 sub ParseTypedefPull($)
1457 my $static = fn_prefix($e);
1459 if (! needed::is_needed("pull_$e->{NAME}")) {
1460 # print "pull_$e->{NAME} not needed\n";
1466 if ($e->{DATA}->{TYPE} eq "STRUCT") {
1467 $args = "struct ndr_pull *ndr, int ndr_flags, struct $e->{NAME} *r";
1470 if ($e->{DATA}->{TYPE} eq "UNION") {
1471 $args = "struct ndr_pull *ndr, int ndr_flags, int level, union $e->{NAME} *r";
1474 if ($e->{DATA}->{TYPE} eq "ENUM") {
1475 $args = "struct ndr_pull *ndr, int ndr_flags, enum $e->{NAME} *r";
1478 if ($e->{DATA}->{TYPE} eq "BITMAP") {
1479 my $type_decl = util::bitmap_type_decl($e->{DATA});
1480 $args = "struct ndr_pull *ndr, int ndr_flags, $type_decl *r";
1483 pidl $static . "NTSTATUS ndr_pull_$e->{NAME}($args)";
1487 $typefamily{$e->{DATA}->{TYPE}}->{PULL_FN_BODY}($e->{DATA});
1488 pidl "return NT_STATUS_OK;";
1494 #####################################################################
1495 # parse a typedef - print side
1496 sub ParseTypedefPrint($)
1500 if ($e->{DATA}->{TYPE} eq "STRUCT") {
1501 pidl "void ndr_print_$e->{NAME}(struct ndr_print *ndr, const char *name, struct $e->{NAME} *r)";
1504 pidl "ndr_print_struct(ndr, name, \"$e->{NAME}\");";
1507 if ($e->{DATA}->{TYPE} eq "UNION") {
1508 pidl "void ndr_print_$e->{NAME}(struct ndr_print *ndr, const char *name, int level, union $e->{NAME} *r)";
1511 pidl "ndr_print_union(ndr, name, level, \"$e->{NAME}\");";
1514 if ($e->{DATA}->{TYPE} eq "ENUM") {
1515 pidl "void ndr_print_$e->{NAME}(struct ndr_print *ndr, const char *name, enum $e->{NAME} r)";
1520 if ($e->{DATA}->{TYPE} eq "BITMAP") {
1521 my $type_decl = util::bitmap_type_decl($e->{DATA});
1522 pidl "void ndr_print_$e->{NAME}(struct ndr_print *ndr, const char *name, $type_decl r)";
1527 $typefamily{$e->{DATA}->{TYPE}}->{PRINT_FN_BODY}($e->{DATA});
1532 #####################################################################
1533 ## calculate the size of a structure
1534 sub ParseTypedefNdrSize($)
1537 if (! needed::is_needed("ndr_size_$t->{NAME}")) {
1541 $typefamily{$t->{DATA}->{TYPE}}->{SIZE_FN}($t);
1544 #####################################################################
1545 # parse a function - print side
1546 sub ParseFunctionPrint($)
1550 pidl "void ndr_print_$fn->{NAME}(struct ndr_print *ndr, const char *name, int flags, struct $fn->{NAME} *r)";
1553 pidl "ndr_print_struct(ndr, name, \"$fn->{NAME}\");";
1554 pidl "ndr->depth++;";
1556 pidl "if (flags & NDR_SET_VALUES) {";
1557 pidl "\tndr->flags |= LIBNDR_PRINT_SET_VALUES;";
1560 pidl "if (flags & NDR_IN) {";
1562 pidl "ndr_print_struct(ndr, \"in\", \"$fn->{NAME}\");";
1563 pidl "ndr->depth++;";
1565 foreach my $e (@{$fn->{ELEMENTS}}) {
1566 if (util::has_property($e, "in")) {
1567 ParseElementPrintScalar($e, "r->in.");
1570 pidl "ndr->depth--;";
1574 pidl "if (flags & NDR_OUT) {";
1576 pidl "ndr_print_struct(ndr, \"out\", \"$fn->{NAME}\");";
1577 pidl "ndr->depth++;";
1578 foreach my $e (@{$fn->{ELEMENTS}}) {
1579 if (util::has_property($e, "out")) {
1580 ParseElementPrintScalar($e, "r->out.");
1583 if ($fn->{RETURN_TYPE} && $fn->{RETURN_TYPE} ne "void") {
1585 $cprefix = "" if (is_scalar_type($fn->{RETURN_TYPE})) ; # FIXME: Should really use util::c_push_prefix here
1586 pidl "ndr_print_$fn->{RETURN_TYPE}(ndr, \"result\", $cprefix"."r->out.result);";
1588 pidl "ndr->depth--;";
1592 pidl "ndr->depth--;";
1598 #####################################################################
1599 # parse a function element
1600 sub ParseFunctionElementPush($$)
1605 if (util::array_size($e)) {
1606 if (need_wire_pointer($e)) {
1607 pidl "NDR_CHECK(ndr_push_unique_ptr(ndr, r->$inout.$e->{NAME}));";
1608 pidl "if (r->$inout.$e->{NAME}) {";
1610 ParseArrayPush($e, "r->$inout.", "NDR_SCALARS|NDR_BUFFERS");
1614 ParseArrayPush($e, "r->$inout.", "NDR_SCALARS|NDR_BUFFERS");
1617 ParseElementPushScalar($e, "r->$inout.", "NDR_SCALARS|NDR_BUFFERS");
1619 if ($e->{POINTERS}) {
1620 ParseElementPushBuffer($e, "r->$inout.", "NDR_SCALARS|NDR_BUFFERS");
1625 #####################################################################
1627 sub ParseFunctionPush($)
1630 my $static = fn_prefix($fn);
1632 pidl $static . "NTSTATUS ndr_push_$fn->{NAME}(struct ndr_push *ndr, int flags, struct $fn->{NAME} *r)";
1636 pidl "if (!(flags & NDR_IN)) goto ndr_out;";
1639 foreach my $e (@{$fn->{ELEMENTS}}) {
1640 if (util::has_property($e, "in")) {
1641 ParseFunctionElementPush($e, "in");
1646 pidl "if (!(flags & NDR_OUT)) goto done;";
1649 foreach my $e (@{$fn->{ELEMENTS}}) {
1650 if (util::has_property($e, "out")) {
1651 ParseFunctionElementPush($e, "out");
1655 if ($fn->{RETURN_TYPE} && $fn->{RETURN_TYPE} ne "void") {
1656 pidl "NDR_CHECK(ndr_push_$fn->{RETURN_TYPE}(ndr, NDR_SCALARS, r->out.result));";
1660 pidl "return NT_STATUS_OK;";
1666 #####################################################################
1667 # parse a function element
1668 sub ParseFunctionElementPull($$)
1673 if (util::array_size($e)) {
1674 if (need_wire_pointer($e)) {
1675 pidl "NDR_CHECK(ndr_pull_unique_ptr(ndr, &_ptr_$e->{NAME}));";
1676 pidl "r->$inout.$e->{NAME} = NULL;";
1677 pidl "if (_ptr_$e->{NAME}) {";
1679 } elsif ($inout eq "out" && util::has_property($e, "ref")) {
1680 pidl "if (r->$inout.$e->{NAME}) {";
1686 ParseArrayPull($e, "r->$inout.", "NDR_SCALARS|NDR_BUFFERS");
1690 if ($inout eq "out" && util::has_property($e, "ref")) {
1691 pidl "if (ndr->flags & LIBNDR_FLAG_REF_ALLOC) {";
1692 pidl "\tNDR_ALLOC(ndr, r->out.$e->{NAME});";
1695 if ($inout eq "in" && util::has_property($e, "ref")) {
1696 pidl "NDR_ALLOC(ndr, r->in.$e->{NAME});";
1699 ParseElementPullScalar($e, "r->$inout.", "NDR_SCALARS|NDR_BUFFERS");
1700 if ($e->{POINTERS}) {
1701 ParseElementPullBuffer($e, "r->$inout.", "NDR_SCALARS|NDR_BUFFERS");
1706 ############################################################
1707 # allocate ref variables
1708 sub AllocateRefVars($)
1711 my $asize = util::array_size($e);
1713 # note that if the variable is also an "in"
1714 # variable then we copy the initial value from
1717 if (!defined $asize) {
1718 # its a simple variable
1719 pidl "NDR_ALLOC(ndr, r->out.$e->{NAME});";
1720 if (util::has_property($e, "in")) {
1721 pidl "*r->out.$e->{NAME} = *r->in.$e->{NAME};";
1723 pidl "ZERO_STRUCTP(r->out.$e->{NAME});";
1729 my $size = ParseExpr($e, $asize, "r->out.");
1730 check_null_pointer($size);
1731 pidl "NDR_ALLOC_N(ndr, r->out.$e->{NAME}, $size);";
1732 if (util::has_property($e, "in")) {
1733 pidl "memcpy(r->out.$e->{NAME},r->in.$e->{NAME},$size * sizeof(*r->in.$e->{NAME}));";
1735 pidl "memset(r->out.$e->{NAME}, 0, $size * sizeof(*r->out.$e->{NAME}));";
1739 #####################################################################
1741 sub ParseFunctionPull($)
1744 my $static = fn_prefix($fn);
1746 # pull function args
1747 pidl $static . "NTSTATUS ndr_pull_$fn->{NAME}(struct ndr_pull *ndr, int flags, struct $fn->{NAME} *r)";
1751 # declare any internal pointers we need
1752 foreach my $e (@{$fn->{ELEMENTS}}) {
1753 if (need_wire_pointer($e)) {
1754 pidl "uint32_t _ptr_$e->{NAME};";
1758 pidl "if (!(flags & NDR_IN)) goto ndr_out;";
1761 # auto-init the out section of a structure. I originally argued that
1762 # this was a bad idea as it hides bugs, but coping correctly
1763 # with initialisation and not wiping ref vars is turning
1764 # out to be too tricky (tridge)
1765 foreach my $e (@{$fn->{ELEMENTS}}) {
1766 if (util::has_property($e, "out")) {
1767 pidl "ZERO_STRUCT(r->out);";
1773 foreach my $e (@{$fn->{ELEMENTS}}) {
1774 if (util::has_property($e, "in")) {
1775 ParseFunctionElementPull($e, "in");
1777 # we need to allocate any reference output variables, so that
1778 # a dcerpc backend can be sure they are non-null
1779 if (util::has_property($e, "out") && util::has_property($e, "ref")) {
1780 AllocateRefVars($e);
1784 foreach my $e (@{$fn->{ELEMENTS}}) {
1785 if (util::has_property($e, "in")) {
1786 CheckArraySizes($e, "r->in.");
1791 pidl "if (!(flags & NDR_OUT)) goto done;";
1794 foreach my $e (@{$fn->{ELEMENTS}}) {
1795 if (util::has_property($e, "out")) {
1796 ParseFunctionElementPull($e, "out");
1800 foreach my $e (@{$fn->{ELEMENTS}}) {
1801 if (util::has_property($e, "out")) {
1802 CheckArraySizes($e, "r->out.");
1806 if ($fn->{RETURN_TYPE} && $fn->{RETURN_TYPE} ne "void") {
1807 pidl "NDR_CHECK(ndr_pull_$fn->{RETURN_TYPE}(ndr, NDR_SCALARS, &r->out.result));";
1812 pidl "return NT_STATUS_OK;";
1818 #####################################################################
1819 # produce a function call table
1820 sub FunctionTable($)
1822 my($interface) = shift;
1823 my($data) = $interface->{INHERITED_DATA};
1825 my $uname = uc $interface->{NAME};
1827 foreach my $d (@{$data}) {
1828 if ($d->{TYPE} eq "FUNCTION") { $count++; }
1831 return if ($count == 0);
1833 pidl "static const struct dcerpc_interface_call $interface->{NAME}\_calls[] = {";
1834 foreach my $d (@{$data}) {
1835 if ($d->{TYPE} eq "FUNCTION") {
1837 pidl "\t\t\"$d->{NAME}\",";
1838 pidl "\t\tsizeof(struct $d->{NAME}),";
1839 pidl "\t\t(ndr_push_flags_fn_t) ndr_push_$d->{NAME},";
1840 pidl "\t\t(ndr_pull_flags_fn_t) ndr_pull_$d->{NAME},";
1841 pidl "\t\t(ndr_print_function_t) ndr_print_$d->{NAME}";
1845 pidl "\t{ NULL, 0, NULL, NULL, NULL }";
1849 # If no endpoint is set, default to the interface name as a named pipe
1850 if (! defined $interface->{PROPERTIES}->{endpoint}) {
1851 $interface->{PROPERTIES}->{endpoint} = "\"ncacn_np:[\\\\pipe\\\\" . $interface->{NAME} . "]\"";
1854 my @e = split / /, $interface->{PROPERTIES}->{endpoint};
1855 my $endpoint_count = $#e + 1;
1857 pidl "static const char * const $interface->{NAME}\_endpoint_strings[] = {";
1858 foreach my $ep (@e) {
1864 pidl "static const struct dcerpc_endpoint_list $interface->{NAME}\_endpoints = {";
1865 pidl "\t$endpoint_count, $interface->{NAME}\_endpoint_strings";
1869 pidl "\nconst struct dcerpc_interface_table dcerpc_table_$interface->{NAME} = {";
1870 pidl "\t\"$interface->{NAME}\",";
1871 pidl "\tDCERPC_$uname\_UUID,";
1872 pidl "\tDCERPC_$uname\_VERSION,";
1873 pidl "\tDCERPC_$uname\_HELPSTRING,";
1875 pidl "\t$interface->{NAME}\_calls,";
1876 pidl "\t&$interface->{NAME}\_endpoints";
1880 pidl "static NTSTATUS dcerpc_ndr_$interface->{NAME}_init(void)";
1882 pidl "\treturn librpc_register_interface(&dcerpc_table_$interface->{NAME});";
1887 #####################################################################
1888 # parse the interface definitions
1889 sub ParseInterface($)
1891 my($interface) = shift;
1892 my($data) = $interface->{DATA};
1895 foreach my $d (@{$data}) {
1896 ($d->{TYPE} eq "TYPEDEF") &&
1897 ParseTypedefPush($d);
1898 ($d->{TYPE} eq "FUNCTION") &&
1899 ParseFunctionPush($d);
1903 foreach my $d (@{$data}) {
1904 ($d->{TYPE} eq "TYPEDEF") &&
1905 ParseTypedefPull($d);
1906 ($d->{TYPE} eq "FUNCTION") &&
1907 ParseFunctionPull($d);
1911 foreach my $d (@{$data}) {
1912 if ($d->{TYPE} eq "TYPEDEF" &&
1913 !util::has_property($d, "noprint")) {
1914 ParseTypedefPrint($d);
1916 if ($d->{TYPE} eq "FUNCTION" &&
1917 !util::has_property($d, "noprint")) {
1918 ParseFunctionPrint($d);
1923 foreach my $d (@{$data}) {
1924 ($d->{TYPE} eq "TYPEDEF") &&
1925 ParseTypedefNdrSize($d);
1928 FunctionTable($interface);
1931 sub RegistrationFunction($$)
1934 my $filename = shift;
1936 $filename =~ /.*\/ndr_(.*).c/;
1938 pidl "NTSTATUS dcerpc_$basename\_init(void)";
1941 pidl "NTSTATUS status = NT_STATUS_OK;";
1942 foreach my $interface (@{$idl}) {
1943 next if $interface->{TYPE} ne "INTERFACE";
1945 my $data = $interface->{INHERITED_DATA};
1947 foreach my $d (@{$data}) {
1948 if ($d->{TYPE} eq "FUNCTION") { $count++; }
1951 next if ($count == 0);
1953 pidl "status = dcerpc_ndr_$interface->{NAME}_init();";
1954 pidl "if (NT_STATUS_IS_ERR(status)) {";
1955 pidl "\treturn status;";
1959 pidl "return status;";
1965 sub CheckPointerTypes($$)
1968 my $default = shift;
1970 foreach my $e (@{$s->{ELEMENTS}}) {
1971 if ($e->{POINTERS}) {
1972 if (not defined(pointer_type($e))) {
1973 $e->{PROPERTIES}->{$default} = 1;
1976 if (pointer_type($e) eq "ptr") {
1977 print "Warning: ptr is not supported by pidl yet\n";
1983 sub LoadInterface($)
1987 if (not util::has_property($x, "pointer_default")) {
1988 # MIDL defaults to "ptr" in DCE compatible mode (/osf)
1989 # and "unique" in Microsoft Extensions mode (default)
1990 $x->{PROPERTIES}->{pointer_default} = "unique";
1993 foreach my $d (@{$x->{DATA}}) {
1994 if (($d->{TYPE} eq "DECLARE") or ($d->{TYPE} eq "TYPEDEF")) {
1995 $typedefs{$d->{NAME}} = $d;
1996 if ($d->{DATA}->{TYPE} eq "STRUCT" or $d->{DATA}->{TYPE} eq "UNION") {
1997 CheckPointerTypes($d->{DATA}, $x->{PROPERTIES}->{pointer_default});
2000 if (defined($d->{PROPERTIES}) && !defined($d->{DATA}->{PROPERTIES})) {
2001 $d->{DATA}->{PROPERTIES} = $d->{PROPERTIES};
2004 if ($d->{TYPE} eq "FUNCTION") {
2005 CheckPointerTypes($d,
2006 $x->{PROPERTIES}->{pointer_default} # MIDL defaults to "ref"
2012 # Add ORPC specific bits to an interface.
2013 sub InterfaceORPC($)
2016 # Add [in] ORPCTHIS *this, [out] ORPCTHAT *that
2017 # for 'object' interfaces
2018 if (util::has_property($x, "object")) {
2019 foreach my $e (@{$x->{DATA}}) {
2020 if($e->{TYPE} eq "FUNCTION") {
2021 $e->{PROPERTIES}->{object} = 1;
2022 unshift(@{$e->{ELEMENTS}},
2023 { 'NAME' => 'ORPCthis',
2025 'PROPERTIES' => { 'in' => '1' },
2026 'TYPE' => 'ORPCTHIS'
2028 unshift(@{$e->{ELEMENTS}},
2029 { 'NAME' => 'ORPCthat',
2031 'PROPERTIES' => { 'out' => '1' },
2032 'TYPE' => 'ORPCTHAT'
2043 foreach my $x (@{$idl}) {
2048 #####################################################################
2049 # parse a parsed IDL structure back into an IDL file
2053 my($filename) = shift;
2054 my $h_filename = $filename;
2059 if ($h_filename =~ /(.*)\.c/) {
2060 $h_filename = "$1.h";
2063 pidl "/* parser auto-generated by pidl */";
2065 pidl "#include \"includes.h\"";
2066 pidl "#include \"$h_filename\"";
2069 foreach my $x (@{$idl}) {
2070 if ($x->{TYPE} eq "INTERFACE") {
2071 needed::BuildNeeded($x);
2076 RegistrationFunction($idl, $filename);
2081 RegisterPrimitives();