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
21 return $typefamily{$n};
24 # determine if an element needs a "buffers" section in NDR
25 sub need_buffers_section($)
28 if (!Ndr::can_contain_deferred($e) &&
29 !util::array_size($e)) {
35 # see if a variable needs to be allocated by the NDR subsystem on pull
40 return 0 if (util::has_property($e, "ref") && $e->{PARENT}->{TYPE} eq "FUNCTION");
41 return 1 if ($e->{POINTERS} || util::array_size($e));
45 # Prefix to get the actual value of a variable
50 foreach my $i (Ndr::need_wire_pointer($e)..$e->{POINTERS}-1) { $pointers.="*"; }
54 # determine the C prefix used to refer to a variable when passing to a push
55 # function. This will be '*' for pointers to scalar types, '' for scalar
56 # types and normal pointers and '&' for pass-by-reference structures
63 if ($e->{TYPE} =~ "string") {
65 } elsif (Ndr::is_scalar_type($e->{TYPE}) and $e->{POINTERS} and
66 !util::array_size($e)) {
68 } elsif (!Ndr::is_scalar_type($e->{TYPE}) &&
70 !util::array_size($e)) {
74 foreach my $i (2..$e->{POINTERS}) { $ret.="*"; }
79 # determine the C prefix used to refer to a variable when passing to a pull
85 if (!$e->{POINTERS} && !util::array_size($e)) {
89 if ($e->{TYPE} =~ "string") {
94 foreach my $i (2..$e->{POINTERS}) { $ret.="*"; }
116 $tabs = substr($tabs, 0, -1);
119 ####################################################################
120 # work out the name of a size_is() variable
125 my($var_prefix) = shift;
127 my($fn) = $e->{PARENT};
129 return $size if (util::is_constant($size));
131 return $size if ($size =~ /ndr->|\(/);
135 if ($size =~ /\*(.*)/) {
140 if ($fn->{TYPE} ne "FUNCTION") {
141 return $prefix . "r->$size";
144 my $e2 = util::find_sibling($e, $size);
146 die("Invalid sibling '$size'") unless defined($e2);
148 if (util::has_property($e2, "in") && util::has_property($e2, "out")) {
149 return $prefix . "$var_prefix$size";
152 if (util::has_property($e2, "in")) {
153 return $prefix . "r->in.$size";
156 if (util::has_property($e2, "out")) {
157 return $prefix . "r->out.$size";
160 die "invalid variable in $size for element $e->{NAME} in $fn->{NAME}\n";
163 #####################################################################
164 # check that a variable we get from ParseExpr isn't a null pointer
165 sub check_null_pointer($)
168 if ($size =~ /^\*/) {
169 my $size2 = substr($size, 1);
170 pidl "if ($size2 == NULL) return NT_STATUS_INVALID_PARAMETER_MIX;";
174 #####################################################################
175 # check that a variable we get from ParseExpr isn't a null pointer
176 # void return varient
177 sub check_null_pointer_void($)
180 if ($size =~ /^\*/) {
181 my $size2 = substr($size, 1);
182 pidl "if ($size2 == NULL) return;";
186 #####################################################################
187 # work out is a parse function should be declared static or not
192 if ($fn->{TYPE} eq "TYPEDEF" or
193 $fn->{TYPE} eq "FUNCTION") {
194 return "" if (util::has_property($fn, "public"));
200 ###################################################################
201 # setup any special flags for an element or structure
205 my $flags = util::has_property($e, "flag");
206 if (defined $flags) {
207 pidl "{ uint32_t _flags_save_$e->{TYPE} = ndr->flags;";
208 pidl "ndr_set_flags(&ndr->flags, $flags);";
212 ###################################################################
213 # end any special flags for an element or structure
217 my $flags = util::has_property($e, "flag");
218 if (defined $flags) {
219 pidl "ndr->flags = _flags_save_$e->{TYPE};\n\t}";
223 #####################################################################
224 # parse array preceding data - push side
225 sub ParseArrayPushPreceding($$$)
228 my $var_prefix = shift;
229 my $ndr_flags = shift;
231 my $size = ParseExpr($e, util::array_size($e), $var_prefix);
233 if (!Ndr::is_inline_array($e)) {
234 # we need to emit the array size
235 pidl "NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, $size));";
239 #####################################################################
240 # parse the data of an array - push side
241 sub ParseArrayPush($$$$)
245 my $var_prefix = shift;
246 my $ndr_flags = shift;
247 my $cprefix = c_push_prefix($e);
249 my $size = ParseExpr($e, util::array_size($e), $var_prefix);
251 # See whether the array size has been pushed yet
252 if (!Ndr::is_surrounding_array($e)) {
253 ParseArrayPushPreceding($e, $var_prefix, $ndr_flags);
256 if (Ndr::is_varying_array($e)) {
257 my $length = util::has_property($e, "length_is");
258 $length = ParseExpr($e, $length, $var_prefix);
259 pidl "NDR_CHECK(ndr_push_uint32($ndr, NDR_SCALARS, 0));";
260 pidl "NDR_CHECK(ndr_push_uint32($ndr, NDR_SCALARS, $length));";
264 if (Ndr::is_scalar_type($e->{TYPE})) {
265 pidl "NDR_CHECK(ndr_push_array_$e->{TYPE}($ndr, $ndr_flags, $cprefix$var_prefix$e->{NAME}, $size));";
267 pidl "NDR_CHECK(ndr_push_array($ndr, $ndr_flags, $cprefix$var_prefix$e->{NAME}, sizeof($cprefix$var_prefix$e->{NAME}\[0]), $size, (ndr_push_flags_fn_t)ndr_push_$e->{TYPE}));";
271 #####################################################################
273 sub ParseArrayPrint($$)
276 my $var_prefix = shift;
277 my $size = ParseExpr($e, util::array_size($e), $var_prefix);
278 my $cprefix = c_push_prefix($e);
280 if (Ndr::is_varying_array($e)) {
281 $size = ParseExpr($e, util::has_property($e, "length_is"), $var_prefix);
284 if (Ndr::is_scalar_type($e->{TYPE})) {
285 pidl "ndr_print_array_$e->{TYPE}(ndr, \"$e->{NAME}\", $cprefix$var_prefix$e->{NAME}, $size);";
287 pidl "ndr_print_array(ndr, \"$e->{NAME}\", $cprefix$var_prefix$e->{NAME}, sizeof($cprefix$var_prefix$e->{NAME}\[0]), $size, (ndr_print_fn_t)ndr_print_$e->{TYPE});";
291 #####################################################################
292 # check the size_is and length_is constraints
293 sub CheckArraySizes($$)
296 my $var_prefix = shift;
298 if (Ndr::is_conformant_array($e)) {
299 my $size = ParseExpr($e, util::array_size($e), $var_prefix);
300 pidl "if ($var_prefix$e->{NAME}) {";
302 check_null_pointer($size);
303 pidl "NDR_CHECK(ndr_check_array_size(ndr, (void*)&$var_prefix$e->{NAME}, $size));";
308 if (Ndr::is_varying_array($e)) {
309 my $length = util::has_property($e, "length_is");
310 $length = ParseExpr($e, $length, $var_prefix);
311 pidl "if ($var_prefix$e->{NAME}) {";
313 check_null_pointer($length);
314 pidl "NDR_CHECK(ndr_check_array_length(ndr, (void*)&$var_prefix$e->{NAME}, $length));";
320 sub ParseArrayPullPreceding($$$)
323 my $var_prefix = shift;
324 my $ndr_flags = shift;
326 if (!Ndr::is_inline_array($e)) {
327 # non fixed arrays encode the size just before the array
328 pidl "NDR_CHECK(ndr_pull_array_size(ndr, &$var_prefix$e->{NAME}));";
332 #####################################################################
333 # parse an array - pull side
334 sub ParseArrayPull($$$$)
338 my $var_prefix = shift;
339 my $ndr_flags = shift;
341 my $cprefix = c_pull_prefix($e);
342 my $length = ParseExpr($e, util::array_size($e), $var_prefix);
345 if (Ndr::is_conformant_array($e)) {
346 $length = $size = "ndr_get_array_size($ndr, &$var_prefix$e->{NAME})";
349 # if this is a conformant array then we use that size to allocate, and make sure
350 # we allocate enough to pull the elements
351 if (!Ndr::is_inline_array($e) and not Ndr::is_surrounding_array($e)) {
352 if ($var_prefix =~ /^r->out/ && $length =~ /^\*r->in/) {
353 my $length2 = substr($length, 1);
354 pidl "if (ndr->flags & LIBNDR_FLAG_REF_ALLOC) { NDR_ALLOC($ndr, $length2); }";
357 ParseArrayPullPreceding($e, $var_prefix, $ndr_flags);
360 if (Ndr::is_varying_array($e)) {
361 pidl "NDR_CHECK(ndr_pull_array_length($ndr, &$var_prefix$e->{NAME}));";
362 $length = "ndr_get_array_length($ndr, &$var_prefix$e->{NAME})";
365 check_null_pointer($length);
367 if ($length ne $size) {
368 pidl "if ($length > $size) {";
370 pidl "return ndr_pull_error($ndr, NDR_ERR_CONFORMANT_SIZE, \"Bad conformant size %u should be %u\", $size, $length);";
375 if ((need_alloc($e) && !Ndr::is_fixed_array($e)) ||
376 ($var_prefix eq "r->in." && util::has_property($e, "ref"))) {
377 if (!Ndr::is_inline_array($e) || $ndr_flags eq "NDR_SCALARS") {
378 pidl "NDR_ALLOC_N($ndr, $var_prefix$e->{NAME}, $size);";
382 if (($var_prefix eq "r->out." && util::has_property($e, "ref"))) {
383 if (!Ndr::is_inline_array($e) || $ndr_flags eq "NDR_SCALARS") {
384 pidl "if ($ndr->flags & LIBNDR_FLAG_REF_ALLOC) {";
385 pidl "\tNDR_ALLOC_N($ndr, $var_prefix$e->{NAME}, $size);";
390 if (Ndr::is_scalar_type($e->{TYPE})) {
391 pidl "NDR_CHECK(ndr_pull_array_$e->{TYPE}($ndr, $ndr_flags, $cprefix$var_prefix$e->{NAME}, $length));";
393 pidl "NDR_CHECK(ndr_pull_array($ndr, $ndr_flags, (void **)$cprefix$var_prefix$e->{NAME}, sizeof($cprefix$var_prefix$e->{NAME}\[0]), $length, (ndr_pull_flags_fn_t)ndr_pull_$e->{TYPE}));";
397 sub compression_alg($)
400 my $compression = util::has_property($e, "compression");
401 my ($alg, $clen, $dlen) = split(/ /, $compression);
406 sub compression_clen($)
409 my $compression = util::has_property($e, "compression");
410 my ($alg, $clen, $dlen) = split(/ /, $compression);
412 return ParseExpr($e, $clen, "r->");
415 sub compression_dlen($)
418 my $compression = util::has_property($e, "compression");
419 my ($alg, $clen, $dlen) = split(/ /, $compression);
421 return ParseExpr($e, $dlen, "r->");
424 sub ParseCompressionPushStart($$)
428 my $comndr = $subndr."_compressed";
432 pidl "struct ndr_push *$comndr;";
434 pidl "$comndr = ndr_push_init_ctx($subndr);";
435 pidl "if (!$comndr) return NT_STATUS_NO_MEMORY;";
436 pidl "$comndr->flags = $subndr->flags;";
442 sub ParseCompressionPushEnd($$)
446 my $comndr = $subndr."_compressed";
447 my $alg = compression_alg($e);
449 pidl "NDR_CHECK(ndr_push_compression($subndr, $comndr, $alg));";
454 sub ParseCompressionPullStart($$)
458 my $comndr = $subndr."_compressed";
459 my $alg = compression_alg($e);
460 my $dlen = compression_dlen($e);
464 pidl "struct ndr_pull *$comndr;";
465 pidl "NDR_ALLOC($subndr, $comndr);";
466 pidl "NDR_CHECK(ndr_pull_compression($subndr, $comndr, $alg, $dlen));";
471 sub ParseCompressionPullEnd($$)
475 my $comndr = $subndr."_compressed";
481 sub ParseObfuscationPushStart($$)
491 sub ParseObfuscationPushEnd($$)
495 my $obfuscation = util::has_property($e, "obfuscation");
497 pidl "NDR_CHECK(ndr_push_obfuscation($ndr, $obfuscation));";
500 sub ParseObfuscationPullStart($$)
504 my $obfuscation = util::has_property($e, "obfuscation");
506 pidl "NDR_CHECK(ndr_pull_obfuscation($ndr, $obfuscation));";
511 sub ParseObfuscationPullEnd($$)
519 sub ParseSubcontextPushStart($$)
522 my $ndr_flags = shift;
523 my $compression = util::has_property($e, "compression");
524 my $obfuscation = util::has_property($e, "obfuscation");
525 my $retndr = "_ndr_$e->{NAME}";
527 pidl "if (($ndr_flags) & NDR_SCALARS) {";
529 pidl "struct ndr_push *$retndr;";
531 pidl "$retndr = ndr_push_init_ctx(ndr);";
532 pidl "if (!$retndr) return NT_STATUS_NO_MEMORY;";
533 pidl "$retndr->flags = ndr->flags;";
536 if (defined $compression) {
537 $retndr = ParseCompressionPushStart($e, $retndr);
540 if (defined $obfuscation) {
541 $retndr = ParseObfuscationPushStart($e, $retndr);
547 sub ParseSubcontextPushEnd($)
550 my $header_size = util::has_property($e, "subcontext");
551 my $size_is = util::has_property($e, "subcontext_size");
552 my $compression = util::has_property($e, "compression");
553 my $obfuscation = util::has_property($e, "obfuscation");
554 my $ndr = "_ndr_$e->{NAME}";
556 if (defined $obfuscation) {
557 ParseObfuscationPushEnd($e, $ndr);
560 if (defined $compression) {
561 ParseCompressionPushEnd($e, $ndr);
564 if (not defined($size_is)) {
568 pidl "NDR_CHECK(ndr_push_subcontext_header(ndr, $header_size, $size_is, $ndr));";
569 pidl "NDR_CHECK(ndr_push_bytes(ndr, $ndr->data, $ndr->offset));";
574 sub ParseSubcontextPullStart($$)
577 my $ndr_flags = shift;
578 my $header_size = util::has_property($e, "subcontext");
579 my $size_is = util::has_property($e, "subcontext_size");
580 my $compression = util::has_property($e, "compression");
581 my $obfuscation = util::has_property($e, "obfuscation");
582 my $retndr = "_ndr_$e->{NAME}";
584 if (not defined($size_is)) {
588 pidl "if (($ndr_flags) & NDR_SCALARS) {";
590 pidl "struct ndr_pull *$retndr;";
591 pidl "NDR_ALLOC(ndr, $retndr);";
592 pidl "NDR_CHECK(ndr_pull_subcontext_header(ndr, $header_size, $size_is, $retndr));";
594 if (defined $compression) {
595 $retndr = ParseCompressionPullStart($e, $retndr);
598 if (defined $obfuscation) {
599 $retndr = ParseObfuscationPullStart($e, $retndr);
605 sub ParseSubcontextPullEnd($)
608 my $header_size = util::has_property($e, "subcontext");
609 my $size_is = util::has_property($e, "subcontext_size");
610 my $compression = util::has_property($e, "compression");
611 my $obfuscation = util::has_property($e, "obfuscation");
612 my $ndr = "_ndr_$e->{NAME}";
614 if (defined $obfuscation) {
615 ParseObfuscationPullEnd($e, $ndr);
618 if (defined $compression) {
619 ParseCompressionPullEnd($e, $ndr);
623 if (defined ($size_is)) {
624 $advance = "$size_is";
625 } elsif ($header_size) {
626 $advance = "$ndr->data_size";
628 $advance = "$ndr->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");
650 if (my $value = util::has_property($e, "value")) {
651 pidl "$cprefix$var_prefix$e->{NAME} = $value;";
654 if (defined $sub_size and $e->{POINTERS} == 0) {
655 $subndr = ParseSubcontextPushStart($e, "NDR_SCALARS");
659 if (Ndr::need_wire_pointer($e)) {
660 ParsePtrPush($e, $ptr_prefix.$var_prefix);
661 } elsif (Ndr::is_inline_array($e)) {
662 ParseArrayPush($e, $ndr, "r->", "NDR_SCALARS");
663 } elsif (need_alloc($e)) {
664 # no scalar component
666 if (my $switch = util::has_property($e, "switch_is")) {
667 ParseSwitchPush($e, $ndr, $var_prefix, $ndr_flags, $switch);
670 pidl "NDR_CHECK(ndr_push_$e->{TYPE}($ndr, $ndr_flags, $cprefix$var_prefix$e->{NAME}));";
673 if (defined $sub_size and $e->{POINTERS} == 0) {
674 ParseSubcontextPushEnd($e);
680 #####################################################################
681 # parse a pointer in a struct element or function
685 my $var_prefix = shift;
687 if (util::has_property($e, "ref")) {
688 pidl "NDR_CHECK(ndr_push_ref_ptr(ndr, $var_prefix$e->{NAME}));";
689 } elsif (util::has_property($e, "relative")) {
690 pidl "NDR_CHECK(ndr_push_relative_ptr1(ndr, $var_prefix$e->{NAME}));";
692 pidl "NDR_CHECK(ndr_push_unique_ptr(ndr, $var_prefix$e->{NAME}));";
696 #####################################################################
697 # print scalars in a structure element
698 sub ParseElementPrint($$)
701 my($var_prefix) = shift;
702 my $cprefix = c_push_prefix($e);
703 my $ptr_prefix = c_ptr_prefix($e);
705 return if (util::has_property($e, "noprint"));
707 if (my $value = util::has_property($e, "value")) {
708 pidl "if (ndr->flags & LIBNDR_PRINT_SET_VALUES) {";
709 pidl "\t$cprefix$var_prefix$e->{NAME} = $value;";
713 my $l = $e->{POINTERS};
714 $l++ if (util::array_size($e) and $l == 0 and !Ndr::is_fixed_array($e));
716 foreach my $i (1..$l) {
717 pidl "ndr_print_ptr(ndr, \"$e->{NAME}\", $var_prefix$e->{NAME});";
718 pidl "ndr->depth++;";
719 if ($i > $l-Ndr::need_wire_pointer($e)) {
720 pidl "if ($ptr_prefix$var_prefix$e->{NAME}) {";
725 if (util::array_size($e)) {
726 ParseArrayPrint($e, $var_prefix)
728 if (my $switch = util::has_property($e, "switch_is")) {
729 my $switch_var = ParseExpr($e, $switch, $var_prefix);
730 check_null_pointer_void($switch_var);
732 pidl "ndr_print_set_switch_value(ndr, $cprefix$var_prefix$e->{NAME}, $switch_var);";
735 pidl "ndr_print_$e->{TYPE}(ndr, \"$e->{NAME}\", $cprefix$var_prefix$e->{NAME});";
738 foreach my $i (1..$l) {
739 if ($i > $l-Ndr::need_wire_pointer($e)) {
743 pidl "ndr->depth--;";
747 #####################################################################
748 # parse scalars in a structure element - pull size
749 sub ParseSwitchPull($$$$$)
753 my($var_prefix) = shift;
754 my($ndr_flags) = shift;
756 my $switch_var = ParseExpr($e, $switch, $var_prefix);
758 my $cprefix = c_pull_prefix($e);
760 my $utype = typelist::getType($e->{TYPE});
762 check_null_pointer($switch_var);
764 pidl "NDR_CHECK(ndr_pull_set_switch_value($ndr, $cprefix$var_prefix$e->{NAME}, $switch_var));";
768 #####################################################################
769 # push switch element
770 sub ParseSwitchPush($$$$$)
774 my($var_prefix) = shift;
775 my($ndr_flags) = shift;
777 my $switch_var = ParseExpr($e, $switch, $var_prefix);
778 my $cprefix = c_push_prefix($e);
780 check_null_pointer($switch_var);
782 pidl "NDR_CHECK(ndr_push_set_switch_value($ndr, $cprefix$var_prefix$e->{NAME}, $switch_var));";
786 #####################################################################
787 # parse scalars in a structure element - pull size
788 sub ParseElementPullScalar($$$)
791 my($var_prefix) = shift;
792 my($ndr_flags) = shift;
793 my $cprefix = c_pull_prefix($e);
794 my $ptr_prefix = c_ptr_prefix($e);
795 my $sub_size = util::has_property($e, "subcontext");
801 if (defined $sub_size && $e->{POINTERS} == 0) {
802 $subndr = ParseSubcontextPullStart($e, $ndr_flags);
804 $ndr_flags = "NDR_SCALARS|NDR_BUFFERS";
807 if (Ndr::is_inline_array($e)) {
808 ParseArrayPull($e, $ndr, "r->", "NDR_SCALARS");
809 } elsif (Ndr::need_wire_pointer($e)) {
810 ParsePtrPull($e, $ptr_prefix.$var_prefix);
811 } elsif (Ndr::is_surrounding_array($e)) {
813 if (my $switch = util::has_property($e, "switch_is")) {
814 ParseSwitchPull($e, $ndr, $var_prefix, $ndr_flags, $switch);
817 pidl "NDR_CHECK(ndr_pull_$e->{TYPE}($ndr, $ndr_flags, $cprefix$var_prefix$e->{NAME}));";
820 if (my $range = util::has_property($e, "range")) {
821 my ($low, $high) = split(/ /, $range, 2);
822 pidl "if ($var_prefix$e->{NAME} < $low || $var_prefix$e->{NAME} > $high) {";
823 pidl "\treturn ndr_pull_error($ndr, NDR_ERR_RANGE, \"value out of range\");";
827 if (defined $sub_size && $e->{POINTERS} == 0) {
828 ParseSubcontextPullEnd($e);
834 #####################################################################
835 # parse a pointer in a struct element or function
839 my($var_prefix) = shift;
841 if (util::has_property($e, "ref")) {
842 pidl "NDR_CHECK(ndr_pull_ref_ptr(ndr, &_ptr_$e->{NAME}));";
844 pidl "NDR_CHECK(ndr_pull_unique_ptr(ndr, &_ptr_$e->{NAME}));";
846 pidl "if (_ptr_$e->{NAME}) {";
848 pidl "NDR_ALLOC(ndr, $var_prefix$e->{NAME});";
849 if (util::has_property($e, "relative")) {
850 pidl "NDR_CHECK(ndr_pull_relative_ptr1(ndr, $var_prefix$e->{NAME}, _ptr_$e->{NAME}));";
854 pidl "\t$var_prefix$e->{NAME} = NULL;";
858 #####################################################################
859 # parse buffers in a structure element
860 sub ParseElementPushBuffer($$)
863 my($var_prefix) = shift;
864 my $cprefix = c_push_prefix($e);
865 my $sub_size = util::has_property($e, "subcontext");
869 return unless (need_buffers_section($e));
873 my $pointers = c_ptr_prefix($e);
874 for my $i (1..Ndr::need_wire_pointer($e)) {
876 ParsePtrPush($e,$pointers.$var_prefix);
878 pidl "if ($pointers$var_prefix$e->{NAME}) {";
883 if (util::has_property($e, "relative")) {
884 pidl "NDR_CHECK(ndr_push_relative_ptr2(ndr, $var_prefix$e->{NAME}));";
887 my $ndr_flags = "NDR_BUFFERS";
888 if ($e->{POINTERS} || (util::array_size($e) && !Ndr::is_inline_array($e)))
890 $ndr_flags="NDR_SCALARS|$ndr_flags"
893 if (defined $sub_size) {
894 $subndr = ParseSubcontextPushStart($e, $ndr_flags);
896 $ndr_flags = "NDR_SCALARS|NDR_BUFFERS";
899 if (util::array_size($e)) {
900 ParseArrayPush($e, $ndr, "r->", $ndr_flags);
902 if (my $switch = util::has_property($e, "switch_is")) {
903 ParseSwitchPush($e, $ndr, $var_prefix, $ndr_flags, $switch);
906 pidl "NDR_CHECK(ndr_push_$e->{TYPE}($ndr, $ndr_flags, $cprefix$var_prefix$e->{NAME}));";
909 if (defined $sub_size) {
910 ParseSubcontextPushEnd($e);
913 for my $i (1..Ndr::need_wire_pointer($e)) {
921 #####################################################################
922 # parse buffers in a structure element - pull side
923 sub ParseElementPullBuffer($$)
926 my($var_prefix) = shift;
927 my $cprefix = c_pull_prefix($e);
928 my $sub_size = util::has_property($e, "subcontext");
932 return unless (need_buffers_section($e));
936 my $pointers = c_ptr_prefix($e);
937 for my $i (1..Ndr::need_wire_pointer($e)) {
939 ParsePtrPull($e,$pointers.$var_prefix);
941 pidl "if ($pointers$var_prefix$e->{NAME}) {";
946 if (util::has_property($e, "relative")) {
947 pidl "struct ndr_pull_save _relative_save;";
948 pidl "ndr_pull_save(ndr, &_relative_save);";
949 pidl "NDR_CHECK(ndr_pull_relative_ptr2(ndr, $var_prefix$e->{NAME}));";
952 my $ndr_flags = "NDR_BUFFERS";
953 if ($e->{POINTERS} || (util::array_size($e) && !Ndr::is_inline_array($e)))
955 $ndr_flags="NDR_SCALARS|$ndr_flags"
958 if (defined $sub_size) {
959 $subndr = ParseSubcontextPullStart($e, $ndr_flags);
961 $ndr_flags = "NDR_SCALARS|NDR_BUFFERS";
964 if (util::array_size($e)) {
965 ParseArrayPull($e, $ndr, "r->", $ndr_flags);
967 if (my $switch = util::has_property($e, "switch_is")) {
968 ParseSwitchPull($e, $ndr, $var_prefix, $ndr_flags, $switch);
971 pidl "NDR_CHECK(ndr_pull_$e->{TYPE}($ndr, $ndr_flags, $cprefix$var_prefix$e->{NAME}));";
974 if (defined $sub_size) {
975 ParseSubcontextPullEnd($e);
978 if (util::has_property($e, "relative")) {
979 pidl "ndr_pull_restore(ndr, &_relative_save);";
982 for my $i (1..Ndr::need_wire_pointer($e)) {
990 #####################################################################
992 sub ParseStructPush($)
996 return unless defined($struct->{ELEMENTS});
998 start_flags($struct);
1000 # see if the structure contains a conformant array. If it
1001 # does, then it must be the last element of the structure, and
1002 # we need to push the conformant length early, as it fits on
1003 # the wire before the structure (and even before the structure
1005 my $e = $struct->{ELEMENTS}[-1];
1006 if (Ndr::is_conformant_array($e) and Ndr::is_surrounding_array($e)) {
1007 ParseArrayPushPreceding($e, "r->", "NDR_SCALARS");
1010 if (defined $e->{TYPE} && $e->{TYPE} eq "string"
1011 && util::property_matches($e, "flag", ".*LIBNDR_FLAG_STR_CONFORMANT.*")) {
1012 pidl "NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_string_array_size(ndr, r->$e->{NAME})));";
1015 pidl "if (!(ndr_flags & NDR_SCALARS)) goto buffers;";
1017 pidl "NDR_CHECK(ndr_push_struct_start(ndr));";
1019 my $align = Ndr::find_largest_alignment($struct);
1020 pidl "NDR_CHECK(ndr_push_align(ndr, $align));";
1022 foreach my $e (@{$struct->{ELEMENTS}}) {
1023 ParseElementPushScalar($e, "r->", "NDR_SCALARS");
1027 pidl "if (!(ndr_flags & NDR_BUFFERS)) goto done;";
1028 foreach my $e (@{$struct->{ELEMENTS}}) {
1029 ParseElementPushBuffer($e, "r->");
1032 pidl "ndr_push_struct_end(ndr);";
1039 #####################################################################
1040 # generate a push function for an enum
1041 sub ParseEnumPush($)
1044 my($type_fn) = typelist::enum_type_fn($enum);
1048 pidl "NDR_CHECK(ndr_push_$type_fn(ndr, NDR_SCALARS, r));";
1053 #####################################################################
1054 # generate a pull function for an enum
1055 sub ParseEnumPull($)
1058 my($type_fn) = typelist::enum_type_fn($enum);
1059 my($type_v_decl) = typelist::mapScalarType(typelist::enum_type_fn($enum));
1061 pidl "$type_v_decl v;";
1063 pidl "NDR_CHECK(ndr_pull_$type_fn(ndr, NDR_SCALARS, &v));";
1069 #####################################################################
1070 # generate a print function for an enum
1071 sub ParseEnumPrint($)
1075 pidl "const char *val = NULL;";
1080 pidl "switch (r) {";
1082 my $els = \@{$enum->{ELEMENTS}};
1083 foreach my $i (0 .. $#{$els}) {
1084 my $e = ${$els}[$i];
1086 if ($e =~ /^(.*)=/) {
1089 pidl "case $e: val = \"$e\"; break;";
1095 pidl "ndr_print_enum(ndr, name, \"$enum->{TYPE}\", val, r);";
1103 return "struct ndr_push *ndr, int ndr_flags, enum $e->{NAME} r";
1106 sub ArgsEnumPrint($)
1109 return "struct ndr_print *ndr, const char *name, enum $e->{NAME} r";
1115 return "struct ndr_pull *ndr, int ndr_flags, enum $e->{NAME} *r";
1118 $typefamily{ENUM} = {
1119 PUSH_FN_BODY => \&ParseEnumPush,
1120 PUSH_FN_ARGS => \&ArgsEnumPush,
1121 PULL_FN_BODY => \&ParseEnumPull,
1122 PULL_FN_ARGS => \&ArgsEnumPull,
1123 PRINT_FN_BODY => \&ParseEnumPrint,
1124 PRINT_FN_ARGS => \&ArgsEnumPrint,
1127 #####################################################################
1128 # generate a push function for a bitmap
1129 sub ParseBitmapPush($)
1131 my($bitmap) = shift;
1132 my($type_fn) = typelist::bitmap_type_fn($bitmap);
1134 start_flags($bitmap);
1136 pidl "NDR_CHECK(ndr_push_$type_fn(ndr, NDR_SCALARS, r));";
1141 #####################################################################
1142 # generate a pull function for an bitmap
1143 sub ParseBitmapPull($)
1145 my($bitmap) = shift;
1146 my($type_fn) = typelist::bitmap_type_fn($bitmap);
1147 my($type_decl) = typelist::mapType($bitmap);
1149 pidl "$type_decl v;";
1150 start_flags($bitmap);
1151 pidl "NDR_CHECK(ndr_pull_$type_fn(ndr, NDR_SCALARS, &v));";
1157 #####################################################################
1158 # generate a print function for an bitmap
1159 sub ParseBitmapPrintElement($$)
1162 my($bitmap) = shift;
1163 my($type_decl) = typelist::mapType($bitmap);
1164 my($type_fn) = typelist::bitmap_type_fn($bitmap);
1165 my($name) = $bitmap->{PARENT}->{NAME};
1168 if ($e =~ /^(\w+) .*$/) {
1171 die "Bitmap: \"$name\" invalid Flag: \"$e\"";
1174 pidl "ndr_print_bitmap_flag(ndr, sizeof($type_decl), \"$flag\", $flag, r);";
1177 #####################################################################
1178 # generate a print function for an bitmap
1179 sub ParseBitmapPrint($)
1181 my($bitmap) = shift;
1182 my($type_decl) = typelist::mapType($bitmap);
1183 my($type_fn) = typelist::bitmap_type_fn($bitmap);
1185 start_flags($bitmap);
1187 pidl "ndr_print_$type_fn(ndr, name, r);";
1189 pidl "ndr->depth++;";
1190 foreach my $e (@{$bitmap->{ELEMENTS}}) {
1191 ParseBitmapPrintElement($e, $bitmap);
1193 pidl "ndr->depth--;";
1198 sub ArgsBitmapPush($)
1201 my $type_decl = typelist::mapType($e->{DATA});
1202 return "struct ndr_push *ndr, int ndr_flags, $type_decl r";
1205 sub ArgsBitmapPrint($)
1208 my $type_decl = typelist::mapType($e->{DATA});
1209 return "struct ndr_print *ndr, const char *name, $type_decl r";
1212 sub ArgsBitmapPull($)
1215 my $type_decl = typelist::mapType($e->{DATA});
1216 return "struct ndr_pull *ndr, int ndr_flags, $type_decl *r";
1219 $typefamily{BITMAP} = {
1220 PUSH_FN_BODY => \&ParseBitmapPush,
1221 PUSH_FN_ARGS => \&ArgsBitmapPush,
1222 PULL_FN_BODY => \&ParseBitmapPull,
1223 PULL_FN_ARGS => \&ArgsBitmapPull,
1224 PRINT_FN_BODY => \&ParseBitmapPrint,
1225 PRINT_FN_ARGS => \&ArgsBitmapPrint,
1228 #####################################################################
1229 # generate a struct print function
1230 sub ParseStructPrint($)
1232 my($struct) = shift;
1233 my($name) = $struct->{PARENT}->{NAME};
1235 return unless defined $struct->{ELEMENTS};
1237 pidl "ndr_print_struct(ndr, name, \"$name\");";
1239 start_flags($struct);
1241 pidl "ndr->depth++;";
1242 foreach my $e (@{$struct->{ELEMENTS}}) {
1243 ParseElementPrint($e, "r->");
1245 pidl "ndr->depth--;";
1250 #####################################################################
1251 # parse a struct - pull side
1252 sub ParseStructPull($)
1254 my($struct) = shift;
1257 return unless defined $struct->{ELEMENTS};
1259 # see if the structure contains a conformant array. If it
1260 # does, then it must be the last element of the structure, and
1261 # we need to pull the conformant length early, as it fits on
1262 # the wire before the structure (and even before the structure
1264 my $e = $struct->{ELEMENTS}[-1];
1265 if (Ndr::is_conformant_array($e) and Ndr::is_surrounding_array($e)) {
1269 if (defined $e->{TYPE} && $e->{TYPE} eq "string"
1270 && util::property_matches($e, "flag", ".*LIBNDR_FLAG_STR_CONFORMANT.*")) {
1274 # declare any internal pointers we need
1275 foreach my $e (@{$struct->{ELEMENTS}}) {
1276 if (Ndr::need_wire_pointer($e)) {
1277 pidl "uint32_t _ptr_$e->{NAME};";
1281 start_flags($struct);
1283 pidl "if (!(ndr_flags & NDR_SCALARS)) goto buffers;";
1285 pidl "NDR_CHECK(ndr_pull_struct_start(ndr));";
1287 if (defined $conform_e) {
1288 ParseArrayPullPreceding($conform_e, "r->", "NDR_SCALARS");
1291 my $align = Ndr::find_largest_alignment($struct);
1292 pidl "NDR_CHECK(ndr_pull_align(ndr, $align));";
1294 foreach my $e (@{$struct->{ELEMENTS}}) {
1295 ParseElementPullScalar($e, "r->", "NDR_SCALARS");
1299 pidl "if (!(ndr_flags & NDR_BUFFERS)) goto done;";
1300 foreach my $e (@{$struct->{ELEMENTS}}) {
1301 ParseElementPullBuffer($e, "r->");
1304 foreach my $e (@{$struct->{ELEMENTS}}) {
1305 CheckArraySizes($e, "r->");
1308 pidl "ndr_pull_struct_end(ndr);";
1315 #####################################################################
1316 # calculate size of ndr struct
1317 sub ParseStructNdrSize($)
1320 my $static = fn_prefix($t);
1323 if (my $flags = util::has_property($t, "flag")) {
1324 pidl "flags |= $flags;";
1326 pidl "return ndr_size_struct(r, flags, (ndr_push_flags_fn_t)ndr_push_$t->{NAME});";
1329 sub ArgsStructPush($)
1332 return "struct ndr_push *ndr, int ndr_flags, struct $e->{NAME} *r";
1335 sub ArgsStructPrint($)
1338 return "struct ndr_print *ndr, const char *name, struct $e->{NAME} *r";
1341 sub ArgsStructPull($)
1344 return "struct ndr_pull *ndr, int ndr_flags, struct $e->{NAME} *r";
1347 sub ArgsStructNdrSize($)
1350 return "const struct $d->{NAME} *r, int flags";
1353 $typefamily{STRUCT} = {
1354 PUSH_FN_BODY => \&ParseStructPush,
1355 PUSH_FN_ARGS => \&ArgsStructPush,
1356 PULL_FN_BODY => \&ParseStructPull,
1357 PULL_FN_ARGS => \&ArgsStructPull,
1358 PRINT_FN_BODY => \&ParseStructPrint,
1359 PRINT_FN_ARGS => \&ArgsStructPrint,
1360 SIZE_FN_BODY => \&ParseStructNdrSize,
1361 SIZE_FN_ARGS => \&ArgsStructNdrSize,
1364 #####################################################################
1365 # calculate size of ndr struct
1366 sub ParseUnionNdrSize($)
1369 my $static = fn_prefix($t);
1372 if (my $flags = util::has_property($t, "flag")) {
1373 pidl "flags |= $flags;";
1376 pidl "return ndr_size_union(r, flags, level, (ndr_push_flags_fn_t)ndr_push_$t->{NAME});";
1379 #####################################################################
1380 # parse a union - push side
1381 sub ParseUnionPush($)
1384 my $have_default = 0;
1390 pidl "level = ndr_push_get_switch_value(ndr, r);";
1392 pidl "if (!(ndr_flags & NDR_SCALARS)) goto buffers;";
1394 if (!util::has_property($e, "nodiscriminant")) {
1395 my $switch_type = util::has_property($e, "switch_type");
1396 $switch_type = "uint32" unless (defined ($switch_type));
1397 pidl "NDR_CHECK(ndr_push_$switch_type(ndr, NDR_SCALARS, level));";
1400 pidl "NDR_CHECK(ndr_push_struct_start(ndr));";
1402 # my $align = union_alignment($e);
1403 # pidl "NDR_CHECK(ndr_push_align(ndr, $align));";
1405 pidl "switch (level) {";
1407 foreach my $el (@{$e->{ELEMENTS}}) {
1408 if (util::has_property($el, "default")) {
1412 pidl "case $el->{PROPERTIES}->{case}:";
1415 if ($el->{TYPE} ne "EMPTY") {
1417 ParseElementPushScalar($el, "r->", "NDR_SCALARS");
1423 if (! $have_default) {
1425 pidl "\treturn ndr_push_error(ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value \%u\", level);";
1430 pidl "if (!(ndr_flags & NDR_BUFFERS)) goto done;";
1431 pidl "switch (level) {";
1433 foreach my $el (@{$e->{ELEMENTS}}) {
1434 if (util::has_property($el, "default")) {
1437 pidl "case $el->{PROPERTIES}->{case}:";
1439 if ($el->{TYPE} ne "EMPTY") {
1441 ParseElementPushBuffer($el, "r->");
1447 if (! $have_default) {
1449 pidl "\treturn ndr_push_error(ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value \%u\", level);";
1453 pidl "ndr_push_struct_end(ndr);";
1458 #####################################################################
1460 sub ParseUnionPrint($)
1463 my $have_default = 0;
1464 my($name) = $e->{PARENT}->{NAME};
1466 pidl "int level = ndr_print_get_switch_value(ndr, r);";
1468 pidl "ndr_print_union(ndr, name, level, \"$name\");";
1471 pidl "switch (level) {";
1473 foreach my $el (@{$e->{ELEMENTS}}) {
1474 if (util::has_property($el, "default")) {
1478 pidl "case $el->{PROPERTIES}->{case}:";
1480 if ($el->{TYPE} ne "EMPTY") {
1482 ParseElementPrint($el, "r->");
1488 if (! $have_default) {
1490 pidl "\tndr_print_bad_level(ndr, name, level);";
1498 #####################################################################
1499 # parse a union - pull side
1500 sub ParseUnionPull($)
1503 my $have_default = 0;
1504 my $switch_type = util::has_property($e, "switch_type");
1505 $switch_type = "uint32" unless defined($switch_type);
1508 if (!util::has_property($e, "nodiscriminant")) {
1509 if (typelist::typeIs($switch_type, "ENUM")) {
1510 $switch_type = typelist::enum_type_fn(typelist::getType($switch_type));
1512 pidl typelist::mapScalarType($switch_type) . " _level;";
1517 pidl "level = ndr_pull_get_switch_value(ndr, r);";
1519 pidl "if (!(ndr_flags & NDR_SCALARS)) goto buffers;";
1521 if (!util::has_property($e, "nodiscriminant")) {
1522 pidl "NDR_CHECK(ndr_pull_$switch_type(ndr, NDR_SCALARS, &_level));";
1523 pidl "if (_level != level) {";
1524 pidl "\treturn ndr_pull_error(ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value %u for $e->{PARENT}->{NAME}\", _level);";
1528 pidl "NDR_CHECK(ndr_pull_struct_start(ndr));";
1530 # my $align = union_alignment($e);
1531 # pidl "\tNDR_CHECK(ndr_pull_align(ndr, $align));\n";
1533 pidl "switch (level) {";
1535 foreach my $el (@{$e->{ELEMENTS}}) {
1536 if (util::has_property($el, "default")) {
1540 pidl "case $el->{PROPERTIES}->{case}: {";
1542 if ($el->{TYPE} ne "EMPTY") {
1544 if ($el->{POINTERS}) {
1545 pidl "uint32_t _ptr_$el->{NAME};";
1547 ParseElementPullScalar($el, "r->", "NDR_SCALARS");
1553 if (! $have_default) {
1555 pidl "\treturn ndr_pull_error(ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value \%u\", level);";
1560 pidl "if (!(ndr_flags & NDR_BUFFERS)) goto done;";
1561 pidl "switch (level) {";
1563 foreach my $el (@{$e->{ELEMENTS}}) {
1564 if (util::has_property($el, "default")) {
1567 pidl "case $el->{PROPERTIES}->{case}:";
1569 if ($el->{TYPE} ne "EMPTY") {
1571 ParseElementPullBuffer($el, "r->");
1577 if (! $have_default) {
1579 pidl "\treturn ndr_pull_error(ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value \%u\", level);";
1583 pidl "ndr_pull_struct_end(ndr);";
1588 sub ArgsUnionPush($)
1591 return "struct ndr_push *ndr, int ndr_flags, union $e->{NAME} *r";
1594 sub ArgsUnionPrint($)
1597 return "struct ndr_print *ndr, const char *name, union $e->{NAME} *r";
1600 sub ArgsUnionPull($)
1603 return "struct ndr_pull *ndr, int ndr_flags, union $e->{NAME} *r";
1606 sub ArgsUnionNdrSize($)
1609 return "const union $d->{NAME} *r, uint32_t level, int flags";
1612 $typefamily{UNION} = {
1613 PUSH_FN_BODY => \&ParseUnionPush,
1614 PUSH_FN_ARGS => \&ArgsUnionPush,
1615 PULL_FN_BODY => \&ParseUnionPull,
1616 PULL_FN_ARGS => \&ArgsUnionPull,
1617 PRINT_FN_BODY => \&ParseUnionPrint,
1618 PRINT_FN_ARGS => \&ArgsUnionPrint,
1619 SIZE_FN_ARGS => \&ArgsUnionNdrSize,
1620 SIZE_FN_BODY => \&ParseUnionNdrSize,
1623 #####################################################################
1624 # parse a typedef - push side
1625 sub ParseTypedefPush($)
1628 my $static = fn_prefix($e);
1630 return unless needed::is_needed("push_$e->{NAME}");
1632 my $args = $typefamily{$e->{DATA}->{TYPE}}->{PUSH_FN_ARGS}->($e);
1633 pidl $static . "NTSTATUS ndr_push_$e->{NAME}($args)";
1637 $typefamily{$e->{DATA}->{TYPE}}->{PUSH_FN_BODY}->($e->{DATA});
1638 pidl "return NT_STATUS_OK;";
1645 #####################################################################
1646 # parse a typedef - pull side
1647 sub ParseTypedefPull($)
1650 my $static = fn_prefix($e);
1652 return unless needed::is_needed("pull_$e->{NAME}");
1654 my $args = $typefamily{$e->{DATA}->{TYPE}}->{PULL_FN_ARGS}->($e);
1656 pidl $static . "NTSTATUS ndr_pull_$e->{NAME}($args)";
1660 $typefamily{$e->{DATA}->{TYPE}}->{PULL_FN_BODY}->($e->{DATA});
1661 pidl "return NT_STATUS_OK;";
1667 #####################################################################
1668 # parse a typedef - print side
1669 sub ParseTypedefPrint($)
1673 my $args = $typefamily{$e->{DATA}->{TYPE}}->{PRINT_FN_ARGS}->($e);
1675 return unless !util::has_property($e, "noprint");
1677 pidl "void ndr_print_$e->{NAME}($args)";
1680 $typefamily{$e->{DATA}->{TYPE}}->{PRINT_FN_BODY}->($e->{DATA});
1686 #####################################################################
1687 ## calculate the size of a structure
1688 sub ParseTypedefNdrSize($)
1692 return unless needed::is_needed("ndr_size_$t->{NAME}");
1694 my $tf = $typefamily{$t->{DATA}->{TYPE}};
1695 my $args = $tf->{SIZE_FN_ARGS}->($t);
1697 pidl "size_t ndr_size_$t->{NAME}($args)";
1700 $typefamily{$t->{DATA}->{TYPE}}->{SIZE_FN_BODY}->($t);
1706 #####################################################################
1707 # parse a function - print side
1708 sub ParseFunctionPrint($)
1712 return unless !util::has_property($fn, "noprint");
1714 pidl "void ndr_print_$fn->{NAME}(struct ndr_print *ndr, const char *name, int flags, struct $fn->{NAME} *r)";
1717 pidl "ndr_print_struct(ndr, name, \"$fn->{NAME}\");";
1718 pidl "ndr->depth++;";
1720 pidl "if (flags & NDR_SET_VALUES) {";
1721 pidl "\tndr->flags |= LIBNDR_PRINT_SET_VALUES;";
1724 pidl "if (flags & NDR_IN) {";
1726 pidl "ndr_print_struct(ndr, \"in\", \"$fn->{NAME}\");";
1727 pidl "ndr->depth++;";
1729 foreach my $e (@{$fn->{ELEMENTS}}) {
1730 if (util::has_property($e, "in")) {
1731 ParseElementPrint($e, "r->in.");
1734 pidl "ndr->depth--;";
1738 pidl "if (flags & NDR_OUT) {";
1740 pidl "ndr_print_struct(ndr, \"out\", \"$fn->{NAME}\");";
1741 pidl "ndr->depth++;";
1742 foreach my $e (@{$fn->{ELEMENTS}}) {
1743 if (util::has_property($e, "out")) {
1744 ParseElementPrint($e, "r->out.");
1747 if ($fn->{RETURN_TYPE} && $fn->{RETURN_TYPE} ne "void") {
1749 $cprefix = "" if (Ndr::is_scalar_type($fn->{RETURN_TYPE})) ; # FIXME: Should really use util::c_push_prefix here
1750 pidl "ndr_print_$fn->{RETURN_TYPE}(ndr, \"result\", $cprefix"."r->out.result);";
1752 pidl "ndr->depth--;";
1756 pidl "ndr->depth--;";
1762 #####################################################################
1763 # parse a function element
1764 sub ParseFunctionElementPush($$)
1769 if (util::array_size($e)) {
1770 if (Ndr::need_wire_pointer($e)) {
1771 ParsePtrPush($e, "r->$inout.");
1772 pidl "if (r->$inout.$e->{NAME}) {";
1774 ParseArrayPush($e, "ndr", "r->$inout.", "NDR_SCALARS|NDR_BUFFERS");
1778 ParseArrayPush($e, "ndr", "r->$inout.", "NDR_SCALARS|NDR_BUFFERS");
1781 ParseElementPushScalar($e, "r->$inout.", "NDR_SCALARS|NDR_BUFFERS");
1782 if (Ndr::need_wire_pointer($e)) {
1783 ParseElementPushBuffer($e, "r->$inout.");
1788 #####################################################################
1790 sub ParseFunctionPush($)
1793 my $static = fn_prefix($fn);
1795 return unless !util::has_property($fn, "nopush");
1797 pidl $static . "NTSTATUS ndr_push_$fn->{NAME}(struct ndr_push *ndr, int flags, struct $fn->{NAME} *r)";
1801 pidl "if (!(flags & NDR_IN)) goto ndr_out;";
1804 foreach my $e (@{$fn->{ELEMENTS}}) {
1805 if (util::has_property($e, "in")) {
1806 if (util::has_property($e, "ref")) {
1807 check_null_pointer("*r->in.$e->{NAME}");
1809 ParseFunctionElementPush($e, "in");
1814 pidl "if (!(flags & NDR_OUT)) goto done;";
1817 foreach my $e (@{$fn->{ELEMENTS}}) {
1818 if (util::has_property($e, "out")) {
1819 if (util::has_property($e, "ref")) {
1820 check_null_pointer("*r->out.$e->{NAME}");
1822 ParseFunctionElementPush($e, "out");
1826 if ($fn->{RETURN_TYPE} && $fn->{RETURN_TYPE} ne "void") {
1827 pidl "NDR_CHECK(ndr_push_$fn->{RETURN_TYPE}(ndr, NDR_SCALARS, r->out.result));";
1831 pidl "return NT_STATUS_OK;";
1837 #####################################################################
1838 # parse a function element
1839 sub ParseFunctionElementPull($$)
1844 if (util::array_size($e)) {
1845 if (Ndr::need_wire_pointer($e)) {
1846 pidl "NDR_CHECK(ndr_pull_unique_ptr(ndr, &_ptr_$e->{NAME}));";
1847 pidl "r->$inout.$e->{NAME} = NULL;";
1848 pidl "if (_ptr_$e->{NAME}) {";
1850 } elsif ($inout eq "out" && util::has_property($e, "ref")) {
1851 pidl "if (r->$inout.$e->{NAME}) {";
1855 ParseArrayPull($e, "ndr", "r->$inout.", "NDR_SCALARS|NDR_BUFFERS");
1857 if (Ndr::need_wire_pointer($e) or ($inout eq "out" and util::has_property($e, "ref"))) {
1862 if ($inout eq "out" && util::has_property($e, "ref")) {
1863 pidl "if (ndr->flags & LIBNDR_FLAG_REF_ALLOC) {";
1864 pidl "\tNDR_ALLOC(ndr, r->out.$e->{NAME});";
1868 if ($inout eq "in" && util::has_property($e, "ref")) {
1869 pidl "NDR_ALLOC(ndr, r->in.$e->{NAME});";
1872 ParseElementPullScalar($e, "r->$inout.", "NDR_SCALARS|NDR_BUFFERS");
1873 if (Ndr::need_wire_pointer($e)) {
1874 ParseElementPullBuffer($e, "r->$inout.");
1879 ############################################################
1880 # allocate ref variables
1881 sub AllocateRefVars($)
1884 my $asize = util::array_size($e);
1886 # note that if the variable is also an "in"
1887 # variable then we copy the initial value from
1890 if (!defined $asize) {
1891 # its a simple variable
1892 pidl "NDR_ALLOC(ndr, r->out.$e->{NAME});";
1893 if (util::has_property($e, "in")) {
1894 pidl "*r->out.$e->{NAME} = *r->in.$e->{NAME};";
1896 pidl "ZERO_STRUCTP(r->out.$e->{NAME});";
1902 my $size = ParseExpr($e, $asize, "r->out.");
1903 check_null_pointer($size);
1904 pidl "NDR_ALLOC_N(ndr, r->out.$e->{NAME}, $size);";
1905 if (util::has_property($e, "in")) {
1906 pidl "memcpy(r->out.$e->{NAME},r->in.$e->{NAME},$size * sizeof(*r->in.$e->{NAME}));";
1908 pidl "memset(r->out.$e->{NAME}, 0, $size * sizeof(*r->out.$e->{NAME}));";
1912 #####################################################################
1914 sub ParseFunctionPull($)
1917 my $static = fn_prefix($fn);
1919 return unless !util::has_property($fn, "nopull");
1921 # pull function args
1922 pidl $static . "NTSTATUS ndr_pull_$fn->{NAME}(struct ndr_pull *ndr, int flags, struct $fn->{NAME} *r)";
1926 # declare any internal pointers we need
1927 foreach my $e (@{$fn->{ELEMENTS}}) {
1928 if (Ndr::need_wire_pointer($e)) {
1929 pidl "uint32_t _ptr_$e->{NAME};";
1933 pidl "if (!(flags & NDR_IN)) goto ndr_out;";
1936 # auto-init the out section of a structure. I originally argued that
1937 # this was a bad idea as it hides bugs, but coping correctly
1938 # with initialisation and not wiping ref vars is turning
1939 # out to be too tricky (tridge)
1940 foreach my $e (@{$fn->{ELEMENTS}}) {
1941 if (util::has_property($e, "out")) {
1942 pidl "ZERO_STRUCT(r->out);";
1948 foreach my $e (@{$fn->{ELEMENTS}}) {
1949 if (util::has_property($e, "in")) {
1950 ParseFunctionElementPull($e, "in");
1952 # we need to allocate any reference output variables, so that
1953 # a dcerpc backend can be sure they are non-null
1954 if (util::has_property($e, "out") && util::has_property($e, "ref")) {
1955 AllocateRefVars($e);
1959 foreach my $e (@{$fn->{ELEMENTS}}) {
1960 if (util::has_property($e, "in")) {
1961 CheckArraySizes($e, "r->in.");
1966 pidl "if (!(flags & NDR_OUT)) goto done;";
1969 foreach my $e (@{$fn->{ELEMENTS}}) {
1970 if (util::has_property($e, "out")) {
1971 ParseFunctionElementPull($e, "out");
1975 foreach my $e (@{$fn->{ELEMENTS}}) {
1976 if (util::has_property($e, "out")) {
1977 CheckArraySizes($e, "r->out.");
1981 if ($fn->{RETURN_TYPE} && $fn->{RETURN_TYPE} ne "void") {
1982 pidl "NDR_CHECK(ndr_pull_$fn->{RETURN_TYPE}(ndr, NDR_SCALARS, &r->out.result));";
1987 pidl "return NT_STATUS_OK;";
1993 #####################################################################
1994 # produce a function call table
1995 sub FunctionTable($)
1997 my($interface) = shift;
1998 my($data) = $interface->{INHERITED_DATA};
2000 my $uname = uc $interface->{NAME};
2002 foreach my $d (@{$data}) {
2003 if ($d->{TYPE} eq "FUNCTION") { $count++; }
2006 return if ($count == 0);
2008 pidl "static const struct dcerpc_interface_call $interface->{NAME}\_calls[] = {";
2009 foreach my $d (@{$data}) {
2010 if ($d->{TYPE} eq "FUNCTION") {
2012 pidl "\t\t\"$d->{NAME}\",";
2013 pidl "\t\tsizeof(struct $d->{NAME}),";
2014 pidl "\t\t(ndr_push_flags_fn_t) ndr_push_$d->{NAME},";
2015 pidl "\t\t(ndr_pull_flags_fn_t) ndr_pull_$d->{NAME},";
2016 pidl "\t\t(ndr_print_function_t) ndr_print_$d->{NAME}";
2020 pidl "\t{ NULL, 0, NULL, NULL, NULL }";
2024 # If no endpoint is set, default to the interface name as a named pipe
2025 if (! defined $interface->{PROPERTIES}->{endpoint}) {
2026 $interface->{PROPERTIES}->{endpoint} = "\"ncacn_np:[\\\\pipe\\\\" . $interface->{NAME} . "]\"";
2029 my @e = split / /, $interface->{PROPERTIES}->{endpoint};
2030 my $endpoint_count = $#e + 1;
2032 pidl "static const char * const $interface->{NAME}\_endpoint_strings[] = {";
2033 foreach my $ep (@e) {
2039 pidl "static const struct dcerpc_endpoint_list $interface->{NAME}\_endpoints = {";
2040 pidl "\t.count\t= $endpoint_count,";
2041 pidl "\t.names\t= $interface->{NAME}\_endpoint_strings";
2045 if (! defined $interface->{PROPERTIES}->{authservice}) {
2046 $interface->{PROPERTIES}->{authservice} = "\"host\"";
2049 my @a = split / /, $interface->{PROPERTIES}->{authservice};
2050 my $authservice_count = $#a + 1;
2052 pidl "static const char * const $interface->{NAME}\_authservice_strings[] = {";
2053 foreach my $ap (@a) {
2059 pidl "static const struct dcerpc_authservice_list $interface->{NAME}\_authservices = {";
2060 pidl "\t.count\t= $endpoint_count,";
2061 pidl "\t.names\t= $interface->{NAME}\_authservice_strings";
2065 pidl "\nconst struct dcerpc_interface_table dcerpc_table_$interface->{NAME} = {";
2066 pidl "\t.name\t\t= \"$interface->{NAME}\",";
2067 pidl "\t.uuid\t\t= DCERPC_$uname\_UUID,";
2068 pidl "\t.if_version\t= DCERPC_$uname\_VERSION,";
2069 pidl "\t.helpstring\t= DCERPC_$uname\_HELPSTRING,";
2070 pidl "\t.num_calls\t= $count,";
2071 pidl "\t.calls\t\t= $interface->{NAME}\_calls,";
2072 pidl "\t.endpoints\t= &$interface->{NAME}\_endpoints,";
2073 pidl "\t.authservices\t= &$interface->{NAME}\_authservices";
2077 pidl "static NTSTATUS dcerpc_ndr_$interface->{NAME}_init(void)";
2079 pidl "\treturn librpc_register_interface(&dcerpc_table_$interface->{NAME});";
2084 #####################################################################
2085 # parse the interface definitions
2086 sub ParseInterface($)
2088 my($interface) = shift;
2089 my($data) = $interface->{DATA};
2092 foreach my $d (@{$data}) {
2093 if ($d->{TYPE} eq "TYPEDEF") {
2094 ParseTypedefPush($d);
2095 ParseTypedefPull($d);
2096 ParseTypedefPrint($d);
2097 ParseTypedefNdrSize($d);
2101 foreach my $d (@{$data}) {
2102 if ($d->{TYPE} eq "FUNCTION") {
2103 ParseFunctionPush($d);
2104 ParseFunctionPull($d);
2105 ParseFunctionPrint($d);
2109 FunctionTable($interface);
2112 sub RegistrationFunction($$)
2115 my $filename = shift;
2117 $filename =~ /.*\/ndr_(.*).c/;
2119 pidl "NTSTATUS dcerpc_$basename\_init(void)";
2122 pidl "NTSTATUS status = NT_STATUS_OK;";
2123 foreach my $interface (@{$idl}) {
2124 next if $interface->{TYPE} ne "INTERFACE";
2126 my $data = $interface->{INHERITED_DATA};
2128 foreach my $d (@{$data}) {
2129 if ($d->{TYPE} eq "FUNCTION") { $count++; }
2132 next if ($count == 0);
2134 pidl "status = dcerpc_ndr_$interface->{NAME}_init();";
2135 pidl "if (NT_STATUS_IS_ERR(status)) {";
2136 pidl "\treturn status;";
2140 pidl "return status;";
2146 sub CheckPointerTypes($$)
2149 my $default = shift;
2151 foreach my $e (@{$s->{ELEMENTS}}) {
2152 if ($e->{POINTERS}) {
2153 if (not defined(Ndr::pointer_type($e))) {
2154 $e->{PROPERTIES}->{$default} = 1;
2157 if (Ndr::pointer_type($e) eq "ptr") {
2158 print "Warning: ptr is not supported by pidl yet\n";
2164 sub LoadInterface($)
2168 if (not util::has_property($x, "pointer_default")) {
2169 # MIDL defaults to "ptr" in DCE compatible mode (/osf)
2170 # and "unique" in Microsoft Extensions mode (default)
2171 $x->{PROPERTIES}->{pointer_default} = "unique";
2174 foreach my $d (@{$x->{DATA}}) {
2175 if (($d->{TYPE} eq "DECLARE") or ($d->{TYPE} eq "TYPEDEF")) {
2176 if ($d->{DATA}->{TYPE} eq "STRUCT" or $d->{DATA}->{TYPE} eq "UNION") {
2177 CheckPointerTypes($d->{DATA}, $x->{PROPERTIES}->{pointer_default});
2180 if (defined($d->{PROPERTIES}) && !defined($d->{DATA}->{PROPERTIES})) {
2181 $d->{DATA}->{PROPERTIES} = $d->{PROPERTIES};
2184 if ($d->{TYPE} eq "FUNCTION") {
2185 CheckPointerTypes($d,
2186 $x->{PROPERTIES}->{pointer_default} # MIDL defaults to "ref"
2196 foreach my $x (@{$idl}) {
2201 #####################################################################
2202 # parse a parsed IDL structure back into an IDL file
2206 my($filename) = shift;
2207 my $h_filename = $filename;
2212 if ($h_filename =~ /(.*)\.c/) {
2213 $h_filename = "$1.h";
2216 pidl "/* parser auto-generated by pidl */";
2218 pidl "#include \"includes.h\"";
2219 pidl "#include \"$h_filename\"";
2222 foreach my $x (@{$idl}) {
2223 if ($x->{TYPE} eq "INTERFACE") {
2224 needed::BuildNeeded($x);
2229 RegistrationFunction($idl, $filename);