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
23 sub RegisterPrimitives
()
44 "error_status_t" => 4,
54 foreach my $k (keys %type_alignments) {
60 ALIGN
=> $type_alignments{$k}
70 if (my $dt = $typedefs{$type}->{DATA
}->{TYPE
}) {
71 return 1 if ($dt eq "SCALAR" or $dt eq "ENUM" or $dt eq "BITMAP");
81 return undef unless $e->{POINTERS
};
83 return "ref" if (util
::has_property
($e, "ref"));
84 return "ptr" if (util
::has_property
($e, "ptr"));
85 return "unique" if (util
::has_property
($e, "unique"));
86 return "relative" if (util
::has_property
($e, "relative"));
87 return "ignore" if (util
::has_property
($e, "ignore"));
92 # determine if an element needs a reference pointer on the wire
93 # in its NDR representation
94 sub need_wire_pointer
($)
99 return 0 unless ($pt = pointer_type
($e));
108 # determine if an element is a pure scalar. pure scalars do not
109 # have a "buffers" section in NDR
110 sub is_pure_scalar
($)
113 if (util
::has_property
($e, "ref")) {
116 if (is_scalar_type
($e->{TYPE
}) &&
118 !util
::array_size
($e)) {
124 # see if a variable needs to be allocated by the NDR subsystem on pull
129 if (util
::has_property
($e, "ref")) {
133 if ($e->{POINTERS
} || util
::array_size
($e)) {
141 # determine the C prefix used to refer to a variable when passing to a push
142 # function. This will be '*' for pointers to scalar types, '' for scalar
143 # types and normal pointers and '&' for pass-by-reference structures
148 if ($e->{TYPE
} =~ "string") {
152 if (is_scalar_type
($e->{TYPE
}) &&
156 if (!is_scalar_type
($e->{TYPE
}) &&
158 !util
::array_size
($e)) {
165 # determine the C prefix used to refer to a variable when passing to a pull
171 if (!$e->{POINTERS
} && !util
::array_size
($e)) {
175 if ($e->{TYPE
} =~ "string") {
200 $tabs = substr($tabs, 0, -1);
203 ###################################
204 # find a sibling var in a structure
209 my($fn) = $e->{PARENT
};
211 if ($name =~ /\*(.*)/) {
215 if ($fn->{TYPE
} eq "FUNCTION") {
216 for my $e2 (@
{$fn->{ELEMENTS
}}) {
217 if ($e2->{NAME
} eq $name) {
223 for my $e2 (@
{$fn->{ELEMENTS
}}) {
224 if ($e2->{NAME
} eq $name) {
228 die "invalid sibling '$name'";
231 ####################################################################
232 # work out the name of a size_is() variable
237 my($var_prefix) = shift;
239 my($fn) = $e->{PARENT
};
241 if (util
::is_constant
($size)) {
245 if ($size =~ /ndr->|\(/) {
251 if ($size =~ /\*(.*)/) {
256 if ($fn->{TYPE
} ne "FUNCTION") {
257 return $prefix . "r->$size";
260 my $e2 = find_sibling
($e, $size);
262 if (util
::has_property
($e2, "in") && util
::has_property
($e2, "out")) {
263 return $prefix . "$var_prefix$size";
265 if (util
::has_property
($e2, "in")) {
266 return $prefix . "r->in.$size";
268 if (util
::has_property
($e2, "out")) {
269 return $prefix . "r->out.$size";
272 die "invalid variable in $size for element $e->{NAME} in $fn->{NAME}\n";
275 #####################################################################
276 # check that a variable we get from ParseExpr isn't a null pointer
277 sub check_null_pointer
($)
280 if ($size =~ /^\*/) {
281 my $size2 = substr($size, 1);
282 pidl
"if ($size2 == NULL) return NT_STATUS_INVALID_PARAMETER_MIX;";
286 #####################################################################
287 # check that a variable we get from ParseExpr isn't a null pointer
288 # void return varient
289 sub check_null_pointer_void
($)
292 if ($size =~ /^\*/) {
293 my $size2 = substr($size, 1);
294 pidl
"if ($size2 == NULL) return;";
299 #####################################################################
300 # work out is a parse function should be declared static or not
304 if ($fn->{TYPE
} eq "TYPEDEF") {
305 if (util
::has_property
($fn, "public")) {
310 if ($fn->{TYPE
} eq "FUNCTION") {
311 if (util
::has_property
($fn, "public")) {
319 ###################################################################
320 # setup any special flags for an element or structure
324 my $flags = util
::has_property
($e, "flag");
325 if (defined $flags) {
326 pidl
"{ uint32_t _flags_save_$e->{TYPE} = ndr->flags;";
327 pidl
"ndr_set_flags(&ndr->flags, $flags);";
331 ###################################################################
332 # end any special flags for an element or structure
336 my $flags = util
::has_property
($e, "flag");
337 if (defined $flags) {
338 pidl
"ndr->flags = _flags_save_$e->{TYPE};\n\t}";
342 #####################################################################
343 # work out the correct alignment for a structure or union
344 sub find_largest_alignment
($)
349 for my $e (@
{$s->{ELEMENTS
}}) {
352 if (need_wire_pointer
($e)) {
355 $a = align_type
($e->{TYPE
});
358 $align = $a if ($align < $a);
364 #####################################################################
370 unless (defined($typedefs{$e}) && defined($typedefs{$e}->{DATA
}->{TYPE
})) {
371 # it must be an external type - all we can do is guess
372 # print "Warning: assuming alignment of unknown type '$e' is 4\n";
376 my $dt = $typedefs{$e}->{DATA
};
378 return $dt->{ALIGN
} if ($dt->{ALIGN
});
379 return $typefamily{$dt->{TYPE
}}->{ALIGN
}($dt);
382 #####################################################################
383 # parse an array - push side
384 sub ParseArrayPush
($$$)
387 my $var_prefix = shift;
388 my $ndr_flags = shift;
390 my $size = ParseExpr
($e, util
::array_size
($e), $var_prefix);
392 if (defined $e->{CONFORMANT_SIZE
}) {
393 # the conformant size has already been pushed
394 } elsif (!util
::is_inline_array
($e)) {
395 # we need to emit the array size
396 pidl
"NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, $size));";
399 if (my $length = util
::has_property
($e, "length_is")) {
400 $length = ParseExpr
($e, $length, $var_prefix);
401 pidl
"NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0));";
402 pidl
"NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, $length));";
406 if (is_scalar_type
($e->{TYPE
})) {
407 pidl
"NDR_CHECK(ndr_push_array_$e->{TYPE}(ndr, $ndr_flags, $var_prefix$e->{NAME}, $size));";
409 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}));";
413 #####################################################################
415 sub ParseArrayPrint
($$)
418 my $var_prefix = shift;
419 my $size = ParseExpr
($e, util
::array_size
($e), $var_prefix);
420 my $length = util
::has_property
($e, "length_is");
422 if (defined $length) {
423 $size = ParseExpr
($e, $length, $var_prefix);
426 if (is_scalar_type
($e->{TYPE
})) {
427 pidl
"ndr_print_array_$e->{TYPE}(ndr, \"$e->{NAME}\", $var_prefix$e->{NAME}, $size);";
429 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});";
433 #####################################################################
434 # check the size_is and length_is constraints
435 sub CheckArraySizes
($$)
438 my $var_prefix = shift;
440 if (!defined $e->{CONFORMANT_SIZE
} &&
441 util
::has_property
($e, "size_is")) {
442 my $size = ParseExpr
($e, util
::array_size
($e), $var_prefix);
443 pidl
"if ($var_prefix$e->{NAME}) {";
445 check_null_pointer
($size);
446 pidl
"NDR_CHECK(ndr_check_array_size(ndr, (void*)&$var_prefix$e->{NAME}, $size));";
451 if (my $length = util
::has_property
($e, "length_is")) {
452 $length = ParseExpr
($e, $length, $var_prefix);
453 pidl
"if ($var_prefix$e->{NAME}) {";
455 check_null_pointer
($length);
456 pidl
"NDR_CHECK(ndr_check_array_length(ndr, (void*)&$var_prefix$e->{NAME}, $length));";
462 #####################################################################
463 # parse an array - pull side
464 sub ParseArrayPull
($$$)
467 my $var_prefix = shift;
468 my $ndr_flags = shift;
470 my $size = ParseExpr
($e, util
::array_size
($e), $var_prefix);
471 my $alloc_size = $size;
473 # if this is a conformant array then we use that size to allocate, and make sure
474 # we allocate enough to pull the elements
475 if (defined $e->{CONFORMANT_SIZE
}) {
476 $alloc_size = $e->{CONFORMANT_SIZE
};
477 check_null_pointer
($size);
478 pidl
"if ($size > $alloc_size) {";
480 pidl
"return ndr_pull_error(ndr, NDR_ERR_CONFORMANT_SIZE, \"Bad conformant size %u should be %u\", $alloc_size, $size);";
483 } elsif (!util
::is_inline_array
($e)) {
484 if ($var_prefix =~ /^r->out/ && $size =~ /^\*r->in/) {
485 my $size2 = substr($size, 1);
486 pidl
"if (ndr->flags & LIBNDR_FLAG_REF_ALLOC) { NDR_ALLOC(ndr, $size2); }";
489 # non fixed arrays encode the size just before the array
490 pidl
"NDR_CHECK(ndr_pull_array_size(ndr, &$var_prefix$e->{NAME}));";
491 $alloc_size = "ndr_get_array_size(ndr, &$var_prefix$e->{NAME})";
494 if ((need_alloc
($e) && !util
::is_fixed_array
($e)) ||
495 ($var_prefix eq "r->in." && util
::has_property
($e, "ref"))) {
496 if (!util
::is_inline_array
($e) || $ndr_flags eq "NDR_SCALARS") {
497 pidl
"NDR_ALLOC_N(ndr, $var_prefix$e->{NAME}, $alloc_size);";
501 if (($var_prefix eq "r->out." && util
::has_property
($e, "ref"))) {
502 if (!util
::is_inline_array
($e) || $ndr_flags eq "NDR_SCALARS") {
503 pidl
"if (ndr->flags & LIBNDR_FLAG_REF_ALLOC) {";
505 pidl
"NDR_ALLOC_N(ndr, $var_prefix$e->{NAME}, $alloc_size);";
511 if (my $length = util
::has_property
($e, "length_is")) {
512 pidl
"NDR_CHECK(ndr_pull_array_length(ndr, &$var_prefix$e->{NAME}));";
513 $size = "ndr_get_array_length(ndr, &$var_prefix$e->{NAME})";
516 check_null_pointer
($size);
517 if (is_scalar_type
($e->{TYPE
})) {
518 pidl
"NDR_CHECK(ndr_pull_array_$e->{TYPE}(ndr, $ndr_flags, $var_prefix$e->{NAME}, $size));";
520 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}));";
524 #####################################################################
525 # parse scalars in a structure element
526 sub ParseElementPushScalar
($$$)
529 my($var_prefix) = shift;
530 my($ndr_flags) = shift;
531 my $cprefix = c_push_prefix
($e);
532 my $sub_size = util
::has_property
($e, "subcontext");
536 if (my $value = util
::has_property
($e, "value")) {
537 pidl
"$cprefix$var_prefix$e->{NAME} = $value;";
540 if (util
::has_property
($e, "relative")) {
541 pidl
"NDR_CHECK(ndr_push_relative_ptr1(ndr, $var_prefix$e->{NAME}));";
542 } elsif (util
::is_inline_array
($e)) {
543 ParseArrayPush
($e, "r->", "NDR_SCALARS");
544 } elsif (need_wire_pointer
($e)) {
545 ParseElementPushPtr
($e, $var_prefix, $ndr_flags);
546 } elsif (need_alloc
($e)) {
547 # no scalar component
548 } elsif (my $switch = util
::has_property
($e, "switch_is")) {
549 ParseElementPushSwitch
($e, $var_prefix, $ndr_flags, $switch);
550 } elsif (defined $sub_size) {
551 pidl
"NDR_CHECK(ndr_push_subcontext_flags_fn(ndr, $sub_size, $cprefix$var_prefix$e->{NAME}, (ndr_push_flags_fn_t) ndr_push_$e->{TYPE}));";
553 pidl
"NDR_CHECK(ndr_push_$e->{TYPE}(ndr, $ndr_flags, $cprefix$var_prefix$e->{NAME}));";
559 #####################################################################
560 # parse a pointer in a struct element or function
561 sub ParseElementPushPtr
($$$)
564 my $var_prefix = shift;
565 my $ndr_flags = shift;
567 pidl
"NDR_CHECK(ndr_push_unique_ptr(ndr, $var_prefix$e->{NAME}));";
571 #####################################################################
572 # print scalars in a structure element
573 sub ParseElementPrintScalar
($$)
576 my($var_prefix) = shift;
577 my $cprefix = c_push_prefix
($e);
579 if (util
::has_property
($e, "noprint")) {
583 if (my $value = util
::has_property
($e, "value")) {
584 pidl
"if (ndr->flags & LIBNDR_PRINT_SET_VALUES) {";
586 pidl
"$cprefix$var_prefix$e->{NAME} = $value;";
591 if (util
::is_fixed_array
($e)) {
592 ParseElementPrintBuffer
($e, $var_prefix);
593 } elsif ($e->{POINTERS
} || util
::array_size
($e)) {
594 pidl
"ndr_print_ptr(ndr, \"$e->{NAME}\", $var_prefix$e->{NAME});";
595 pidl
"ndr->depth++;";
596 ParseElementPrintBuffer
($e, $var_prefix);
597 pidl
"ndr->depth--;";
598 } elsif (my $switch = util
::has_property
($e, "switch_is")) {
599 ParseElementPrintSwitch
($e, $var_prefix, $switch);
601 pidl
"ndr_print_$e->{TYPE}(ndr, \"$e->{NAME}\", $cprefix$var_prefix$e->{NAME});";
605 #####################################################################
606 # parse scalars in a structure element - pull size
607 sub ParseElementPullSwitch
($$$$)
610 my($var_prefix) = shift;
611 my($ndr_flags) = shift;
613 my $switch_var = ParseExpr
($e, $switch, $var_prefix);
615 my $cprefix = c_pull_prefix
($e);
617 my $utype = $typedefs{$e->{TYPE
}};
619 check_null_pointer
($switch_var);
621 if (!defined $utype ||
622 !util
::has_property
($utype, "nodiscriminant")) {
623 my $e2 = find_sibling
($e, $switch);
624 my $type_decl = util
::map_type
($e2->{TYPE
});
625 pidl
"if (($ndr_flags) & NDR_SCALARS) {";
627 if ($typedefs{$e2->{TYPE
}}->{DATA
}->{TYPE
} eq "ENUM") {
628 $type_decl = util
::enum_type_decl
($e2);
629 } elsif ($typedefs{$e2->{TYPE
}}->{DATA
}->{TYPE
} eq "BITMAP") {
630 $type_decl = util
::bitmap_type_decl
($e2);
632 pidl
"$type_decl _level;";
633 pidl
"NDR_CHECK(ndr_pull_$e2->{TYPE}(ndr, NDR_SCALARS, &_level));";
634 if ($switch_var =~ /r->in/) {
635 pidl
"if (!(ndr->flags & LIBNDR_FLAG_REF_ALLOC) && _level != $switch_var) {";
638 pidl
"if (_level != $switch_var) {";
641 pidl
"return ndr_pull_error(ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value %u in $e->{NAME}\", _level);";
643 if ($switch_var =~ /r->/) {
644 pidl
"} else { $switch_var = _level; }";
652 my $sub_size = util
::has_property
($e, "subcontext");
653 if (defined $sub_size) {
654 pidl
"if (($ndr_flags) & NDR_SCALARS) {";
656 pidl
"NDR_CHECK(ndr_pull_subcontext_union_fn(ndr, $sub_size, $switch_var, $cprefix$var_prefix$e->{NAME}, (ndr_pull_union_fn_t) ndr_pull_$e->{TYPE}));";
660 pidl
"NDR_CHECK(ndr_pull_$e->{TYPE}(ndr, $ndr_flags, $switch_var, $cprefix$var_prefix$e->{NAME}));";
666 #####################################################################
667 # push switch element
668 sub ParseElementPushSwitch
($$$$)
671 my($var_prefix) = shift;
672 my($ndr_flags) = shift;
674 my $switch_var = ParseExpr
($e, $switch, $var_prefix);
675 my $cprefix = c_push_prefix
($e);
677 check_null_pointer
($switch_var);
679 my $utype = $typedefs{$e->{TYPE
}};
680 if (!defined $utype ||
681 !util
::has_property
($utype, "nodiscriminant")) {
682 my $e2 = find_sibling
($e, $switch);
683 pidl
"if (($ndr_flags) & NDR_SCALARS) {";
685 pidl
"NDR_CHECK(ndr_push_$e2->{TYPE}(ndr, NDR_SCALARS, $switch_var));";
690 my $sub_size = util
::has_property
($e, "subcontext");
691 if (defined $sub_size) {
692 pidl
"if(($ndr_flags) & NDR_SCALARS) {";
694 pidl
"NDR_CHECK(ndr_push_subcontext_union_fn(ndr, $sub_size, $switch_var, $cprefix$var_prefix$e->{NAME}, (ndr_push_union_fn_t) ndr_push_$e->{TYPE}));";
698 pidl
"NDR_CHECK(ndr_push_$e->{TYPE}(ndr, $ndr_flags, $switch_var, $cprefix$var_prefix$e->{NAME}));";
702 #####################################################################
703 # print scalars in a structure element
704 sub ParseElementPrintSwitch
($$$)
707 my($var_prefix) = shift;
709 my $switch_var = ParseExpr
($e, $switch, $var_prefix);
710 my $cprefix = c_push_prefix
($e);
712 check_null_pointer_void
($switch_var);
714 pidl
"ndr_print_$e->{TYPE}(ndr, \"$e->{NAME}\", $switch_var, $cprefix$var_prefix$e->{NAME});";
718 #####################################################################
719 # parse scalars in a structure element - pull size
720 sub ParseElementPullScalar
($$$)
723 my($var_prefix) = shift;
724 my($ndr_flags) = shift;
725 my $cprefix = c_pull_prefix
($e);
726 my $sub_size = util
::has_property
($e, "subcontext");
730 if (util
::is_inline_array
($e)) {
731 ParseArrayPull
($e, "r->", "NDR_SCALARS");
732 } elsif (need_wire_pointer
($e)) {
733 ParseElementPullPtr
($e, $var_prefix, $ndr_flags);
734 } elsif (need_alloc
($e)) {
735 # no scalar component
736 } elsif (my $switch = util
::has_property
($e, "switch_is")) {
737 ParseElementPullSwitch
($e, $var_prefix, $ndr_flags, $switch);
738 } elsif (defined $sub_size) {
739 pidl
"NDR_CHECK(ndr_pull_subcontext_flags_fn(ndr, $sub_size, $cprefix$var_prefix$e->{NAME}, (ndr_pull_flags_fn_t) ndr_pull_$e->{TYPE}));";
741 pidl
"NDR_CHECK(ndr_pull_$e->{TYPE}(ndr, $ndr_flags, $cprefix$var_prefix$e->{NAME}));";
743 if (my $range = util
::has_property
($e, "range")) {
744 my ($low, $high) = split(/ /, $range, 2);
745 pidl
"if ($var_prefix$e->{NAME} < $low || $var_prefix$e->{NAME} > $high) {";
746 pidl
"\treturn ndr_pull_error(ndr, NDR_ERR_RANGE, \"value out of range\");";
753 #####################################################################
754 # parse a pointer in a struct element or function
755 sub ParseElementPullPtr
($$$)
758 my($var_prefix) = shift;
759 my($ndr_flags) = shift;
761 pidl
"NDR_CHECK(ndr_pull_unique_ptr(ndr, &_ptr_$e->{NAME}));";
762 pidl
"if (_ptr_$e->{NAME}) {";
764 pidl
"NDR_ALLOC(ndr, $var_prefix$e->{NAME});";
765 if (util
::has_property
($e, "relative")) {
766 pidl
"NDR_CHECK(ndr_pull_relative_ptr1(ndr, $var_prefix$e->{NAME}, _ptr_$e->{NAME}));";
770 pidl
"\t$var_prefix$e->{NAME} = NULL;";
774 #####################################################################
775 # parse buffers in a structure element
776 sub ParseElementPushBuffer
($$$)
779 my($var_prefix) = shift;
780 my($ndr_flags) = shift;
781 my $cprefix = c_push_prefix
($e);
782 my $sub_size = util
::has_property
($e, "subcontext");
784 if (is_pure_scalar
($e)) {
790 if (need_wire_pointer
($e)) {
791 pidl
"if ($var_prefix$e->{NAME}) {";
793 if (util
::has_property
($e, "relative")) {
794 pidl
"NDR_CHECK(ndr_push_relative_ptr2(ndr, $var_prefix$e->{NAME}));";
798 if (util
::is_inline_array
($e)) {
799 ParseArrayPush
($e, "r->", "NDR_BUFFERS");
800 } elsif (util
::array_size
($e)) {
801 ParseArrayPush
($e, "r->", "NDR_SCALARS|NDR_BUFFERS");
802 } elsif (my $switch = util
::has_property
($e, "switch_is")) {
803 if ($e->{POINTERS
}) {
804 ParseElementPushSwitch
($e, $var_prefix, "NDR_BUFFERS|NDR_SCALARS", $switch);
806 ParseElementPushSwitch
($e, $var_prefix, "NDR_BUFFERS", $switch);
808 } elsif (defined $sub_size) {
809 if ($e->{POINTERS
}) {
810 pidl
"NDR_CHECK(ndr_push_subcontext_flags_fn(ndr, $sub_size, $cprefix$var_prefix$e->{NAME}, (ndr_push_flags_fn_t) ndr_push_$e->{TYPE}));";
812 } elsif ($e->{POINTERS
}) {
813 pidl
"NDR_CHECK(ndr_push_$e->{TYPE}(ndr, NDR_SCALARS|NDR_BUFFERS, $cprefix$var_prefix$e->{NAME}));";
815 pidl
"NDR_CHECK(ndr_push_$e->{TYPE}(ndr, $ndr_flags, $cprefix$var_prefix$e->{NAME}));";
818 if (need_wire_pointer
($e)) {
826 #####################################################################
827 # print buffers in a structure element
828 sub ParseElementPrintBuffer
($$)
831 my($var_prefix) = shift;
832 my $cprefix = c_push_prefix
($e);
834 if (need_wire_pointer
($e)) {
835 pidl
"if ($var_prefix$e->{NAME}) {";
839 if (util
::array_size
($e)) {
840 ParseArrayPrint
($e, $var_prefix)
841 } elsif (my $switch = util
::has_property
($e, "switch_is")) {
842 ParseElementPrintSwitch
($e, $var_prefix, $switch);
844 pidl
"ndr_print_$e->{TYPE}(ndr, \"$e->{NAME}\", $cprefix$var_prefix$e->{NAME});";
847 if (need_wire_pointer
($e)) {
853 #####################################################################
854 # parse buffers in a structure element - pull side
855 sub ParseElementPullBuffer
($$$)
858 my($var_prefix) = shift;
859 my($ndr_flags) = shift;
860 my $cprefix = c_pull_prefix
($e);
861 my $sub_size = util
::has_property
($e, "subcontext");
863 if (is_pure_scalar
($e)) {
869 if (need_wire_pointer
($e)) {
870 pidl
"if ($var_prefix$e->{NAME}) {";
872 if (util
::has_property
($e, "relative")) {
873 pidl
"struct ndr_pull_save _relative_save;";
874 pidl
"ndr_pull_save(ndr, &_relative_save);";
875 pidl
"NDR_CHECK(ndr_pull_relative_ptr2(ndr, $var_prefix$e->{NAME}));";
879 if (util
::is_inline_array
($e)) {
880 ParseArrayPull
($e, "r->", "NDR_BUFFERS");
881 } elsif (util
::array_size
($e)) {
882 ParseArrayPull
($e, "r->", "NDR_SCALARS|NDR_BUFFERS");
883 } elsif (my $switch = util
::has_property
($e, "switch_is")) {
884 if ($e->{POINTERS
}) {
885 ParseElementPullSwitch
($e, $var_prefix, "NDR_SCALARS|NDR_BUFFERS", $switch);
887 ParseElementPullSwitch
($e, $var_prefix, "NDR_BUFFERS", $switch);
889 } elsif (defined $sub_size) {
890 if ($e->{POINTERS
}) {
891 pidl
"NDR_CHECK(ndr_pull_subcontext_flags_fn(ndr, $sub_size, $cprefix$var_prefix$e->{NAME}, (ndr_pull_flags_fn_t) ndr_pull_$e->{TYPE}));";
893 } elsif ($e->{POINTERS
}) {
894 pidl
"NDR_CHECK(ndr_pull_$e->{TYPE}(ndr, NDR_SCALARS|NDR_BUFFERS, $cprefix$var_prefix$e->{NAME}));";
896 pidl
"NDR_CHECK(ndr_pull_$e->{TYPE}(ndr, $ndr_flags, $cprefix$var_prefix$e->{NAME}));";
899 if (need_wire_pointer
($e)) {
900 if (util
::has_property
($e, "relative")) {
901 pidl
"ndr_pull_restore(ndr, &_relative_save);";
910 #####################################################################
912 sub ParseStructPush
($)
916 if (! defined $struct->{ELEMENTS
}) {
920 start_flags
($struct);
922 # see if the structure contains a conformant array. If it
923 # does, then it must be the last element of the structure, and
924 # we need to push the conformant length early, as it fits on
925 # the wire before the structure (and even before the structure
927 my $e = $struct->{ELEMENTS
}[-1];
928 if (defined $e->{ARRAY_LEN
} && $e->{ARRAY_LEN
} eq "*") {
929 my $size = ParseExpr
($e, util
::array_size
($e), "r->");
930 $e->{CONFORMANT_SIZE
} = $size;
931 check_null_pointer
($size);
932 pidl
"NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, $size));";
935 if (defined $e->{TYPE
} && $e->{TYPE
} eq "string"
936 && util
::property_matches
($e, "flag", ".*LIBNDR_FLAG_STR_CONFORMANT.*")) {
937 pidl
"NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_string_array_size(ndr, r->$e->{NAME})));";
940 pidl
"if (!(ndr_flags & NDR_SCALARS)) goto buffers;";
942 pidl
"NDR_CHECK(ndr_push_struct_start(ndr));";
944 my $align = find_largest_alignment
($struct);
945 pidl
"NDR_CHECK(ndr_push_align(ndr, $align));";
947 foreach my $e (@
{$struct->{ELEMENTS
}}) {
948 ParseElementPushScalar
($e, "r->", "NDR_SCALARS");
952 pidl
"if (!(ndr_flags & NDR_BUFFERS)) goto done;";
953 foreach my $e (@
{$struct->{ELEMENTS
}}) {
954 ParseElementPushBuffer
($e, "r->", "NDR_BUFFERS");
957 pidl
"ndr_push_struct_end(ndr);";
964 #####################################################################
965 # generate a push function for an enum
969 my($type_fn) = util
::enum_type_fn
($enum);
973 pidl
"NDR_CHECK(ndr_push_$type_fn(ndr, NDR_SCALARS, r));";
978 #####################################################################
979 # generate a pull function for an enum
983 my($type_fn) = util
::enum_type_fn
($enum);
984 my($type_v_decl) = util
::map_type
(util
::enum_type_fn
($enum));
986 pidl
"$type_v_decl v;";
988 pidl
"NDR_CHECK(ndr_pull_$type_fn(ndr, NDR_SCALARS, &v));";
994 #####################################################################
995 # generate a print function for an enum
996 sub ParseEnumPrint
($)
1000 pidl
"const char *val = NULL;";
1005 pidl
"switch (r) {";
1007 my $els = \@
{$enum->{ELEMENTS
}};
1008 foreach my $i (0 .. $#{$els}) {
1009 my $e = ${$els}[$i];
1011 if ($e =~ /^(.*)=/) {
1014 pidl
"case $e: val = \"$e\"; break;";
1020 pidl
"ndr_print_enum(ndr, name, \"$enum->{TYPE}\", val, r);";
1025 $typefamily{ENUM
} = {
1026 PUSH_FN_BODY
=> \
&ParseEnumPush
,
1027 PULL_FN_BODY
=> \
&ParseEnumPull
,
1028 PRINT_FN_BODY
=> \
&ParseEnumPrint
,
1029 ALIGN
=> sub { return align_type
(util
::enum_type_fn
(shift)); }
1032 #####################################################################
1033 # generate a push function for a bitmap
1034 sub ParseBitmapPush
($)
1036 my($bitmap) = shift;
1037 my($type_fn) = util
::bitmap_type_fn
($bitmap);
1039 start_flags
($bitmap);
1041 pidl
"NDR_CHECK(ndr_push_$type_fn(ndr, NDR_SCALARS, r));";
1046 #####################################################################
1047 # generate a pull function for an bitmap
1048 sub ParseBitmapPull
($)
1050 my($bitmap) = shift;
1051 my($type_fn) = util
::bitmap_type_fn
($bitmap);
1052 my($type_decl) = util
::bitmap_type_decl
($bitmap);
1054 pidl
"$type_decl v;";
1055 start_flags
($bitmap);
1056 pidl
"NDR_CHECK(ndr_pull_$type_fn(ndr, NDR_SCALARS, &v));";
1062 #####################################################################
1063 # generate a print function for an bitmap
1064 sub ParseBitmapPrintElement
($$)
1067 my($bitmap) = shift;
1068 my($type_decl) = util
::bitmap_type_decl
($bitmap);
1069 my($type_fn) = util
::bitmap_type_fn
($bitmap);
1070 my($name) = $bitmap->{PARENT
}->{NAME
};
1073 if ($e =~ /^(\w+) .*$/) {
1076 die "Bitmap: \"$name\" invalid Flag: \"$e\"";
1079 pidl
"ndr_print_bitmap_flag(ndr, sizeof($type_decl), \"$flag\", $flag, r);";
1082 #####################################################################
1083 # generate a print function for an bitmap
1084 sub ParseBitmapPrint
($)
1086 my($bitmap) = shift;
1087 my($type_decl) = util
::bitmap_type_decl
($bitmap);
1088 my($type_fn) = util
::bitmap_type_fn
($bitmap);
1090 start_flags
($bitmap);
1092 pidl
"ndr_print_$type_fn(ndr, name, r);";
1094 pidl
"ndr->depth++;";
1095 foreach my $e (@
{$bitmap->{ELEMENTS
}}) {
1096 ParseBitmapPrintElement
($e, $bitmap);
1098 pidl
"ndr->depth--;";
1103 $typefamily{BITMAP
} = {
1104 PUSH_FN_BODY
=> \
&ParseBitmapPush
,
1105 PULL_FN_BODY
=> \
&ParseBitmapPull
,
1106 PRINT_FN_BODY
=> \
&ParseBitmapPrint
,
1107 ALIGN
=> sub { return align_type
(util
::bitmap_type_fn
(shift)); }
1110 #####################################################################
1111 # generate a struct print function
1112 sub ParseStructPrint
($)
1114 my($struct) = shift;
1116 if (! defined $struct->{ELEMENTS
}) {
1120 start_flags
($struct);
1122 pidl
"ndr->depth++;";
1123 foreach my $e (@
{$struct->{ELEMENTS
}}) {
1124 ParseElementPrintScalar
($e, "r->");
1126 pidl
"ndr->depth--;";
1131 #####################################################################
1132 # parse a struct - pull side
1133 sub ParseStructPull
($)
1135 my($struct) = shift;
1138 if (! defined $struct->{ELEMENTS
}) {
1142 # see if the structure contains a conformant array. If it
1143 # does, then it must be the last element of the structure, and
1144 # we need to pull the conformant length early, as it fits on
1145 # the wire before the structure (and even before the structure
1147 my $e = $struct->{ELEMENTS
}[-1];
1148 if (defined $e->{ARRAY_LEN
} && $e->{ARRAY_LEN
} eq "*") {
1152 if (defined $e->{TYPE
} && $e->{TYPE
} eq "string"
1153 && util
::property_matches
($e, "flag", ".*LIBNDR_FLAG_STR_CONFORMANT.*")) {
1157 if (defined $conform_e) {
1159 pidl
"uint32_t _conformant_size;";
1160 $conform_e->{CONFORMANT_SIZE
} = "_conformant_size";
1163 # declare any internal pointers we need
1164 foreach my $e (@
{$struct->{ELEMENTS
}}) {
1165 if (need_wire_pointer
($e)) {
1166 pidl
"uint32_t _ptr_$e->{NAME};";
1170 start_flags
($struct);
1172 pidl
"if (!(ndr_flags & NDR_SCALARS)) goto buffers;";
1174 pidl
"NDR_CHECK(ndr_pull_struct_start(ndr));";
1176 if (defined $conform_e) {
1177 pidl
"NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &$conform_e->{CONFORMANT_SIZE}));";
1180 my $align = find_largest_alignment
($struct);
1181 pidl
"NDR_CHECK(ndr_pull_align(ndr, $align));";
1183 foreach my $e (@
{$struct->{ELEMENTS
}}) {
1184 ParseElementPullScalar
($e, "r->", "NDR_SCALARS");
1188 pidl
"if (!(ndr_flags & NDR_BUFFERS)) goto done;";
1189 foreach my $e (@
{$struct->{ELEMENTS
}}) {
1190 ParseElementPullBuffer
($e, "r->", "NDR_BUFFERS");
1193 foreach my $e (@
{$struct->{ELEMENTS
}}) {
1194 CheckArraySizes
($e, "r->");
1197 pidl
"ndr_pull_struct_end(ndr);";
1204 #####################################################################
1205 # calculate size of ndr struct
1206 sub ParseStructNdrSize
($)
1209 my $static = fn_prefix
($t);
1212 pidl
"size_t ndr_size_$t->{NAME}(const struct $t->{NAME} *r, int flags)";
1215 if (my $flags = util
::has_property
($t, "flag")) {
1216 pidl
"flags |= $flags;";
1218 pidl
"return ndr_size_struct(r, flags, (ndr_push_flags_fn_t)ndr_push_$t->{NAME});";
1224 $typefamily{STRUCT
} = {
1225 PUSH_FN_BODY
=> \
&ParseStructPush
,
1226 PULL_FN_BODY
=> \
&ParseStructPull
,
1227 PRINT_FN_BODY
=> \
&ParseStructPrint
,
1228 SIZE_FN
=> \
&ParseStructNdrSize
,
1229 ALIGN
=> \
&find_largest_alignment
1232 #####################################################################
1233 # calculate size of ndr struct
1234 sub ParseUnionNdrSize
($)
1237 my $static = fn_prefix
($t);
1240 pidl
"size_t ndr_size_$t->{NAME}(const union $t->{NAME} *r, int level, int flags)";
1243 if (my $flags = util
::has_property
($t, "flag")) {
1244 pidl
"flags |= $flags;";
1246 pidl
"return ndr_size_union(r, flags, level, (ndr_push_union_fn_t)ndr_push_$t->{NAME});";
1252 #####################################################################
1253 # parse a union - push side
1254 sub ParseUnionPush
($)
1257 my $have_default = 0;
1261 pidl
"if (!(ndr_flags & NDR_SCALARS)) goto buffers;";
1263 pidl
"NDR_CHECK(ndr_push_struct_start(ndr));";
1265 # my $align = union_alignment($e);
1266 # pidl "NDR_CHECK(ndr_push_align(ndr, $align));";
1268 pidl
"switch (level) {";
1270 foreach my $el (@
{$e->{ELEMENTS
}}) {
1271 if (util
::has_property
($el, "default")) {
1275 pidl
"case $el->{PROPERTIES}->{case}:";
1278 if ($el->{TYPE
} ne "EMPTY") {
1280 ParseElementPushScalar
($el, "r->", "NDR_SCALARS");
1286 if (! $have_default) {
1288 pidl
"\treturn ndr_push_error(ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value \%u\", level);";
1293 pidl
"if (!(ndr_flags & NDR_BUFFERS)) goto done;";
1294 pidl
"switch (level) {";
1296 foreach my $el (@
{$e->{ELEMENTS
}}) {
1297 if (util
::has_property
($el, "default")) {
1300 pidl
"case $el->{PROPERTIES}->{case}:";
1302 if ($el->{TYPE
} ne "EMPTY") {
1304 ParseElementPushBuffer
($el, "r->", "NDR_BUFFERS");
1310 if (! $have_default) {
1312 pidl
"\treturn ndr_push_error(ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value \%u\", level);";
1316 pidl
"ndr_push_struct_end(ndr);";
1321 #####################################################################
1323 sub ParseUnionPrint
($)
1326 my $have_default = 0;
1330 pidl
"switch (level) {";
1332 foreach my $el (@
{$e->{ELEMENTS
}}) {
1333 if (util
::has_property
($el, "default")) {
1337 pidl
"case $el->{PROPERTIES}->{case}:";
1339 if ($el->{TYPE
} ne "EMPTY") {
1341 ParseElementPrintScalar
($el, "r->");
1347 if (! $have_default) {
1349 pidl
"\tndr_print_bad_level(ndr, name, level);";
1357 #####################################################################
1358 # parse a union - pull side
1359 sub ParseUnionPull
($)
1362 my $have_default = 0;
1366 pidl
"if (!(ndr_flags & NDR_SCALARS)) goto buffers;";
1368 pidl
"NDR_CHECK(ndr_pull_struct_start(ndr));";
1370 # my $align = union_alignment($e);
1371 # pidl "\tNDR_CHECK(ndr_pull_align(ndr, $align));\n";
1373 pidl
"switch (level) {";
1375 foreach my $el (@
{$e->{ELEMENTS
}}) {
1376 if (util
::has_property
($el, "default")) {
1380 pidl
"case $el->{PROPERTIES}->{case}: {";
1382 if ($el->{TYPE
} ne "EMPTY") {
1384 if ($el->{POINTERS
}) {
1385 pidl
"uint32_t _ptr_$el->{NAME};";
1387 ParseElementPullScalar
($el, "r->", "NDR_SCALARS");
1393 if (! $have_default) {
1395 pidl
"\treturn ndr_pull_error(ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value \%u\", level);";
1400 pidl
"if (!(ndr_flags & NDR_BUFFERS)) goto done;";
1401 pidl
"switch (level) {";
1403 foreach my $el (@
{$e->{ELEMENTS
}}) {
1404 if (util
::has_property
($el, "default")) {
1407 pidl
"case $el->{PROPERTIES}->{case}:";
1409 if ($el->{TYPE
} ne "EMPTY") {
1411 ParseElementPullBuffer
($el, "r->", "NDR_BUFFERS");
1417 if (! $have_default) {
1419 pidl
"\treturn ndr_pull_error(ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value \%u\", level);";
1423 pidl
"ndr_pull_struct_end(ndr);";
1428 $typefamily{UNION
} = {
1429 PUSH_FN_BODY
=> \
&ParseUnionPush
,
1430 PULL_FN_BODY
=> \
&ParseUnionPull
,
1431 PRINT_FN_BODY
=> \
&ParseUnionPrint
,
1432 SIZE_FN
=> \
&ParseUnionNdrSize
,
1433 ALIGN
=> \
&find_largest_alignment
1437 #####################################################################
1438 # parse a typedef - push side
1439 sub ParseTypedefPush
($)
1442 my $static = fn_prefix
($e);
1444 if (! needed
::is_needed
("push_$e->{NAME}")) {
1445 # print "push_$e->{NAME} not needed\n";
1450 if ($e->{DATA
}->{TYPE
} eq "STRUCT") {
1451 $args = "struct ndr_push *ndr, int ndr_flags, struct $e->{NAME} *r";
1454 if ($e->{DATA
}->{TYPE
} eq "UNION") {
1455 $args = "struct ndr_push *ndr, int ndr_flags, int level, union $e->{NAME} *r";
1458 if ($e->{DATA
}->{TYPE
} eq "ENUM") {
1459 $args = "struct ndr_push *ndr, int ndr_flags, enum $e->{NAME} r";
1462 if ($e->{DATA
}->{TYPE
} eq "BITMAP") {
1463 my $type_decl = util
::bitmap_type_decl
($e->{DATA
});
1464 $args = "struct ndr_push *ndr, int ndr_flags, $type_decl r";
1467 pidl
$static . "NTSTATUS ndr_push_$e->{NAME}($args)";
1471 $typefamily{$e->{DATA
}->{TYPE
}}->{PUSH_FN_BODY
}($e->{DATA
});
1472 pidl
"return NT_STATUS_OK;";
1478 #####################################################################
1479 # parse a typedef - pull side
1480 sub ParseTypedefPull
($)
1483 my $static = fn_prefix
($e);
1485 if (! needed
::is_needed
("pull_$e->{NAME}")) {
1486 # print "pull_$e->{NAME} not needed\n";
1492 if ($e->{DATA
}->{TYPE
} eq "STRUCT") {
1493 $args = "struct ndr_pull *ndr, int ndr_flags, struct $e->{NAME} *r";
1496 if ($e->{DATA
}->{TYPE
} eq "UNION") {
1497 $args = "struct ndr_pull *ndr, int ndr_flags, int level, union $e->{NAME} *r";
1500 if ($e->{DATA
}->{TYPE
} eq "ENUM") {
1501 $args = "struct ndr_pull *ndr, int ndr_flags, enum $e->{NAME} *r";
1504 if ($e->{DATA
}->{TYPE
} eq "BITMAP") {
1505 my $type_decl = util
::bitmap_type_decl
($e->{DATA
});
1506 $args = "struct ndr_pull *ndr, int ndr_flags, $type_decl *r";
1509 pidl
$static . "NTSTATUS ndr_pull_$e->{NAME}($args)";
1513 $typefamily{$e->{DATA
}->{TYPE
}}->{PULL_FN_BODY
}($e->{DATA
});
1514 pidl
"return NT_STATUS_OK;";
1520 #####################################################################
1521 # parse a typedef - print side
1522 sub ParseTypedefPrint
($)
1526 if ($e->{DATA
}->{TYPE
} eq "STRUCT") {
1527 pidl
"void ndr_print_$e->{NAME}(struct ndr_print *ndr, const char *name, struct $e->{NAME} *r)";
1530 pidl
"ndr_print_struct(ndr, name, \"$e->{NAME}\");";
1533 if ($e->{DATA
}->{TYPE
} eq "UNION") {
1534 pidl
"void ndr_print_$e->{NAME}(struct ndr_print *ndr, const char *name, int level, union $e->{NAME} *r)";
1537 pidl
"ndr_print_union(ndr, name, level, \"$e->{NAME}\");";
1540 if ($e->{DATA
}->{TYPE
} eq "ENUM") {
1541 pidl
"void ndr_print_$e->{NAME}(struct ndr_print *ndr, const char *name, enum $e->{NAME} r)";
1546 if ($e->{DATA
}->{TYPE
} eq "BITMAP") {
1547 my $type_decl = util
::bitmap_type_decl
($e->{DATA
});
1548 pidl
"void ndr_print_$e->{NAME}(struct ndr_print *ndr, const char *name, $type_decl r)";
1553 $typefamily{$e->{DATA
}->{TYPE
}}->{PRINT_FN_BODY
}($e->{DATA
});
1558 #####################################################################
1559 ## calculate the size of a structure
1560 sub ParseTypedefNdrSize
($)
1563 if (! needed
::is_needed
("ndr_size_$t->{NAME}")) {
1567 $typefamily{$t->{DATA
}->{TYPE
}}->{SIZE_FN
}($t);
1570 #####################################################################
1571 # parse a function - print side
1572 sub ParseFunctionPrint
($)
1576 pidl
"void ndr_print_$fn->{NAME}(struct ndr_print *ndr, const char *name, int flags, struct $fn->{NAME} *r)";
1579 pidl
"ndr_print_struct(ndr, name, \"$fn->{NAME}\");";
1580 pidl
"ndr->depth++;";
1582 pidl
"if (flags & NDR_SET_VALUES) {";
1583 pidl
"\tndr->flags |= LIBNDR_PRINT_SET_VALUES;";
1586 pidl
"if (flags & NDR_IN) {";
1588 pidl
"ndr_print_struct(ndr, \"in\", \"$fn->{NAME}\");";
1589 pidl
"ndr->depth++;";
1591 foreach my $e (@
{$fn->{ELEMENTS
}}) {
1592 if (util
::has_property
($e, "in")) {
1593 ParseElementPrintScalar
($e, "r->in.");
1596 pidl
"ndr->depth--;";
1600 pidl
"if (flags & NDR_OUT) {";
1602 pidl
"ndr_print_struct(ndr, \"out\", \"$fn->{NAME}\");";
1603 pidl
"ndr->depth++;";
1604 foreach my $e (@
{$fn->{ELEMENTS
}}) {
1605 if (util
::has_property
($e, "out")) {
1606 ParseElementPrintScalar
($e, "r->out.");
1609 if ($fn->{RETURN_TYPE
} && $fn->{RETURN_TYPE
} ne "void") {
1611 $cprefix = "" if (is_scalar_type
($fn->{RETURN_TYPE
})) ; # FIXME: Should really use util::c_push_prefix here
1612 pidl
"ndr_print_$fn->{RETURN_TYPE}(ndr, \"result\", $cprefix"."r->out.result);";
1614 pidl
"ndr->depth--;";
1618 pidl
"ndr->depth--;";
1624 #####################################################################
1625 # parse a function element
1626 sub ParseFunctionElementPush
($$)
1631 if (util
::array_size
($e)) {
1632 if (need_wire_pointer
($e)) {
1633 pidl
"NDR_CHECK(ndr_push_unique_ptr(ndr, r->$inout.$e->{NAME}));";
1634 pidl
"if (r->$inout.$e->{NAME}) {";
1636 ParseArrayPush
($e, "r->$inout.", "NDR_SCALARS|NDR_BUFFERS");
1640 ParseArrayPush
($e, "r->$inout.", "NDR_SCALARS|NDR_BUFFERS");
1643 ParseElementPushScalar
($e, "r->$inout.", "NDR_SCALARS|NDR_BUFFERS");
1645 if ($e->{POINTERS
}) {
1646 ParseElementPushBuffer
($e, "r->$inout.", "NDR_SCALARS|NDR_BUFFERS");
1651 #####################################################################
1653 sub ParseFunctionPush
($)
1656 my $static = fn_prefix
($fn);
1658 pidl
$static . "NTSTATUS ndr_push_$fn->{NAME}(struct ndr_push *ndr, int flags, struct $fn->{NAME} *r)";
1662 pidl
"if (!(flags & NDR_IN)) goto ndr_out;";
1665 foreach my $e (@
{$fn->{ELEMENTS
}}) {
1666 if (util
::has_property
($e, "in")) {
1667 ParseFunctionElementPush
($e, "in");
1672 pidl
"if (!(flags & NDR_OUT)) goto done;";
1675 foreach my $e (@
{$fn->{ELEMENTS
}}) {
1676 if (util
::has_property
($e, "out")) {
1677 ParseFunctionElementPush
($e, "out");
1681 if ($fn->{RETURN_TYPE
} && $fn->{RETURN_TYPE
} ne "void") {
1682 pidl
"NDR_CHECK(ndr_push_$fn->{RETURN_TYPE}(ndr, NDR_SCALARS, r->out.result));";
1686 pidl
"return NT_STATUS_OK;";
1692 #####################################################################
1693 # parse a function element
1694 sub ParseFunctionElementPull
($$)
1699 if (util
::array_size
($e)) {
1700 if (need_wire_pointer
($e)) {
1701 pidl
"NDR_CHECK(ndr_pull_unique_ptr(ndr, &_ptr_$e->{NAME}));";
1702 pidl
"r->$inout.$e->{NAME} = NULL;";
1703 pidl
"if (_ptr_$e->{NAME}) {";
1705 } elsif ($inout eq "out" && util
::has_property
($e, "ref")) {
1706 pidl
"if (r->$inout.$e->{NAME}) {";
1712 ParseArrayPull
($e, "r->$inout.", "NDR_SCALARS|NDR_BUFFERS");
1716 if ($inout eq "out" && util
::has_property
($e, "ref")) {
1717 pidl
"if (ndr->flags & LIBNDR_FLAG_REF_ALLOC) {";
1718 pidl
"\tNDR_ALLOC(ndr, r->out.$e->{NAME});";
1721 if ($inout eq "in" && util
::has_property
($e, "ref")) {
1722 pidl
"NDR_ALLOC(ndr, r->in.$e->{NAME});";
1725 ParseElementPullScalar
($e, "r->$inout.", "NDR_SCALARS|NDR_BUFFERS");
1726 if ($e->{POINTERS
}) {
1727 ParseElementPullBuffer
($e, "r->$inout.", "NDR_SCALARS|NDR_BUFFERS");
1732 ############################################################
1733 # allocate ref variables
1734 sub AllocateRefVars
($)
1737 my $asize = util
::array_size
($e);
1739 # note that if the variable is also an "in"
1740 # variable then we copy the initial value from
1743 if (!defined $asize) {
1744 # its a simple variable
1745 pidl
"NDR_ALLOC(ndr, r->out.$e->{NAME});";
1746 if (util
::has_property
($e, "in")) {
1747 pidl
"*r->out.$e->{NAME} = *r->in.$e->{NAME};";
1749 pidl
"ZERO_STRUCTP(r->out.$e->{NAME});";
1755 my $size = ParseExpr
($e, $asize, "r->out.");
1756 check_null_pointer
($size);
1757 pidl
"NDR_ALLOC_N(ndr, r->out.$e->{NAME}, $size);";
1758 if (util
::has_property
($e, "in")) {
1759 pidl
"memcpy(r->out.$e->{NAME},r->in.$e->{NAME},$size * sizeof(*r->in.$e->{NAME}));";
1761 pidl
"memset(r->out.$e->{NAME}, 0, $size * sizeof(*r->out.$e->{NAME}));";
1765 #####################################################################
1767 sub ParseFunctionPull
($)
1770 my $static = fn_prefix
($fn);
1772 # pull function args
1773 pidl
$static . "NTSTATUS ndr_pull_$fn->{NAME}(struct ndr_pull *ndr, int flags, struct $fn->{NAME} *r)";
1777 # declare any internal pointers we need
1778 foreach my $e (@
{$fn->{ELEMENTS
}}) {
1779 if (need_wire_pointer
($e)) {
1780 pidl
"uint32_t _ptr_$e->{NAME};";
1784 pidl
"if (!(flags & NDR_IN)) goto ndr_out;";
1787 # auto-init the out section of a structure. I originally argued that
1788 # this was a bad idea as it hides bugs, but coping correctly
1789 # with initialisation and not wiping ref vars is turning
1790 # out to be too tricky (tridge)
1791 foreach my $e (@
{$fn->{ELEMENTS
}}) {
1792 if (util
::has_property
($e, "out")) {
1793 pidl
"ZERO_STRUCT(r->out);";
1799 foreach my $e (@
{$fn->{ELEMENTS
}}) {
1800 if (util
::has_property
($e, "in")) {
1801 ParseFunctionElementPull
($e, "in");
1803 # we need to allocate any reference output variables, so that
1804 # a dcerpc backend can be sure they are non-null
1805 if (util
::has_property
($e, "out") && util
::has_property
($e, "ref")) {
1806 AllocateRefVars
($e);
1810 foreach my $e (@
{$fn->{ELEMENTS
}}) {
1811 if (util
::has_property
($e, "in")) {
1812 CheckArraySizes
($e, "r->in.");
1817 pidl
"if (!(flags & NDR_OUT)) goto done;";
1820 foreach my $e (@
{$fn->{ELEMENTS
}}) {
1821 if (util
::has_property
($e, "out")) {
1822 ParseFunctionElementPull
($e, "out");
1826 foreach my $e (@
{$fn->{ELEMENTS
}}) {
1827 if (util
::has_property
($e, "out")) {
1828 CheckArraySizes
($e, "r->out.");
1832 if ($fn->{RETURN_TYPE
} && $fn->{RETURN_TYPE
} ne "void") {
1833 pidl
"NDR_CHECK(ndr_pull_$fn->{RETURN_TYPE}(ndr, NDR_SCALARS, &r->out.result));";
1838 pidl
"return NT_STATUS_OK;";
1844 #####################################################################
1845 # produce a function call table
1846 sub FunctionTable
($)
1848 my($interface) = shift;
1849 my($data) = $interface->{INHERITED_DATA
};
1851 my $uname = uc $interface->{NAME
};
1853 foreach my $d (@
{$data}) {
1854 if ($d->{TYPE
} eq "FUNCTION") { $count++; }
1857 return if ($count == 0);
1859 pidl
"static const struct dcerpc_interface_call $interface->{NAME}\_calls[] = {";
1860 foreach my $d (@
{$data}) {
1861 if ($d->{TYPE
} eq "FUNCTION") {
1863 pidl
"\t\t\"$d->{NAME}\",";
1864 pidl
"\t\tsizeof(struct $d->{NAME}),";
1865 pidl
"\t\t(ndr_push_flags_fn_t) ndr_push_$d->{NAME},";
1866 pidl
"\t\t(ndr_pull_flags_fn_t) ndr_pull_$d->{NAME},";
1867 pidl
"\t\t(ndr_print_function_t) ndr_print_$d->{NAME}";
1871 pidl
"\t{ NULL, 0, NULL, NULL, NULL }";
1875 # If no endpoint is set, default to the interface name as a named pipe
1876 if (! defined $interface->{PROPERTIES
}->{endpoint
}) {
1877 $interface->{PROPERTIES
}->{endpoint
} = "\"ncacn_np:[\\\\pipe\\\\" . $interface->{NAME
} . "]\"";
1880 my @e = split / /, $interface->{PROPERTIES
}->{endpoint
};
1881 my $endpoint_count = $#e + 1;
1883 pidl
"static const char * const $interface->{NAME}\_endpoint_strings[] = {";
1884 foreach my $ep (@e) {
1890 pidl
"static const struct dcerpc_endpoint_list $interface->{NAME}\_endpoints = {";
1891 pidl
"\t$endpoint_count, $interface->{NAME}\_endpoint_strings";
1895 pidl
"\nconst struct dcerpc_interface_table dcerpc_table_$interface->{NAME} = {";
1896 pidl
"\t\"$interface->{NAME}\",";
1897 pidl
"\tDCERPC_$uname\_UUID,";
1898 pidl
"\tDCERPC_$uname\_VERSION,";
1899 pidl
"\tDCERPC_$uname\_HELPSTRING,";
1901 pidl
"\t$interface->{NAME}\_calls,";
1902 pidl
"\t&$interface->{NAME}\_endpoints";
1906 pidl
"static NTSTATUS dcerpc_ndr_$interface->{NAME}_init(void)";
1908 pidl
"\treturn librpc_register_interface(&dcerpc_table_$interface->{NAME});";
1913 #####################################################################
1914 # parse the interface definitions
1915 sub ParseInterface
($)
1917 my($interface) = shift;
1918 my($data) = $interface->{DATA
};
1921 foreach my $d (@
{$data}) {
1922 ($d->{TYPE
} eq "TYPEDEF") &&
1923 ParseTypedefPush
($d);
1924 ($d->{TYPE
} eq "FUNCTION") &&
1925 ParseFunctionPush
($d);
1929 foreach my $d (@
{$data}) {
1930 ($d->{TYPE
} eq "TYPEDEF") &&
1931 ParseTypedefPull
($d);
1932 ($d->{TYPE
} eq "FUNCTION") &&
1933 ParseFunctionPull
($d);
1937 foreach my $d (@
{$data}) {
1938 if ($d->{TYPE
} eq "TYPEDEF" &&
1939 !util
::has_property
($d, "noprint")) {
1940 ParseTypedefPrint
($d);
1942 if ($d->{TYPE
} eq "FUNCTION" &&
1943 !util
::has_property
($d, "noprint")) {
1944 ParseFunctionPrint
($d);
1949 foreach my $d (@
{$data}) {
1950 ($d->{TYPE
} eq "TYPEDEF") &&
1951 ParseTypedefNdrSize
($d);
1954 FunctionTable
($interface);
1957 sub RegistrationFunction
($$)
1960 my $filename = shift;
1962 $filename =~ /.*\/ndr_
(.*).c
/;
1964 pidl
"NTSTATUS dcerpc_$basename\_init(void)";
1967 pidl
"NTSTATUS status = NT_STATUS_OK;";
1968 foreach my $interface (@
{$idl}) {
1969 next if $interface->{TYPE
} ne "INTERFACE";
1971 my $data = $interface->{INHERITED_DATA
};
1973 foreach my $d (@
{$data}) {
1974 if ($d->{TYPE
} eq "FUNCTION") { $count++; }
1977 next if ($count == 0);
1979 pidl
"status = dcerpc_ndr_$interface->{NAME}_init();";
1980 pidl
"if (NT_STATUS_IS_ERR(status)) {";
1981 pidl
"\treturn status;";
1985 pidl
"return status;";
1991 sub CheckPointerTypes
($$)
1994 my $default = shift;
1996 foreach my $e (@
{$s->{ELEMENTS
}}) {
1997 if ($e->{POINTERS
}) {
1998 if (not defined(pointer_type
($e))) {
1999 $e->{PROPERTIES
}->{$default} = 1;
2002 if (pointer_type
($e) eq "ptr") {
2003 print "Warning: ptr is not supported by pidl yet\n";
2009 sub LoadInterface
($)
2013 if (not util
::has_property
($x, "pointer_default")) {
2014 # MIDL defaults to "ptr" in DCE compatible mode (/osf)
2015 # and "unique" in Microsoft Extensions mode (default)
2016 $x->{PROPERTIES
}->{pointer_default
} = "unique";
2019 foreach my $d (@
{$x->{DATA
}}) {
2020 if (($d->{TYPE
} eq "DECLARE") or ($d->{TYPE
} eq "TYPEDEF")) {
2021 $typedefs{$d->{NAME
}} = $d;
2022 if ($d->{DATA
}->{TYPE
} eq "STRUCT" or $d->{DATA
}->{TYPE
} eq "UNION") {
2023 CheckPointerTypes
($d->{DATA
}, $x->{PROPERTIES
}->{pointer_default
});
2026 if (defined($d->{PROPERTIES
}) && !defined($d->{DATA
}->{PROPERTIES
})) {
2027 $d->{DATA
}->{PROPERTIES
} = $d->{PROPERTIES
};
2030 if ($d->{TYPE
} eq "FUNCTION") {
2031 CheckPointerTypes
($d,
2032 $x->{PROPERTIES
}->{pointer_default
} # MIDL defaults to "ref"
2038 # Add ORPC specific bits to an interface.
2039 sub InterfaceORPC
($)
2042 # Add [in] ORPCTHIS *this, [out] ORPCTHAT *that
2043 # for 'object' interfaces
2044 if (util
::has_property
($x, "object")) {
2045 foreach my $e (@
{$x->{DATA
}}) {
2046 if($e->{TYPE
} eq "FUNCTION") {
2047 $e->{PROPERTIES
}->{object
} = 1;
2048 unshift(@
{$e->{ELEMENTS
}},
2049 { 'NAME' => 'ORPCthis',
2051 'PROPERTIES' => { 'in' => '1' },
2052 'TYPE' => 'ORPCTHIS'
2054 unshift(@
{$e->{ELEMENTS
}},
2055 { 'NAME' => 'ORPCthat',
2057 'PROPERTIES' => { 'out' => '1' },
2058 'TYPE' => 'ORPCTHAT'
2069 foreach my $x (@
{$idl}) {
2074 #####################################################################
2075 # parse a parsed IDL structure back into an IDL file
2079 my($filename) = shift;
2080 my $h_filename = $filename;
2085 if ($h_filename =~ /(.*)\.c/) {
2086 $h_filename = "$1.h";
2089 pidl
"/* parser auto-generated by pidl */";
2091 pidl
"#include \"includes.h\"";
2092 pidl
"#include \"$h_filename\"";
2095 foreach my $x (@
{$idl}) {
2096 if ($x->{TYPE
} eq "INTERFACE") {
2097 needed
::BuildNeeded
($x);
2102 RegistrationFunction
($idl, $filename);
2107 RegisterPrimitives
();