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
20 return $typefamily{$n};
23 my %scalar_alignments =
42 "error_status_t" => 4,
52 $typefamily{SCALAR
} = {
55 return $scalar_alignments{$t->{NAME
}};
63 return 0 unless typelist
::hasType
($type);
65 if (my $dt = typelist
::getType
($type)->{DATA
}->{TYPE
}) {
66 return 1 if ($dt eq "SCALAR" or $dt eq "ENUM" or $dt eq "BITMAP");
76 return undef unless $e->{POINTERS
};
78 return "ref" if (util
::has_property
($e, "ref"));
79 return "ptr" if (util
::has_property
($e, "ptr"));
80 return "unique" if (util
::has_property
($e, "unique"));
81 return "relative" if (util
::has_property
($e, "relative"));
82 return "ignore" if (util
::has_property
($e, "ignore"));
87 # return 1 if this is a fixed array
91 my $len = $e->{"ARRAY_LEN"};
92 return 1 if (defined $len && util
::is_constant
($len));
96 # return 1 if this is a conformant array
97 sub is_conformant_array
($)
100 return 1 if (util
::has_property
($e, "size_is"));
104 # return 1 if this is a inline array
105 sub is_inline_array
($)
108 my $len = $e->{"ARRAY_LEN"};
109 if (is_fixed_array
($e) ||
110 defined $len && $len ne "*") {
116 # return 1 if this is a varying array
117 sub is_varying_array
($)
120 return 1 if (util
::has_property
($e, "length_is"));
124 # return 1 if this is a surrounding array (sometimes
125 # referred to as an embedded array). Can only occur as
126 # the last element in a struct and can not contain any pointers.
127 sub is_surrounding_array
($)
131 return ($e->{POINTERS
} == 0
132 and defined $e->{ARRAY_LEN
}
133 and $e->{ARRAY_LEN
} eq "*"
134 and $e == $e->{PARENT
}->{ELEMENTS
}[-1]
135 and $e->{PARENT
}->{TYPE
} ne "FUNCTION");
142 return "conformant-varying" if (is_varying_array
($e) and is_conformant_array
($e));
143 return "conformant" if (is_varying_array
($e));
144 return "varying" if (is_varying_array
($e));
145 return "inline" if (is_inline_array
($e));
146 return "fixed" if (is_fixed_array
($e));
151 # determine if an element needs a reference pointer on the wire
152 # in its NDR representation
153 sub need_wire_pointer
($)
157 my $n = $e->{POINTERS
};
158 my $pt = pointer_type
($e);
160 # Top level "ref" pointers do not have a referrent identifier
163 and $e->{PARENT
}->{TYPE
} eq "FUNCTION")
171 # determine if an element needs a "buffers" section in NDR
172 sub need_buffers_section
($)
175 if ((is_scalar_type
($e->{TYPE
}) || util
::has_property
($e, "subcontext")) &&
176 $e->{POINTERS
} == 0 &&
177 !util
::array_size
($e)) {
183 # see if a variable needs to be allocated by the NDR subsystem on pull
188 return 0 if (util
::has_property
($e, "ref"));
189 return 1 if ($e->{POINTERS
} || util
::array_size
($e));
193 # Prefix to get the actual value of a variable
198 foreach my $i (need_wire_pointer
($e)..$e->{POINTERS
}-1) { $pointers.="*"; }
202 # determine the C prefix used to refer to a variable when passing to a push
203 # function. This will be '*' for pointers to scalar types, '' for scalar
204 # types and normal pointers and '&' for pass-by-reference structures
211 if ($e->{TYPE
} =~ "string") {
213 } elsif (is_scalar_type
($e->{TYPE
}) &&
216 } elsif (!is_scalar_type
($e->{TYPE
}) &&
218 !util
::array_size
($e)) {
222 foreach my $i (2..$e->{POINTERS
}) { $ret.="*"; }
227 # determine the C prefix used to refer to a variable when passing to a pull
233 if (!$e->{POINTERS
} && !util
::array_size
($e)) {
237 if ($e->{TYPE
} =~ "string") {
242 foreach my $i (2..$e->{POINTERS
}) { $ret.="*"; }
264 $tabs = substr($tabs, 0, -1);
267 ####################################################################
268 # work out the name of a size_is() variable
273 my($var_prefix) = shift;
275 my($fn) = $e->{PARENT
};
277 return $size if (util
::is_constant
($size));
279 return $size if ($size =~ /ndr->|\(/);
283 if ($size =~ /\*(.*)/) {
288 if ($fn->{TYPE
} ne "FUNCTION") {
289 return $prefix . "r->$size";
292 my $e2 = util
::find_sibling
($e, $size);
294 if (util
::has_property
($e2, "in") && util
::has_property
($e2, "out")) {
295 return $prefix . "$var_prefix$size";
298 if (util
::has_property
($e2, "in")) {
299 return $prefix . "r->in.$size";
302 if (util
::has_property
($e2, "out")) {
303 return $prefix . "r->out.$size";
306 die "invalid variable in $size for element $e->{NAME} in $fn->{NAME}\n";
309 #####################################################################
310 # check that a variable we get from ParseExpr isn't a null pointer
311 sub check_null_pointer
($)
314 if ($size =~ /^\*/) {
315 my $size2 = substr($size, 1);
316 pidl
"if ($size2 == NULL) return NT_STATUS_INVALID_PARAMETER_MIX;";
320 #####################################################################
321 # check that a variable we get from ParseExpr isn't a null pointer
322 # void return varient
323 sub check_null_pointer_void
($)
326 if ($size =~ /^\*/) {
327 my $size2 = substr($size, 1);
328 pidl
"if ($size2 == NULL) return;";
332 #####################################################################
333 # work out is a parse function should be declared static or not
338 if ($fn->{TYPE
} eq "TYPEDEF" or
339 $fn->{TYPE
} eq "FUNCTION") {
340 return "" if (util
::has_property
($fn, "public"));
346 ###################################################################
347 # setup any special flags for an element or structure
351 my $flags = util
::has_property
($e, "flag");
352 if (defined $flags) {
353 pidl
"{ uint32_t _flags_save_$e->{TYPE} = ndr->flags;";
354 pidl
"ndr_set_flags(&ndr->flags, $flags);";
358 ###################################################################
359 # end any special flags for an element or structure
363 my $flags = util
::has_property
($e, "flag");
364 if (defined $flags) {
365 pidl
"ndr->flags = _flags_save_$e->{TYPE};\n\t}";
369 #####################################################################
370 # work out the correct alignment for a structure or union
371 sub find_largest_alignment
($)
376 for my $e (@
{$s->{ELEMENTS
}}) {
379 if (need_wire_pointer
($e)) {
382 $a = align_type
($e->{TYPE
});
385 $align = $a if ($align < $a);
391 #####################################################################
397 unless (typelist
::hasType
($e)) {
398 # it must be an external type - all we can do is guess
399 # print "Warning: assuming alignment of unknown type '$e' is 4\n";
403 my $dt = typelist
::getType
($e)->{DATA
};
405 my $tmp = $typefamily{$dt->{TYPE
}}->{ALIGN
}->($dt);
409 #####################################################################
410 # parse array preceding data - push side
411 sub ParseArrayPushPreceding
($$$)
414 my $var_prefix = shift;
415 my $ndr_flags = shift;
417 my $size = ParseExpr
($e, util
::array_size
($e), $var_prefix);
419 if (!is_inline_array
($e)) {
420 # we need to emit the array size
421 pidl
"NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, $size));";
425 #####################################################################
426 # parse the data of an array - push side
427 sub ParseArrayPush
($$$$)
431 my $var_prefix = shift;
432 my $ndr_flags = shift;
434 my $size = ParseExpr
($e, util
::array_size
($e), $var_prefix);
436 # See whether the array size has been pushed yet
437 if (!is_surrounding_array
($e)) {
438 ParseArrayPushPreceding
($e, $var_prefix, $ndr_flags);
441 if (is_varying_array
($e)) {
442 my $length = util
::has_property
($e, "length_is");
443 $length = ParseExpr
($e, $length, $var_prefix);
444 pidl
"NDR_CHECK(ndr_push_uint32($ndr, NDR_SCALARS, 0));";
445 pidl
"NDR_CHECK(ndr_push_uint32($ndr, NDR_SCALARS, $length));";
449 if (is_scalar_type
($e->{TYPE
})) {
450 pidl
"NDR_CHECK(ndr_push_array_$e->{TYPE}($ndr, $ndr_flags, $var_prefix$e->{NAME}, $size));";
452 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}));";
456 #####################################################################
458 sub ParseArrayPrint
($$)
461 my $var_prefix = shift;
462 my $size = ParseExpr
($e, util
::array_size
($e), $var_prefix);
464 if (is_varying_array
($e)) {
465 $size = ParseExpr
($e, util
::has_property
($e, "length_is"), $var_prefix);
468 if (is_scalar_type
($e->{TYPE
})) {
469 pidl
"ndr_print_array_$e->{TYPE}(ndr, \"$e->{NAME}\", $var_prefix$e->{NAME}, $size);";
471 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});";
475 #####################################################################
476 # check the size_is and length_is constraints
477 sub CheckArraySizes
($$)
480 my $var_prefix = shift;
482 if (!is_surrounding_array
($e) && is_conformant_array
($e)) {
483 my $size = ParseExpr
($e, util
::array_size
($e), $var_prefix);
484 pidl
"if ($var_prefix$e->{NAME}) {";
486 check_null_pointer
($size);
487 pidl
"NDR_CHECK(ndr_check_array_size(ndr, (void*)&$var_prefix$e->{NAME}, $size));";
492 if (is_varying_array
($e)) {
493 my $length = util
::has_property
($e, "length_is");
494 $length = ParseExpr
($e, $length, $var_prefix);
495 pidl
"if ($var_prefix$e->{NAME}) {";
497 check_null_pointer
($length);
498 pidl
"NDR_CHECK(ndr_check_array_length(ndr, (void*)&$var_prefix$e->{NAME}, $length));";
504 sub ParseArrayPullPreceding
($$$)
507 my $var_prefix = shift;
508 my $ndr_flags = shift;
510 if (!is_inline_array
($e)) {
511 # non fixed arrays encode the size just before the array
512 pidl
"NDR_CHECK(ndr_pull_array_size(ndr, &$var_prefix$e->{NAME}));";
516 #####################################################################
517 # parse an array - pull side
518 sub ParseArrayPull
($$$$)
522 my $var_prefix = shift;
523 my $ndr_flags = shift;
525 my $size = ParseExpr
($e, util
::array_size
($e), $var_prefix);
526 my $alloc_size = $size;
528 # if this is a conformant array then we use that size to allocate, and make sure
529 # we allocate enough to pull the elements
530 if (is_conformant_array
($e) and is_surrounding_array
($e)) {
531 $alloc_size = "ndr_get_array_size($ndr, &$var_prefix$e->{NAME})";
532 check_null_pointer
($size);
533 pidl
"if ($size > $alloc_size) {";
535 pidl
"return ndr_pull_error($ndr, NDR_ERR_CONFORMANT_SIZE, \"Bad conformant size %u should be %u\", $alloc_size, $size);";
538 } elsif (!is_inline_array
($e)) {
539 if ($var_prefix =~ /^r->out/ && $size =~ /^\*r->in/) {
540 my $size2 = substr($size, 1);
541 pidl
"if (ndr->flags & LIBNDR_FLAG_REF_ALLOC) { NDR_ALLOC($ndr, $size2); }";
544 ParseArrayPullPreceding
($e, $var_prefix, $ndr_flags);
546 $alloc_size = "ndr_get_array_size($ndr, &$var_prefix$e->{NAME})";
549 if ((need_alloc
($e) && !is_fixed_array
($e)) ||
550 ($var_prefix eq "r->in." && util
::has_property
($e, "ref"))) {
551 if (!is_inline_array
($e) || $ndr_flags eq "NDR_SCALARS") {
552 pidl
"NDR_ALLOC_N($ndr, $var_prefix$e->{NAME}, $alloc_size);";
556 if (($var_prefix eq "r->out." && util
::has_property
($e, "ref"))) {
557 if (!is_inline_array
($e) || $ndr_flags eq "NDR_SCALARS") {
558 pidl
"if ($ndr->flags & LIBNDR_FLAG_REF_ALLOC) {";
559 pidl
"\tNDR_ALLOC_N($ndr, $var_prefix$e->{NAME}, $alloc_size);";
564 if (is_varying_array
($e)) {
565 pidl
"NDR_CHECK(ndr_pull_array_length($ndr, &$var_prefix$e->{NAME}));";
566 $size = "ndr_get_array_length($ndr, &$var_prefix$e->{NAME})";
569 check_null_pointer
($size);
571 if (is_scalar_type
($e->{TYPE
})) {
572 pidl
"NDR_CHECK(ndr_pull_array_$e->{TYPE}($ndr, $ndr_flags, $var_prefix$e->{NAME}, $size));";
574 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}));";
578 sub ParseSubcontextPushStart
($)
581 my $sub_size = util
::has_property
($e, "subcontext");
585 pidl
"struct ndr_push *_ndr_$e->{NAME};";
587 pidl
"_ndr_$e->{NAME} = ndr_push_init_ctx(ndr);";
588 pidl
"if (!_ndr_$e->{NAME}) return NT_STATUS_NO_MEMORY;";
589 pidl
"_ndr_$e->{NAME}->flags = ndr->flags;";
592 return "_ndr_$e->{NAME}";
595 sub ParseSubcontextPushEnd
($)
598 my $sub_size = util
::has_property
($e, "subcontext");
599 pidl
"NDR_CHECK(ndr_push_subcontext_header(ndr, $sub_size, _ndr_$e->{NAME}));";
600 pidl
"NDR_CHECK(ndr_push_bytes(ndr, _ndr_$e->{NAME}->data, _ndr_$e->{NAME}->offset));";
605 sub ParseSubcontextPullStart
($)
608 my $sub_size = util
::has_property
($e, "subcontext");
612 pidl
"struct ndr_pull *_ndr_$e->{NAME};";
613 pidl
"NDR_ALLOC(ndr, _ndr_$e->{NAME});";
614 pidl
"NDR_CHECK(ndr_pull_subcontext_header(ndr, $sub_size, _ndr_$e->{NAME}));";
616 return "_ndr_$e->{NAME}";
619 sub ParseSubcontextPullEnd
($)
622 my $sub_size = util
::has_property
($e, "subcontext");
626 $advance = "_ndr_$e->{NAME}->data_size";
628 $advance = "_ndr_$e->{NAME}->offset";
630 pidl
"NDR_CHECK(ndr_pull_advance(ndr, $advance));";
635 #####################################################################
636 # parse scalars in a structure element
637 sub ParseElementPushScalar
($$$)
640 my($var_prefix) = shift;
641 my($ndr_flags) = shift;
642 my $cprefix = c_push_prefix
($e);
643 my $ptr_prefix = c_ptr_prefix
($e);
644 my $sub_size = util
::has_property
($e, "subcontext");
649 if (my $value = util
::has_property
($e, "value")) {
650 pidl
"$cprefix$var_prefix$e->{NAME} = $value;";
653 if (defined $sub_size and $e->{POINTERS
} == 0) {
654 $ndr = ParseSubcontextPushStart
($e);
657 if (need_wire_pointer
($e)) {
658 ParsePtrPush
($e, $ptr_prefix.$var_prefix);
659 } elsif (is_inline_array
($e)) {
660 ParseArrayPush
($e, $ndr, "r->", "NDR_SCALARS");
661 } elsif (need_alloc
($e)) {
662 # no scalar component
663 } elsif (my $switch = util
::has_property
($e, "switch_is")) {
664 ParseSwitchPush
($e, $ndr, $var_prefix, $ndr_flags, $switch);
666 pidl
"NDR_CHECK(ndr_push_$e->{TYPE}($ndr, $ndr_flags, $cprefix$var_prefix$e->{NAME}));";
669 if (defined $sub_size and $e->{POINTERS
} == 0) {
670 ParseSubcontextPushEnd
($e);
676 #####################################################################
677 # parse a pointer in a struct element or function
681 my $var_prefix = shift;
683 if (util
::has_property
($e, "relative")) {
684 pidl
"NDR_CHECK(ndr_push_relative_ptr1(ndr, $var_prefix$e->{NAME}));";
686 pidl
"NDR_CHECK(ndr_push_unique_ptr(ndr, $var_prefix$e->{NAME}));";
690 #####################################################################
691 # print scalars in a structure element
692 sub ParseElementPrint
($$)
695 my($var_prefix) = shift;
696 my $cprefix = c_push_prefix
($e);
697 my $ptr_prefix = c_ptr_prefix
($e);
699 return if (util
::has_property
($e, "noprint"));
701 if (my $value = util
::has_property
($e, "value")) {
702 pidl
"if (ndr->flags & LIBNDR_PRINT_SET_VALUES) {";
703 pidl
"\t$cprefix$var_prefix$e->{NAME} = $value;";
707 my $l = $e->{POINTERS
};
708 $l++ if (util
::array_size
($e) and $l == 0 and !is_fixed_array
($e));
710 foreach my $i (1..$l) {
711 pidl
"ndr_print_ptr(ndr, \"$e->{NAME}\", $var_prefix$e->{NAME});";
712 pidl
"ndr->depth++;";
713 if ($i > $l-need_wire_pointer
($e)) {
714 pidl
"if ($ptr_prefix$var_prefix$e->{NAME}) {";
719 if (util
::array_size
($e)) {
720 ParseArrayPrint
($e, $var_prefix)
721 } elsif (my $switch = util
::has_property
($e, "switch_is")) {
722 my $switch_var = ParseExpr
($e, $switch, $var_prefix);
723 check_null_pointer_void
($switch_var);
725 pidl
"ndr_print_$e->{TYPE}(ndr, \"$e->{NAME}\", $switch_var, $cprefix$var_prefix$e->{NAME});";
727 pidl
"ndr_print_$e->{TYPE}(ndr, \"$e->{NAME}\", $cprefix$var_prefix$e->{NAME});";
730 foreach my $i (1..$l) {
731 if ($i > $l-need_wire_pointer
($e)) {
735 pidl
"ndr->depth--;";
739 #####################################################################
740 # parse scalars in a structure element - pull size
741 sub ParseSwitchPull
($$$$$)
745 my($var_prefix) = shift;
746 my($ndr_flags) = shift;
748 my $switch_var = ParseExpr
($e, $switch, $var_prefix);
750 my $cprefix = c_pull_prefix
($e);
752 my $utype = typelist
::getType
($e->{TYPE
});
754 check_null_pointer
($switch_var);
756 if (!defined $utype ||
757 !util
::has_property
($utype, "nodiscriminant")) {
758 my $e2 = util
::find_sibling
($e, $switch);
759 my $type_decl = typelist
::mapType
($e2);
760 pidl
"if (($ndr_flags) & NDR_SCALARS) {";
762 pidl
"$type_decl _level;";
763 pidl
"NDR_CHECK(ndr_pull_$e2->{TYPE}($ndr, NDR_SCALARS, &_level));";
764 if ($switch_var =~ /r->in/) {
765 pidl
"if (!($ndr->flags & LIBNDR_FLAG_REF_ALLOC) && _level != $switch_var) {";
768 pidl
"if (_level != $switch_var) {";
771 pidl
"return ndr_pull_error($ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value %u in $e->{NAME}\", _level);";
773 if ($switch_var =~ /r->/) {
774 pidl
"} else { $switch_var = _level; }";
782 pidl
"NDR_CHECK(ndr_pull_$e->{TYPE}($ndr, $ndr_flags, $switch_var, $cprefix$var_prefix$e->{NAME}));";
785 #####################################################################
786 # push switch element
787 sub ParseSwitchPush
($$$$$)
791 my($var_prefix) = shift;
792 my($ndr_flags) = shift;
794 my $switch_var = ParseExpr
($e, $switch, $var_prefix);
795 my $cprefix = c_push_prefix
($e);
797 check_null_pointer
($switch_var);
799 my $utype = typelist
::getType
($e->{TYPE
});
800 if (!defined $utype ||
801 !util
::has_property
($utype, "nodiscriminant")) {
802 my $e2 = util
::find_sibling
($e, $switch);
803 pidl
"if (($ndr_flags) & NDR_SCALARS) {";
804 pidl
"\tNDR_CHECK(ndr_push_$e2->{TYPE}($ndr, NDR_SCALARS, $switch_var));";
808 pidl
"NDR_CHECK(ndr_push_$e->{TYPE}($ndr, $ndr_flags, $switch_var, $cprefix$var_prefix$e->{NAME}));";
811 #####################################################################
812 # parse scalars in a structure element - pull size
813 sub ParseElementPullScalar
($$$)
816 my($var_prefix) = shift;
817 my($ndr_flags) = shift;
818 my $cprefix = c_pull_prefix
($e);
819 my $ptr_prefix = c_ptr_prefix
($e);
820 my $sub_size = util
::has_property
($e, "subcontext");
825 if (defined $sub_size && $e->{POINTERS
} == 0) {
826 $ndr = ParseSubcontextPullStart
($e);
827 $ndr_flags = "NDR_SCALARS|NDR_BUFFERS";
830 if (is_inline_array
($e)) {
831 ParseArrayPull
($e, $ndr, "r->", "NDR_SCALARS");
832 } elsif (need_wire_pointer
($e)) {
833 ParsePtrPull
($e, $ptr_prefix.$var_prefix);
834 } elsif (is_surrounding_array
($e)) {
835 } elsif (my $switch = util
::has_property
($e, "switch_is")) {
836 ParseSwitchPull
($e, $ndr, $var_prefix, $ndr_flags, $switch);
838 pidl
"NDR_CHECK(ndr_pull_$e->{TYPE}($ndr, $ndr_flags, $cprefix$var_prefix$e->{NAME}));";
841 if (my $range = util
::has_property
($e, "range")) {
842 my ($low, $high) = split(/ /, $range, 2);
843 pidl
"if ($var_prefix$e->{NAME} < $low || $var_prefix$e->{NAME} > $high) {";
844 pidl
"\treturn ndr_pull_error($ndr, NDR_ERR_RANGE, \"value out of range\");";
848 if (defined $sub_size && $e->{POINTERS
} == 0) {
849 ParseSubcontextPullEnd
($e);
855 #####################################################################
856 # parse a pointer in a struct element or function
860 my($var_prefix) = shift;
862 pidl
"NDR_CHECK(ndr_pull_unique_ptr(ndr, &_ptr_$e->{NAME}));";
863 pidl
"if (_ptr_$e->{NAME}) {";
865 pidl
"NDR_ALLOC(ndr, $var_prefix$e->{NAME});";
866 if (util
::has_property
($e, "relative")) {
867 pidl
"NDR_CHECK(ndr_pull_relative_ptr1(ndr, $var_prefix$e->{NAME}, _ptr_$e->{NAME}));";
871 pidl
"\t$var_prefix$e->{NAME} = NULL;";
875 #####################################################################
876 # parse buffers in a structure element
877 sub ParseElementPushBuffer
($$)
880 my($var_prefix) = shift;
881 my $cprefix = c_push_prefix
($e);
882 my $sub_size = util
::has_property
($e, "subcontext");
885 return unless (need_buffers_section
($e));
889 my $pointers = c_ptr_prefix
($e);
890 for my $i (1..need_wire_pointer
($e)) {
892 ParsePtrPush
($e,$pointers.$var_prefix);
894 pidl
"if ($pointers$var_prefix$e->{NAME}) {";
899 if (util
::has_property
($e, "relative")) {
900 pidl
"NDR_CHECK(ndr_push_relative_ptr2(ndr, $var_prefix$e->{NAME}));";
903 my $ndr_flags = "NDR_BUFFERS";
904 if ($e->{POINTERS
} || (util
::array_size
($e) && !is_inline_array
($e)))
906 $ndr_flags="NDR_SCALARS|$ndr_flags"
909 if (defined $sub_size) {
910 $ndr = ParseSubcontextPushStart
($e);
911 $ndr_flags = "NDR_SCALARS|NDR_BUFFERS";
914 if (util
::array_size
($e)) {
915 ParseArrayPush
($e, $ndr, "r->", $ndr_flags);
916 } elsif (my $switch = util
::has_property
($e, "switch_is")) {
917 ParseSwitchPush
($e, $ndr, $var_prefix, $ndr_flags, $switch);
919 pidl
"NDR_CHECK(ndr_push_$e->{TYPE}(ndr, $ndr_flags, $cprefix$var_prefix$e->{NAME}));";
922 if (defined $sub_size) {
923 ParseSubcontextPushEnd
($e);
926 for my $i (1..need_wire_pointer
($e)) {
934 #####################################################################
935 # parse buffers in a structure element - pull side
936 sub ParseElementPullBuffer
($$)
939 my($var_prefix) = shift;
940 my $cprefix = c_pull_prefix
($e);
941 my $sub_size = util
::has_property
($e, "subcontext");
944 return unless (need_buffers_section
($e));
948 my $pointers = c_ptr_prefix
($e);
949 for my $i (1..need_wire_pointer
($e)) {
951 ParsePtrPull
($e,$pointers.$var_prefix);
953 pidl
"if ($pointers$var_prefix$e->{NAME}) {";
958 if (util
::has_property
($e, "relative")) {
959 pidl
"struct ndr_pull_save _relative_save;";
960 pidl
"ndr_pull_save(ndr, &_relative_save);";
961 pidl
"NDR_CHECK(ndr_pull_relative_ptr2(ndr, $var_prefix$e->{NAME}));";
964 my $ndr_flags = "NDR_BUFFERS";
965 if ($e->{POINTERS
} || (util
::array_size
($e) && !is_inline_array
($e)))
967 $ndr_flags="NDR_SCALARS|$ndr_flags"
970 if (defined $sub_size) {
971 $ndr = ParseSubcontextPullStart
($e);
972 $ndr_flags = "NDR_SCALARS|NDR_BUFFERS";
975 if (util
::array_size
($e)) {
976 ParseArrayPull
($e, $ndr, "r->", $ndr_flags);
977 } elsif (my $switch = util
::has_property
($e, "switch_is")) {
978 ParseSwitchPull
($e, $ndr, $var_prefix, $ndr_flags, $switch);
980 pidl
"NDR_CHECK(ndr_pull_$e->{TYPE}($ndr, $ndr_flags, $cprefix$var_prefix$e->{NAME}));";
983 if (defined $sub_size) {
984 ParseSubcontextPullEnd
($e);
987 if (util
::has_property
($e, "relative")) {
988 pidl
"ndr_pull_restore(ndr, &_relative_save);";
991 for my $i (1..need_wire_pointer
($e)) {
999 #####################################################################
1001 sub ParseStructPush
($)
1003 my($struct) = shift;
1005 return unless defined($struct->{ELEMENTS
});
1007 start_flags
($struct);
1009 # see if the structure contains a conformant array. If it
1010 # does, then it must be the last element of the structure, and
1011 # we need to push the conformant length early, as it fits on
1012 # the wire before the structure (and even before the structure
1014 my $e = $struct->{ELEMENTS
}[-1];
1015 if (is_conformant_array
($e) and is_surrounding_array
($e)) {
1016 ParseArrayPushPreceding
($e, "r->", "NDR_SCALARS");
1019 if (defined $e->{TYPE
} && $e->{TYPE
} eq "string"
1020 && util
::property_matches
($e, "flag", ".*LIBNDR_FLAG_STR_CONFORMANT.*")) {
1021 pidl
"NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_string_array_size(ndr, r->$e->{NAME})));";
1024 pidl
"if (!(ndr_flags & NDR_SCALARS)) goto buffers;";
1026 pidl
"NDR_CHECK(ndr_push_struct_start(ndr));";
1028 my $align = find_largest_alignment
($struct);
1029 pidl
"NDR_CHECK(ndr_push_align(ndr, $align));";
1031 foreach my $e (@
{$struct->{ELEMENTS
}}) {
1032 ParseElementPushScalar
($e, "r->", "NDR_SCALARS");
1036 pidl
"if (!(ndr_flags & NDR_BUFFERS)) goto done;";
1037 foreach my $e (@
{$struct->{ELEMENTS
}}) {
1038 ParseElementPushBuffer
($e, "r->");
1041 pidl
"ndr_push_struct_end(ndr);";
1048 #####################################################################
1049 # generate a push function for an enum
1050 sub ParseEnumPush
($)
1053 my($type_fn) = typelist
::enum_type_fn
($enum);
1057 pidl
"NDR_CHECK(ndr_push_$type_fn(ndr, NDR_SCALARS, r));";
1062 #####################################################################
1063 # generate a pull function for an enum
1064 sub ParseEnumPull
($)
1067 my($type_fn) = typelist
::enum_type_fn
($enum);
1068 my($type_v_decl) = typelist
::mapScalarType
(typelist
::enum_type_fn
($enum));
1070 pidl
"$type_v_decl v;";
1072 pidl
"NDR_CHECK(ndr_pull_$type_fn(ndr, NDR_SCALARS, &v));";
1078 #####################################################################
1079 # generate a print function for an enum
1080 sub ParseEnumPrint
($)
1084 pidl
"const char *val = NULL;";
1089 pidl
"switch (r) {";
1091 my $els = \@
{$enum->{ELEMENTS
}};
1092 foreach my $i (0 .. $#{$els}) {
1093 my $e = ${$els}[$i];
1095 if ($e =~ /^(.*)=/) {
1098 pidl
"case $e: val = \"$e\"; break;";
1104 pidl
"ndr_print_enum(ndr, name, \"$enum->{TYPE}\", val, r);";
1112 return "struct ndr_push *ndr, int ndr_flags, enum $e->{NAME} r";
1115 sub ArgsEnumPrint
($)
1118 return "struct ndr_print *ndr, const char *name, enum $e->{NAME} r";
1124 return "struct ndr_pull *ndr, int ndr_flags, enum $e->{NAME} *r";
1127 $typefamily{ENUM
} = {
1128 PUSH_FN_BODY
=> \
&ParseEnumPush
,
1129 PUSH_FN_ARGS
=> \
&ArgsEnumPush
,
1130 PULL_FN_BODY
=> \
&ParseEnumPull
,
1131 PULL_FN_ARGS
=> \
&ArgsEnumPull
,
1132 PRINT_FN_BODY
=> \
&ParseEnumPrint
,
1133 PRINT_FN_ARGS
=> \
&ArgsEnumPrint
,
1134 ALIGN
=> sub { return align_type
(typelist
::enum_type_fn
(shift)); }
1137 #####################################################################
1138 # generate a push function for a bitmap
1139 sub ParseBitmapPush
($)
1141 my($bitmap) = shift;
1142 my($type_fn) = typelist
::bitmap_type_fn
($bitmap);
1144 start_flags
($bitmap);
1146 pidl
"NDR_CHECK(ndr_push_$type_fn(ndr, NDR_SCALARS, r));";
1151 #####################################################################
1152 # generate a pull function for an bitmap
1153 sub ParseBitmapPull
($)
1155 my($bitmap) = shift;
1156 my($type_fn) = typelist
::bitmap_type_fn
($bitmap);
1157 my($type_decl) = typelist
::mapType
($bitmap);
1159 pidl
"$type_decl v;";
1160 start_flags
($bitmap);
1161 pidl
"NDR_CHECK(ndr_pull_$type_fn(ndr, NDR_SCALARS, &v));";
1167 #####################################################################
1168 # generate a print function for an bitmap
1169 sub ParseBitmapPrintElement
($$)
1172 my($bitmap) = shift;
1173 my($type_decl) = typelist
::mapType
($bitmap);
1174 my($type_fn) = typelist
::bitmap_type_fn
($bitmap);
1175 my($name) = $bitmap->{PARENT
}->{NAME
};
1178 if ($e =~ /^(\w+) .*$/) {
1181 die "Bitmap: \"$name\" invalid Flag: \"$e\"";
1184 pidl
"ndr_print_bitmap_flag(ndr, sizeof($type_decl), \"$flag\", $flag, r);";
1187 #####################################################################
1188 # generate a print function for an bitmap
1189 sub ParseBitmapPrint
($)
1191 my($bitmap) = shift;
1192 my($type_decl) = typelist
::mapType
($bitmap);
1193 my($type_fn) = typelist
::bitmap_type_fn
($bitmap);
1195 start_flags
($bitmap);
1197 pidl
"ndr_print_$type_fn(ndr, name, r);";
1199 pidl
"ndr->depth++;";
1200 foreach my $e (@
{$bitmap->{ELEMENTS
}}) {
1201 ParseBitmapPrintElement
($e, $bitmap);
1203 pidl
"ndr->depth--;";
1208 sub ArgsBitmapPush
($)
1211 my $type_decl = typelist
::mapType
($e->{DATA
});
1212 return "struct ndr_push *ndr, int ndr_flags, $type_decl r";
1215 sub ArgsBitmapPrint
($)
1218 my $type_decl = typelist
::mapType
($e->{DATA
});
1219 return "struct ndr_print *ndr, const char *name, $type_decl r";
1222 sub ArgsBitmapPull
($)
1225 my $type_decl = typelist
::mapType
($e->{DATA
});
1226 return "struct ndr_pull *ndr, int ndr_flags, $type_decl *r";
1229 $typefamily{BITMAP
} = {
1230 PUSH_FN_BODY
=> \
&ParseBitmapPush
,
1231 PUSH_FN_ARGS
=> \
&ArgsBitmapPush
,
1232 PULL_FN_BODY
=> \
&ParseBitmapPull
,
1233 PULL_FN_ARGS
=> \
&ArgsBitmapPull
,
1234 PRINT_FN_BODY
=> \
&ParseBitmapPrint
,
1235 PRINT_FN_ARGS
=> \
&ArgsBitmapPrint
,
1236 ALIGN
=> sub { return align_type
(typelist
::bitmap_type_fn
(shift)); }
1239 #####################################################################
1240 # generate a struct print function
1241 sub ParseStructPrint
($)
1243 my($struct) = shift;
1244 my($name) = $struct->{PARENT
}->{NAME
};
1246 return unless defined $struct->{ELEMENTS
};
1248 pidl
"ndr_print_struct(ndr, name, \"$name\");";
1250 start_flags
($struct);
1252 pidl
"ndr->depth++;";
1253 foreach my $e (@
{$struct->{ELEMENTS
}}) {
1254 ParseElementPrint
($e, "r->");
1256 pidl
"ndr->depth--;";
1261 #####################################################################
1262 # parse a struct - pull side
1263 sub ParseStructPull
($)
1265 my($struct) = shift;
1268 return unless defined $struct->{ELEMENTS
};
1270 # see if the structure contains a conformant array. If it
1271 # does, then it must be the last element of the structure, and
1272 # we need to pull the conformant length early, as it fits on
1273 # the wire before the structure (and even before the structure
1275 my $e = $struct->{ELEMENTS
}[-1];
1276 if (is_conformant_array
($e) and is_surrounding_array
($e)) {
1280 if (defined $e->{TYPE
} && $e->{TYPE
} eq "string"
1281 && util
::property_matches
($e, "flag", ".*LIBNDR_FLAG_STR_CONFORMANT.*")) {
1285 # declare any internal pointers we need
1286 foreach my $e (@
{$struct->{ELEMENTS
}}) {
1287 if (need_wire_pointer
($e)) {
1288 pidl
"uint32_t _ptr_$e->{NAME};";
1292 start_flags
($struct);
1294 pidl
"if (!(ndr_flags & NDR_SCALARS)) goto buffers;";
1296 pidl
"NDR_CHECK(ndr_pull_struct_start(ndr));";
1298 if (defined $conform_e) {
1299 ParseArrayPullPreceding
($conform_e, "r->", "NDR_SCALARS");
1302 my $align = find_largest_alignment
($struct);
1303 pidl
"NDR_CHECK(ndr_pull_align(ndr, $align));";
1305 foreach my $e (@
{$struct->{ELEMENTS
}}) {
1306 ParseElementPullScalar
($e, "r->", "NDR_SCALARS");
1310 pidl
"if (!(ndr_flags & NDR_BUFFERS)) goto done;";
1311 foreach my $e (@
{$struct->{ELEMENTS
}}) {
1312 ParseElementPullBuffer
($e, "r->");
1315 foreach my $e (@
{$struct->{ELEMENTS
}}) {
1316 CheckArraySizes
($e, "r->");
1319 pidl
"ndr_pull_struct_end(ndr);";
1326 #####################################################################
1327 # calculate size of ndr struct
1328 sub ParseStructNdrSize
($)
1331 my $static = fn_prefix
($t);
1334 if (my $flags = util
::has_property
($t, "flag")) {
1335 pidl
"flags |= $flags;";
1337 pidl
"return ndr_size_struct(r, flags, (ndr_push_flags_fn_t)ndr_push_$t->{NAME});";
1340 sub ArgsStructPush
($)
1343 return "struct ndr_push *ndr, int ndr_flags, struct $e->{NAME} *r";
1346 sub ArgsStructPrint
($)
1349 return "struct ndr_print *ndr, const char *name, struct $e->{NAME} *r";
1352 sub ArgsStructPull
($)
1355 return "struct ndr_pull *ndr, int ndr_flags, struct $e->{NAME} *r";
1358 sub ArgsStructNdrSize
($)
1361 return "const struct $d->{NAME} *r, int flags";
1364 $typefamily{STRUCT
} = {
1365 PUSH_FN_BODY
=> \
&ParseStructPush
,
1366 PUSH_FN_ARGS
=> \
&ArgsStructPush
,
1367 PULL_FN_BODY
=> \
&ParseStructPull
,
1368 PULL_FN_ARGS
=> \
&ArgsStructPull
,
1369 PRINT_FN_BODY
=> \
&ParseStructPrint
,
1370 PRINT_FN_ARGS
=> \
&ArgsStructPrint
,
1371 SIZE_FN_BODY
=> \
&ParseStructNdrSize
,
1372 SIZE_FN_ARGS
=> \
&ArgsStructNdrSize
,
1373 ALIGN
=> \
&find_largest_alignment
1376 #####################################################################
1377 # calculate size of ndr struct
1378 sub ParseUnionNdrSize
($)
1381 my $static = fn_prefix
($t);
1384 if (my $flags = util
::has_property
($t, "flag")) {
1385 pidl
"flags |= $flags;";
1387 pidl
"return ndr_size_union(r, flags, level, (ndr_push_union_fn_t)ndr_push_$t->{NAME});";
1390 #####################################################################
1391 # parse a union - push side
1392 sub ParseUnionPush
($)
1395 my $have_default = 0;
1399 pidl
"if (!(ndr_flags & NDR_SCALARS)) goto buffers;";
1401 pidl
"NDR_CHECK(ndr_push_struct_start(ndr));";
1403 # my $align = union_alignment($e);
1404 # pidl "NDR_CHECK(ndr_push_align(ndr, $align));";
1406 pidl
"switch (level) {";
1408 foreach my $el (@
{$e->{ELEMENTS
}}) {
1409 if (util
::has_property
($el, "default")) {
1413 pidl
"case $el->{PROPERTIES}->{case}:";
1416 if ($el->{TYPE
} ne "EMPTY") {
1418 ParseElementPushScalar
($el, "r->", "NDR_SCALARS");
1424 if (! $have_default) {
1426 pidl
"\treturn ndr_push_error(ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value \%u\", level);";
1431 pidl
"if (!(ndr_flags & NDR_BUFFERS)) goto done;";
1432 pidl
"switch (level) {";
1434 foreach my $el (@
{$e->{ELEMENTS
}}) {
1435 if (util
::has_property
($el, "default")) {
1438 pidl
"case $el->{PROPERTIES}->{case}:";
1440 if ($el->{TYPE
} ne "EMPTY") {
1442 ParseElementPushBuffer
($el, "r->");
1448 if (! $have_default) {
1450 pidl
"\treturn ndr_push_error(ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value \%u\", level);";
1454 pidl
"ndr_push_struct_end(ndr);";
1459 #####################################################################
1461 sub ParseUnionPrint
($)
1464 my $have_default = 0;
1465 my($name) = $e->{PARENT
}->{NAME
};
1467 pidl
"ndr_print_union(ndr, name, level, \"$name\");";
1470 pidl
"switch (level) {";
1472 foreach my $el (@
{$e->{ELEMENTS
}}) {
1473 if (util
::has_property
($el, "default")) {
1477 pidl
"case $el->{PROPERTIES}->{case}:";
1479 if ($el->{TYPE
} ne "EMPTY") {
1481 ParseElementPrint
($el, "r->");
1487 if (! $have_default) {
1489 pidl
"\tndr_print_bad_level(ndr, name, level);";
1497 #####################################################################
1498 # parse a union - pull side
1499 sub ParseUnionPull
($)
1502 my $have_default = 0;
1506 pidl
"if (!(ndr_flags & NDR_SCALARS)) goto buffers;";
1508 pidl
"NDR_CHECK(ndr_pull_struct_start(ndr));";
1510 # my $align = union_alignment($e);
1511 # pidl "\tNDR_CHECK(ndr_pull_align(ndr, $align));\n";
1513 pidl
"switch (level) {";
1515 foreach my $el (@
{$e->{ELEMENTS
}}) {
1516 if (util
::has_property
($el, "default")) {
1520 pidl
"case $el->{PROPERTIES}->{case}: {";
1522 if ($el->{TYPE
} ne "EMPTY") {
1524 if ($el->{POINTERS
}) {
1525 pidl
"uint32_t _ptr_$el->{NAME};";
1527 ParseElementPullScalar
($el, "r->", "NDR_SCALARS");
1533 if (! $have_default) {
1535 pidl
"\treturn ndr_pull_error(ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value \%u\", level);";
1540 pidl
"if (!(ndr_flags & NDR_BUFFERS)) goto done;";
1541 pidl
"switch (level) {";
1543 foreach my $el (@
{$e->{ELEMENTS
}}) {
1544 if (util
::has_property
($el, "default")) {
1547 pidl
"case $el->{PROPERTIES}->{case}:";
1549 if ($el->{TYPE
} ne "EMPTY") {
1551 ParseElementPullBuffer
($el, "r->");
1557 if (! $have_default) {
1559 pidl
"\treturn ndr_pull_error(ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value \%u\", level);";
1563 pidl
"ndr_pull_struct_end(ndr);";
1568 sub ArgsUnionPush
($)
1571 return "struct ndr_push *ndr, int ndr_flags, int level, union $e->{NAME} *r";
1574 sub ArgsUnionPrint
($)
1577 return "struct ndr_print *ndr, const char *name, int level, union $e->{NAME} *r";
1580 sub ArgsUnionPull
($)
1583 return "struct ndr_pull *ndr, int ndr_flags, int level, union $e->{NAME} *r";
1586 sub ArgsUnionNdrSize
($)
1589 return "const union $d->{NAME} *r, uint32_t level, int flags";
1592 $typefamily{UNION
} = {
1593 PUSH_FN_BODY
=> \
&ParseUnionPush
,
1594 PUSH_FN_ARGS
=> \
&ArgsUnionPush
,
1595 PULL_FN_BODY
=> \
&ParseUnionPull
,
1596 PULL_FN_ARGS
=> \
&ArgsUnionPull
,
1597 PRINT_FN_BODY
=> \
&ParseUnionPrint
,
1598 PRINT_FN_ARGS
=> \
&ArgsUnionPrint
,
1599 SIZE_FN_ARGS
=> \
&ArgsUnionNdrSize
,
1600 SIZE_FN_BODY
=> \
&ParseUnionNdrSize
,
1601 ALIGN
=> \
&find_largest_alignment
1604 #####################################################################
1605 # parse a typedef - push side
1606 sub ParseTypedefPush
($)
1609 my $static = fn_prefix
($e);
1611 return unless needed
::is_needed
("push_$e->{NAME}");
1613 my $args = $typefamily{$e->{DATA
}->{TYPE
}}->{PUSH_FN_ARGS
}->($e);
1614 pidl
$static . "NTSTATUS ndr_push_$e->{NAME}($args)";
1618 $typefamily{$e->{DATA
}->{TYPE
}}->{PUSH_FN_BODY
}->($e->{DATA
});
1619 pidl
"return NT_STATUS_OK;";
1626 #####################################################################
1627 # parse a typedef - pull side
1628 sub ParseTypedefPull
($)
1631 my $static = fn_prefix
($e);
1633 return unless needed
::is_needed
("pull_$e->{NAME}");
1635 my $args = $typefamily{$e->{DATA
}->{TYPE
}}->{PULL_FN_ARGS
}->($e);
1637 pidl
$static . "NTSTATUS ndr_pull_$e->{NAME}($args)";
1641 $typefamily{$e->{DATA
}->{TYPE
}}->{PULL_FN_BODY
}->($e->{DATA
});
1642 pidl
"return NT_STATUS_OK;";
1648 #####################################################################
1649 # parse a typedef - print side
1650 sub ParseTypedefPrint
($)
1654 my $args = $typefamily{$e->{DATA
}->{TYPE
}}->{PRINT_FN_ARGS
}->($e);
1656 return unless !util
::has_property
($e, "noprint");
1658 pidl
"void ndr_print_$e->{NAME}($args)";
1661 $typefamily{$e->{DATA
}->{TYPE
}}->{PRINT_FN_BODY
}->($e->{DATA
});
1666 #####################################################################
1667 ## calculate the size of a structure
1668 sub ParseTypedefNdrSize
($)
1672 return unless needed
::is_needed
("ndr_size_$t->{NAME}");
1674 my $tf = $typefamily{$t->{DATA
}->{TYPE
}};
1675 my $args = $tf->{SIZE_FN_ARGS
}->($t);
1677 pidl
"size_t ndr_size_$t->{NAME}($args)";
1680 $typefamily{$t->{DATA
}->{TYPE
}}->{SIZE_FN_BODY
}->($t);
1686 #####################################################################
1687 # parse a function - print side
1688 sub ParseFunctionPrint
($)
1692 return unless !util
::has_property
($fn, "noprint");
1694 pidl
"void ndr_print_$fn->{NAME}(struct ndr_print *ndr, const char *name, int flags, struct $fn->{NAME} *r)";
1697 pidl
"ndr_print_struct(ndr, name, \"$fn->{NAME}\");";
1698 pidl
"ndr->depth++;";
1700 pidl
"if (flags & NDR_SET_VALUES) {";
1701 pidl
"\tndr->flags |= LIBNDR_PRINT_SET_VALUES;";
1704 pidl
"if (flags & NDR_IN) {";
1706 pidl
"ndr_print_struct(ndr, \"in\", \"$fn->{NAME}\");";
1707 pidl
"ndr->depth++;";
1709 foreach my $e (@
{$fn->{ELEMENTS
}}) {
1710 if (util
::has_property
($e, "in")) {
1711 ParseElementPrint
($e, "r->in.");
1714 pidl
"ndr->depth--;";
1718 pidl
"if (flags & NDR_OUT) {";
1720 pidl
"ndr_print_struct(ndr, \"out\", \"$fn->{NAME}\");";
1721 pidl
"ndr->depth++;";
1722 foreach my $e (@
{$fn->{ELEMENTS
}}) {
1723 if (util
::has_property
($e, "out")) {
1724 ParseElementPrint
($e, "r->out.");
1727 if ($fn->{RETURN_TYPE
} && $fn->{RETURN_TYPE
} ne "void") {
1729 $cprefix = "" if (is_scalar_type
($fn->{RETURN_TYPE
})) ; # FIXME: Should really use util::c_push_prefix here
1730 pidl
"ndr_print_$fn->{RETURN_TYPE}(ndr, \"result\", $cprefix"."r->out.result);";
1732 pidl
"ndr->depth--;";
1736 pidl
"ndr->depth--;";
1742 #####################################################################
1743 # parse a function element
1744 sub ParseFunctionElementPush
($$)
1749 if (util
::array_size
($e)) {
1750 if (need_wire_pointer
($e)) {
1751 pidl
"NDR_CHECK(ndr_push_unique_ptr(ndr, r->$inout.$e->{NAME}));";
1752 pidl
"if (r->$inout.$e->{NAME}) {";
1754 ParseArrayPush
($e, "ndr", "r->$inout.", "NDR_SCALARS|NDR_BUFFERS");
1758 ParseArrayPush
($e, "ndr", "r->$inout.", "NDR_SCALARS|NDR_BUFFERS");
1761 ParseElementPushScalar
($e, "r->$inout.", "NDR_SCALARS|NDR_BUFFERS");
1762 if (need_wire_pointer
($e)) {
1763 ParseElementPushBuffer
($e, "r->$inout.");
1768 #####################################################################
1770 sub ParseFunctionPush
($)
1773 my $static = fn_prefix
($fn);
1775 return unless !util
::has_property
($fn, "nopush");
1777 pidl
$static . "NTSTATUS ndr_push_$fn->{NAME}(struct ndr_push *ndr, int flags, struct $fn->{NAME} *r)";
1781 pidl
"if (!(flags & NDR_IN)) goto ndr_out;";
1784 foreach my $e (@
{$fn->{ELEMENTS
}}) {
1785 if (util
::has_property
($e, "in")) {
1786 ParseFunctionElementPush
($e, "in");
1791 pidl
"if (!(flags & NDR_OUT)) goto done;";
1794 foreach my $e (@
{$fn->{ELEMENTS
}}) {
1795 if (util
::has_property
($e, "out")) {
1796 ParseFunctionElementPush
($e, "out");
1800 if ($fn->{RETURN_TYPE
} && $fn->{RETURN_TYPE
} ne "void") {
1801 pidl
"NDR_CHECK(ndr_push_$fn->{RETURN_TYPE}(ndr, NDR_SCALARS, r->out.result));";
1805 pidl
"return NT_STATUS_OK;";
1811 #####################################################################
1812 # parse a function element
1813 sub ParseFunctionElementPull
($$)
1818 if (util
::array_size
($e)) {
1819 if (need_wire_pointer
($e)) {
1820 pidl
"NDR_CHECK(ndr_pull_unique_ptr(ndr, &_ptr_$e->{NAME}));";
1821 pidl
"r->$inout.$e->{NAME} = NULL;";
1822 pidl
"if (_ptr_$e->{NAME}) {";
1823 } elsif ($inout eq "out" && util
::has_property
($e, "ref")) {
1824 pidl
"if (r->$inout.$e->{NAME}) {";
1829 ParseArrayPull
($e, "ndr", "r->$inout.", "NDR_SCALARS|NDR_BUFFERS");
1833 if ($inout eq "out" && util
::has_property
($e, "ref")) {
1834 pidl
"if (ndr->flags & LIBNDR_FLAG_REF_ALLOC) {";
1835 pidl
"\tNDR_ALLOC(ndr, r->out.$e->{NAME});";
1839 if ($inout eq "in" && util
::has_property
($e, "ref")) {
1840 pidl
"NDR_ALLOC(ndr, r->in.$e->{NAME});";
1843 ParseElementPullScalar
($e, "r->$inout.", "NDR_SCALARS|NDR_BUFFERS");
1844 if (need_wire_pointer
($e)) {
1845 ParseElementPullBuffer
($e, "r->$inout.");
1850 ############################################################
1851 # allocate ref variables
1852 sub AllocateRefVars
($)
1855 my $asize = util
::array_size
($e);
1857 # note that if the variable is also an "in"
1858 # variable then we copy the initial value from
1861 if (!defined $asize) {
1862 # its a simple variable
1863 pidl
"NDR_ALLOC(ndr, r->out.$e->{NAME});";
1864 if (util
::has_property
($e, "in")) {
1865 pidl
"*r->out.$e->{NAME} = *r->in.$e->{NAME};";
1867 pidl
"ZERO_STRUCTP(r->out.$e->{NAME});";
1873 my $size = ParseExpr
($e, $asize, "r->out.");
1874 check_null_pointer
($size);
1875 pidl
"NDR_ALLOC_N(ndr, r->out.$e->{NAME}, $size);";
1876 if (util
::has_property
($e, "in")) {
1877 pidl
"memcpy(r->out.$e->{NAME},r->in.$e->{NAME},$size * sizeof(*r->in.$e->{NAME}));";
1879 pidl
"memset(r->out.$e->{NAME}, 0, $size * sizeof(*r->out.$e->{NAME}));";
1883 #####################################################################
1885 sub ParseFunctionPull
($)
1888 my $static = fn_prefix
($fn);
1890 return unless !util
::has_property
($fn, "nopull");
1892 # pull function args
1893 pidl
$static . "NTSTATUS ndr_pull_$fn->{NAME}(struct ndr_pull *ndr, int flags, struct $fn->{NAME} *r)";
1897 # declare any internal pointers we need
1898 foreach my $e (@
{$fn->{ELEMENTS
}}) {
1899 if (need_wire_pointer
($e)) {
1900 pidl
"uint32_t _ptr_$e->{NAME};";
1904 pidl
"if (!(flags & NDR_IN)) goto ndr_out;";
1907 # auto-init the out section of a structure. I originally argued that
1908 # this was a bad idea as it hides bugs, but coping correctly
1909 # with initialisation and not wiping ref vars is turning
1910 # out to be too tricky (tridge)
1911 foreach my $e (@
{$fn->{ELEMENTS
}}) {
1912 if (util
::has_property
($e, "out")) {
1913 pidl
"ZERO_STRUCT(r->out);";
1919 foreach my $e (@
{$fn->{ELEMENTS
}}) {
1920 if (util
::has_property
($e, "in")) {
1921 ParseFunctionElementPull
($e, "in");
1923 # we need to allocate any reference output variables, so that
1924 # a dcerpc backend can be sure they are non-null
1925 if (util
::has_property
($e, "out") && util
::has_property
($e, "ref")) {
1926 AllocateRefVars
($e);
1930 foreach my $e (@
{$fn->{ELEMENTS
}}) {
1931 if (util
::has_property
($e, "in")) {
1932 CheckArraySizes
($e, "r->in.");
1937 pidl
"if (!(flags & NDR_OUT)) goto done;";
1940 foreach my $e (@
{$fn->{ELEMENTS
}}) {
1941 if (util
::has_property
($e, "out")) {
1942 ParseFunctionElementPull
($e, "out");
1946 foreach my $e (@
{$fn->{ELEMENTS
}}) {
1947 if (util
::has_property
($e, "out")) {
1948 CheckArraySizes
($e, "r->out.");
1952 if ($fn->{RETURN_TYPE
} && $fn->{RETURN_TYPE
} ne "void") {
1953 pidl
"NDR_CHECK(ndr_pull_$fn->{RETURN_TYPE}(ndr, NDR_SCALARS, &r->out.result));";
1958 pidl
"return NT_STATUS_OK;";
1964 #####################################################################
1965 # produce a function call table
1966 sub FunctionTable
($)
1968 my($interface) = shift;
1969 my($data) = $interface->{INHERITED_DATA
};
1971 my $uname = uc $interface->{NAME
};
1973 foreach my $d (@
{$data}) {
1974 if ($d->{TYPE
} eq "FUNCTION") { $count++; }
1977 return if ($count == 0);
1979 pidl
"static const struct dcerpc_interface_call $interface->{NAME}\_calls[] = {";
1980 foreach my $d (@
{$data}) {
1981 if ($d->{TYPE
} eq "FUNCTION") {
1983 pidl
"\t\t\"$d->{NAME}\",";
1984 pidl
"\t\tsizeof(struct $d->{NAME}),";
1985 pidl
"\t\t(ndr_push_flags_fn_t) ndr_push_$d->{NAME},";
1986 pidl
"\t\t(ndr_pull_flags_fn_t) ndr_pull_$d->{NAME},";
1987 pidl
"\t\t(ndr_print_function_t) ndr_print_$d->{NAME}";
1991 pidl
"\t{ NULL, 0, NULL, NULL, NULL }";
1995 # If no endpoint is set, default to the interface name as a named pipe
1996 if (! defined $interface->{PROPERTIES
}->{endpoint
}) {
1997 $interface->{PROPERTIES
}->{endpoint
} = "\"ncacn_np:[\\\\pipe\\\\" . $interface->{NAME
} . "]\"";
2000 my @e = split / /, $interface->{PROPERTIES
}->{endpoint
};
2001 my $endpoint_count = $#e + 1;
2003 pidl
"static const char * const $interface->{NAME}\_endpoint_strings[] = {";
2004 foreach my $ep (@e) {
2010 pidl
"static const struct dcerpc_endpoint_list $interface->{NAME}\_endpoints = {";
2011 pidl
"\t.count\t= $endpoint_count,";
2012 pidl
"\t.names\t= $interface->{NAME}\_endpoint_strings";
2016 if (! defined $interface->{PROPERTIES
}->{authservice
}) {
2017 $interface->{PROPERTIES
}->{authservice
} = "\"host\"";
2020 my @a = split / /, $interface->{PROPERTIES
}->{authservice
};
2021 my $authservice_count = $#a + 1;
2023 pidl
"static const char * const $interface->{NAME}\_authservice_strings[] = {";
2024 foreach my $ap (@a) {
2030 pidl
"static const struct dcerpc_authservice_list $interface->{NAME}\_authservices = {";
2031 pidl
"\t.count\t= $endpoint_count,";
2032 pidl
"\t.names\t= $interface->{NAME}\_authservice_strings";
2036 pidl
"\nconst struct dcerpc_interface_table dcerpc_table_$interface->{NAME} = {";
2037 pidl
"\t.name\t\t= \"$interface->{NAME}\",";
2038 pidl
"\t.uuid\t\t= DCERPC_$uname\_UUID,";
2039 pidl
"\t.if_version\t= DCERPC_$uname\_VERSION,";
2040 pidl
"\t.helpstring\t= DCERPC_$uname\_HELPSTRING,";
2041 pidl
"\t.num_calls\t= $count,";
2042 pidl
"\t.calls\t\t= $interface->{NAME}\_calls,";
2043 pidl
"\t.endpoints\t= &$interface->{NAME}\_endpoints,";
2044 pidl
"\t.authservices\t= &$interface->{NAME}\_authservices";
2048 pidl
"static NTSTATUS dcerpc_ndr_$interface->{NAME}_init(void)";
2050 pidl
"\treturn librpc_register_interface(&dcerpc_table_$interface->{NAME});";
2055 #####################################################################
2056 # parse the interface definitions
2057 sub ParseInterface
($)
2059 my($interface) = shift;
2060 my($data) = $interface->{DATA
};
2063 foreach my $d (@
{$data}) {
2064 ($d->{TYPE
} eq "TYPEDEF") &&
2065 ParseTypedefPush
($d);
2066 ($d->{TYPE
} eq "FUNCTION") &&
2067 ParseFunctionPush
($d);
2071 foreach my $d (@
{$data}) {
2072 ($d->{TYPE
} eq "TYPEDEF") &&
2073 ParseTypedefPull
($d);
2074 ($d->{TYPE
} eq "FUNCTION") &&
2075 ParseFunctionPull
($d);
2079 foreach my $d (@
{$data}) {
2080 ($d->{TYPE
} eq "TYPEDEF") &&
2081 ParseTypedefPrint
($d);
2082 ($d->{TYPE
} eq "FUNCTION") &&
2083 ParseFunctionPrint
($d);
2087 foreach my $d (@
{$data}) {
2088 ($d->{TYPE
} eq "TYPEDEF") &&
2089 ParseTypedefNdrSize
($d);
2092 FunctionTable
($interface);
2095 sub RegistrationFunction
($$)
2098 my $filename = shift;
2100 $filename =~ /.*\/ndr_
(.*).c
/;
2102 pidl
"NTSTATUS dcerpc_$basename\_init(void)";
2105 pidl
"NTSTATUS status = NT_STATUS_OK;";
2106 foreach my $interface (@
{$idl}) {
2107 next if $interface->{TYPE
} ne "INTERFACE";
2109 my $data = $interface->{INHERITED_DATA
};
2111 foreach my $d (@
{$data}) {
2112 if ($d->{TYPE
} eq "FUNCTION") { $count++; }
2115 next if ($count == 0);
2117 pidl
"status = dcerpc_ndr_$interface->{NAME}_init();";
2118 pidl
"if (NT_STATUS_IS_ERR(status)) {";
2119 pidl
"\treturn status;";
2123 pidl
"return status;";
2129 sub CheckPointerTypes
($$)
2132 my $default = shift;
2134 foreach my $e (@
{$s->{ELEMENTS
}}) {
2135 if ($e->{POINTERS
}) {
2136 if (not defined(pointer_type
($e))) {
2137 $e->{PROPERTIES
}->{$default} = 1;
2140 if (pointer_type
($e) eq "ptr") {
2141 print "Warning: ptr is not supported by pidl yet\n";
2147 sub LoadInterface
($)
2151 if (not util
::has_property
($x, "pointer_default")) {
2152 # MIDL defaults to "ptr" in DCE compatible mode (/osf)
2153 # and "unique" in Microsoft Extensions mode (default)
2154 $x->{PROPERTIES
}->{pointer_default
} = "unique";
2157 foreach my $d (@
{$x->{DATA
}}) {
2158 if (($d->{TYPE
} eq "DECLARE") or ($d->{TYPE
} eq "TYPEDEF")) {
2159 if ($d->{DATA
}->{TYPE
} eq "STRUCT" or $d->{DATA
}->{TYPE
} eq "UNION") {
2160 CheckPointerTypes
($d->{DATA
}, $x->{PROPERTIES
}->{pointer_default
});
2163 if (defined($d->{PROPERTIES
}) && !defined($d->{DATA
}->{PROPERTIES
})) {
2164 $d->{DATA
}->{PROPERTIES
} = $d->{PROPERTIES
};
2167 if ($d->{TYPE
} eq "FUNCTION") {
2168 CheckPointerTypes
($d,
2169 $x->{PROPERTIES
}->{pointer_default
} # MIDL defaults to "ref"
2179 foreach my $x (@
{$idl}) {
2184 #####################################################################
2185 # parse a parsed IDL structure back into an IDL file
2189 my($filename) = shift;
2190 my $h_filename = $filename;
2195 if ($h_filename =~ /(.*)\.c/) {
2196 $h_filename = "$1.h";
2199 pidl
"/* parser auto-generated by pidl */";
2201 pidl
"#include \"includes.h\"";
2202 pidl
"#include \"$h_filename\"";
2205 foreach my $x (@
{$idl}) {
2206 if ($x->{TYPE
} eq "INTERFACE") {
2207 needed
::BuildNeeded
($x);
2212 RegistrationFunction
($idl, $filename);