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
26 return $typefamily{$n};
29 sub RegisterPrimitives
()
50 "error_status_t" => 4,
60 foreach my $k (keys %type_alignments) {
66 ALIGN
=> $type_alignments{$k}
76 if (my $dt = $typedefs{$type}->{DATA
}->{TYPE
}) {
77 return 1 if ($dt eq "SCALAR" or $dt eq "ENUM" or $dt eq "BITMAP");
87 return undef unless $e->{POINTERS
};
89 return "ref" if (util
::has_property
($e, "ref"));
90 return "ptr" if (util
::has_property
($e, "ptr"));
91 return "unique" if (util
::has_property
($e, "unique"));
92 return "relative" if (util
::has_property
($e, "relative"));
93 return "ignore" if (util
::has_property
($e, "ignore"));
98 # return 1 if this is a fixed array
102 my $len = $e->{"ARRAY_LEN"};
103 if (defined $len && util
::is_constant
($len)) {
109 # return 1 if this is a conformant array
110 sub is_conformant_array
($)
113 return 1 if (util
::has_property
($e, "size_is"));
117 # return 1 if this is a inline array
118 sub is_inline_array
($)
121 my $len = $e->{"ARRAY_LEN"};
122 if (is_fixed_array
($e) ||
123 defined $len && $len ne "*") {
129 # return 1 if this is a varying array
130 sub is_varying_array
($)
133 return 1 if (util
::has_property
($e, "length_is"));
137 # return 1 if this is a surrounding array (sometimes
138 # referred to as an embedded array). Can only occur as
139 # the last element in a struct and can not contain any pointers.
140 sub is_surrounding_array
($)
144 return ($e->{POINTERS
} == 0
145 and defined $e->{ARRAY_LEN
}
146 and $e->{ARRAY_LEN
} eq "*"
147 and $e == $e->{PARENT
}->{ELEMENTS
}[-1]
148 and $e->{PARENT
}->{TYPE
} ne "FUNCTION");
155 return "conformant-varying" if (is_varying_array
($e) and is_conformant_array
($e));
156 return "conformant" if (is_varying_array
($e));
157 return "varying" if (is_varying_array
($e));
158 return "inline" if (is_inline_array
($e));
159 return "fixed" if (is_fixed_array
($e));
164 # determine if an element needs a reference pointer on the wire
165 # in its NDR representation
166 sub need_wire_pointer
($)
170 my $n = $e->{POINTERS
};
171 my $pt = pointer_type
($e);
173 if (defined($pt) and $pt eq "ref") {
180 # determine if an element is a pure scalar. pure scalars do not
181 # have a "buffers" section in NDR
182 sub is_pure_scalar
($)
185 if (util
::has_property
($e, "ref")) {
188 if (is_scalar_type
($e->{TYPE
}) &&
190 !util
::array_size
($e)) {
196 # see if a variable needs to be allocated by the NDR subsystem on pull
201 if (util
::has_property
($e, "ref")) {
205 if ($e->{POINTERS
} || util
::array_size
($e)) {
212 # determine the C prefix used to refer to a variable when passing to a push
213 # function. This will be '*' for pointers to scalar types, '' for scalar
214 # types and normal pointers and '&' for pass-by-reference structures
219 if ($e->{TYPE
} =~ "string") {
223 if (is_scalar_type
($e->{TYPE
}) &&
227 if (!is_scalar_type
($e->{TYPE
}) &&
229 !util
::array_size
($e)) {
235 # determine the C prefix used to refer to a variable when passing to a pull
241 if (!$e->{POINTERS
} && !util
::array_size
($e)) {
245 if ($e->{TYPE
} =~ "string") {
270 $tabs = substr($tabs, 0, -1);
273 ###################################
274 # find a sibling var in a structure
279 my($fn) = $e->{PARENT
};
281 if ($name =~ /\*(.*)/) {
285 for my $e2 (@
{$fn->{ELEMENTS
}}) {
286 return $e2 if ($e2->{NAME
} eq $name);
289 die "invalid sibling '$name'";
292 ####################################################################
293 # work out the name of a size_is() variable
298 my($var_prefix) = shift;
300 my($fn) = $e->{PARENT
};
302 return $size if (util
::is_constant
($size));
304 return $size if ($size =~ /ndr->|\(/);
308 if ($size =~ /\*(.*)/) {
313 if ($fn->{TYPE
} ne "FUNCTION") {
314 return $prefix . "r->$size";
317 my $e2 = find_sibling
($e, $size);
319 if (util
::has_property
($e2, "in") && util
::has_property
($e2, "out")) {
320 return $prefix . "$var_prefix$size";
323 if (util
::has_property
($e2, "in")) {
324 return $prefix . "r->in.$size";
327 if (util
::has_property
($e2, "out")) {
328 return $prefix . "r->out.$size";
331 die "invalid variable in $size for element $e->{NAME} in $fn->{NAME}\n";
334 #####################################################################
335 # check that a variable we get from ParseExpr isn't a null pointer
336 sub check_null_pointer
($)
339 if ($size =~ /^\*/) {
340 my $size2 = substr($size, 1);
341 pidl
"if ($size2 == NULL) return NT_STATUS_INVALID_PARAMETER_MIX;";
345 #####################################################################
346 # check that a variable we get from ParseExpr isn't a null pointer
347 # void return varient
348 sub check_null_pointer_void
($)
351 if ($size =~ /^\*/) {
352 my $size2 = substr($size, 1);
353 pidl
"if ($size2 == NULL) return;";
357 #####################################################################
358 # work out is a parse function should be declared static or not
362 if ($fn->{TYPE
} eq "TYPEDEF") {
363 if (util
::has_property
($fn, "public")) {
368 if ($fn->{TYPE
} eq "FUNCTION") {
369 if (util
::has_property
($fn, "public")) {
376 ###################################################################
377 # setup any special flags for an element or structure
381 my $flags = util
::has_property
($e, "flag");
382 if (defined $flags) {
383 pidl
"{ uint32_t _flags_save_$e->{TYPE} = ndr->flags;";
384 pidl
"ndr_set_flags(&ndr->flags, $flags);";
388 ###################################################################
389 # end any special flags for an element or structure
393 my $flags = util
::has_property
($e, "flag");
394 if (defined $flags) {
395 pidl
"ndr->flags = _flags_save_$e->{TYPE};\n\t}";
399 #####################################################################
400 # work out the correct alignment for a structure or union
401 sub find_largest_alignment
($)
406 for my $e (@
{$s->{ELEMENTS
}}) {
409 if (need_wire_pointer
($e)) {
412 $a = align_type
($e->{TYPE
});
415 $align = $a if ($align < $a);
421 #####################################################################
427 unless (defined($typedefs{$e}) && defined($typedefs{$e}->{DATA
}->{TYPE
})) {
428 # it must be an external type - all we can do is guess
429 # print "Warning: assuming alignment of unknown type '$e' is 4\n";
433 my $dt = $typedefs{$e}->{DATA
};
435 return $dt->{ALIGN
} if ($dt->{ALIGN
});
436 return $typefamily{$dt->{TYPE
}}->{ALIGN
}->($dt);
439 #####################################################################
440 # parse array preceding data - push side
441 sub ParseArrayPushPreceding
($$$)
444 my $var_prefix = shift;
445 my $ndr_flags = shift;
447 my $size = ParseExpr
($e, util
::array_size
($e), $var_prefix);
449 if (!is_inline_array
($e)) {
450 # we need to emit the array size
451 pidl
"NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, $size));";
455 #####################################################################
456 # parse the data of an array - push side
457 sub ParseArrayPush
($$$)
460 my $var_prefix = shift;
461 my $ndr_flags = shift;
463 my $size = ParseExpr
($e, util
::array_size
($e), $var_prefix);
465 if (!is_surrounding_array
($e)) {
466 ParseArrayPushPreceding
($e, $var_prefix, $ndr_flags);
469 if (is_varying_array
($e)) {
470 my $length = util
::has_property
($e, "length_is");
471 $length = ParseExpr
($e, $length, $var_prefix);
472 pidl
"NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0));";
473 pidl
"NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, $length));";
477 if (is_scalar_type
($e->{TYPE
})) {
478 pidl
"NDR_CHECK(ndr_push_array_$e->{TYPE}(ndr, $ndr_flags, $var_prefix$e->{NAME}, $size));";
480 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}));";
484 #####################################################################
486 sub ParseArrayPrint
($$)
489 my $var_prefix = shift;
490 my $size = ParseExpr
($e, util
::array_size
($e), $var_prefix);
491 my $length = util
::has_property
($e, "length_is");
493 if (defined $length) {
494 $size = ParseExpr
($e, $length, $var_prefix);
497 if (is_scalar_type
($e->{TYPE
})) {
498 pidl
"ndr_print_array_$e->{TYPE}(ndr, \"$e->{NAME}\", $var_prefix$e->{NAME}, $size);";
500 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});";
504 #####################################################################
505 # check the size_is and length_is constraints
506 sub CheckArraySizes
($$)
509 my $var_prefix = shift;
511 if (!is_surrounding_array
($e) &&
512 is_conformant_array
($e)) {
513 my $size = ParseExpr
($e, util
::array_size
($e), $var_prefix);
514 pidl
"if ($var_prefix$e->{NAME}) {";
516 check_null_pointer
($size);
517 pidl
"NDR_CHECK(ndr_check_array_size(ndr, (void*)&$var_prefix$e->{NAME}, $size));";
522 if (is_varying_array
($e)) {
523 my $length = util
::has_property
($e, "length_is");
524 $length = ParseExpr
($e, $length, $var_prefix);
525 pidl
"if ($var_prefix$e->{NAME}) {";
527 check_null_pointer
($length);
528 pidl
"NDR_CHECK(ndr_check_array_length(ndr, (void*)&$var_prefix$e->{NAME}, $length));";
534 sub ParseArrayPullPreceding
($$$)
537 my $var_prefix = shift;
538 my $ndr_flags = shift;
540 if (!is_inline_array
($e)) {
541 # non fixed arrays encode the size just before the array
542 pidl
"NDR_CHECK(ndr_pull_array_size(ndr, &$var_prefix$e->{NAME}));";
546 #####################################################################
547 # parse an array - pull side
548 sub ParseArrayPull
($$$)
551 my $var_prefix = shift;
552 my $ndr_flags = shift;
554 my $size = ParseExpr
($e, util
::array_size
($e), $var_prefix);
555 my $alloc_size = $size;
557 # if this is a conformant array then we use that size to allocate, and make sure
558 # we allocate enough to pull the elements
559 if (is_conformant_array
($e) and is_surrounding_array
($e)) {
560 $alloc_size = "ndr_get_array_size(ndr, &$var_prefix$e->{NAME})";
561 check_null_pointer
($size);
562 pidl
"if ($size > $alloc_size) {";
564 pidl
"return ndr_pull_error(ndr, NDR_ERR_CONFORMANT_SIZE, \"Bad conformant size %u should be %u\", $alloc_size, $size);";
567 } elsif (!is_inline_array
($e)) {
568 if ($var_prefix =~ /^r->out/ && $size =~ /^\*r->in/) {
569 my $size2 = substr($size, 1);
570 pidl
"if (ndr->flags & LIBNDR_FLAG_REF_ALLOC) { NDR_ALLOC(ndr, $size2); }";
573 ParseArrayPullPreceding
($e, $var_prefix, $ndr_flags);
575 $alloc_size = "ndr_get_array_size(ndr, &$var_prefix$e->{NAME})";
578 if ((need_alloc
($e) && !is_fixed_array
($e)) ||
579 ($var_prefix eq "r->in." && util
::has_property
($e, "ref"))) {
580 if (!is_inline_array
($e) || $ndr_flags eq "NDR_SCALARS") {
581 pidl
"NDR_ALLOC_N(ndr, $var_prefix$e->{NAME}, $alloc_size);";
585 if (($var_prefix eq "r->out." && util
::has_property
($e, "ref"))) {
586 if (!is_inline_array
($e) || $ndr_flags eq "NDR_SCALARS") {
587 pidl
"if (ndr->flags & LIBNDR_FLAG_REF_ALLOC) {";
589 pidl
"NDR_ALLOC_N(ndr, $var_prefix$e->{NAME}, $alloc_size);";
595 if (my $length = util
::has_property
($e, "length_is")) {
596 pidl
"NDR_CHECK(ndr_pull_array_length(ndr, &$var_prefix$e->{NAME}));";
597 $size = "ndr_get_array_length(ndr, &$var_prefix$e->{NAME})";
600 check_null_pointer
($size);
601 if (is_scalar_type
($e->{TYPE
})) {
602 pidl
"NDR_CHECK(ndr_pull_array_$e->{TYPE}(ndr, $ndr_flags, $var_prefix$e->{NAME}, $size));";
604 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}));";
608 #####################################################################
609 # parse scalars in a structure element
610 sub ParseElementPushScalar
($$$)
613 my($var_prefix) = shift;
614 my($ndr_flags) = shift;
615 my $cprefix = c_push_prefix
($e);
616 my $sub_size = util
::has_property
($e, "subcontext");
620 if (my $value = util
::has_property
($e, "value")) {
621 pidl
"$cprefix$var_prefix$e->{NAME} = $value;";
624 if (util
::has_property
($e, "relative")) {
625 pidl
"NDR_CHECK(ndr_push_relative_ptr1(ndr, $var_prefix$e->{NAME}));";
626 } elsif (is_inline_array
($e)) {
627 ParseArrayPush
($e, "r->", "NDR_SCALARS");
628 } elsif (need_wire_pointer
($e)) {
629 ParseElementPushPtr
($e, $var_prefix, $ndr_flags);
630 } elsif (need_alloc
($e)) {
631 # no scalar component
632 } elsif (my $switch = util
::has_property
($e, "switch_is")) {
633 ParseElementPushSwitch
($e, $var_prefix, $ndr_flags, $switch);
634 } elsif (defined $sub_size) {
635 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}));";
637 pidl
"NDR_CHECK(ndr_push_$e->{TYPE}(ndr, $ndr_flags, $cprefix$var_prefix$e->{NAME}));";
643 #####################################################################
644 # parse a pointer in a struct element or function
645 sub ParseElementPushPtr
($$$)
648 my $var_prefix = shift;
649 my $ndr_flags = shift;
651 pidl
"NDR_CHECK(ndr_push_unique_ptr(ndr, $var_prefix$e->{NAME}));";
655 #####################################################################
656 # print scalars in a structure element
657 sub ParseElementPrintScalar
($$)
660 my($var_prefix) = shift;
661 my $cprefix = c_push_prefix
($e);
663 if (util
::has_property
($e, "noprint")) {
667 if (my $value = util
::has_property
($e, "value")) {
668 pidl
"if (ndr->flags & LIBNDR_PRINT_SET_VALUES) {";
670 pidl
"$cprefix$var_prefix$e->{NAME} = $value;";
675 if (is_fixed_array
($e)) {
676 ParseElementPrintBuffer
($e, $var_prefix);
677 } elsif ($e->{POINTERS
} || util
::array_size
($e)) {
678 pidl
"ndr_print_ptr(ndr, \"$e->{NAME}\", $var_prefix$e->{NAME});";
679 pidl
"ndr->depth++;";
680 ParseElementPrintBuffer
($e, $var_prefix);
681 pidl
"ndr->depth--;";
682 } elsif (my $switch = util
::has_property
($e, "switch_is")) {
683 ParseElementPrintSwitch
($e, $var_prefix, $switch);
685 pidl
"ndr_print_$e->{TYPE}(ndr, \"$e->{NAME}\", $cprefix$var_prefix$e->{NAME});";
689 #####################################################################
690 # parse scalars in a structure element - pull size
691 sub ParseElementPullSwitch
($$$$)
694 my($var_prefix) = shift;
695 my($ndr_flags) = shift;
697 my $switch_var = ParseExpr
($e, $switch, $var_prefix);
699 my $cprefix = c_pull_prefix
($e);
701 my $utype = $typedefs{$e->{TYPE
}};
703 check_null_pointer
($switch_var);
705 if (!defined $utype ||
706 !util
::has_property
($utype, "nodiscriminant")) {
707 my $e2 = find_sibling
($e, $switch);
708 my $type_decl = util
::map_type
($e2->{TYPE
});
709 pidl
"if (($ndr_flags) & NDR_SCALARS) {";
711 if ($typedefs{$e2->{TYPE
}}->{DATA
}->{TYPE
} eq "ENUM") {
712 $type_decl = util
::enum_type_decl
($e2);
713 } elsif ($typedefs{$e2->{TYPE
}}->{DATA
}->{TYPE
} eq "BITMAP") {
714 $type_decl = util
::bitmap_type_decl
($e2);
716 pidl
"$type_decl _level;";
717 pidl
"NDR_CHECK(ndr_pull_$e2->{TYPE}(ndr, NDR_SCALARS, &_level));";
718 if ($switch_var =~ /r->in/) {
719 pidl
"if (!(ndr->flags & LIBNDR_FLAG_REF_ALLOC) && _level != $switch_var) {";
722 pidl
"if (_level != $switch_var) {";
725 pidl
"return ndr_pull_error(ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value %u in $e->{NAME}\", _level);";
727 if ($switch_var =~ /r->/) {
728 pidl
"} else { $switch_var = _level; }";
736 my $sub_size = util
::has_property
($e, "subcontext");
737 if (defined $sub_size) {
738 pidl
"if (($ndr_flags) & NDR_SCALARS) {";
740 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}));";
744 pidl
"NDR_CHECK(ndr_pull_$e->{TYPE}(ndr, $ndr_flags, $switch_var, $cprefix$var_prefix$e->{NAME}));";
750 #####################################################################
751 # push switch element
752 sub ParseElementPushSwitch
($$$$)
755 my($var_prefix) = shift;
756 my($ndr_flags) = shift;
758 my $switch_var = ParseExpr
($e, $switch, $var_prefix);
759 my $cprefix = c_push_prefix
($e);
761 check_null_pointer
($switch_var);
763 my $utype = $typedefs{$e->{TYPE
}};
764 if (!defined $utype ||
765 !util
::has_property
($utype, "nodiscriminant")) {
766 my $e2 = find_sibling
($e, $switch);
767 pidl
"if (($ndr_flags) & NDR_SCALARS) {";
769 pidl
"NDR_CHECK(ndr_push_$e2->{TYPE}(ndr, NDR_SCALARS, $switch_var));";
774 my $sub_size = util
::has_property
($e, "subcontext");
775 if (defined $sub_size) {
776 pidl
"if(($ndr_flags) & NDR_SCALARS) {";
778 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}));";
782 pidl
"NDR_CHECK(ndr_push_$e->{TYPE}(ndr, $ndr_flags, $switch_var, $cprefix$var_prefix$e->{NAME}));";
786 #####################################################################
787 # print scalars in a structure element
788 sub ParseElementPrintSwitch
($$$)
791 my($var_prefix) = shift;
793 my $switch_var = ParseExpr
($e, $switch, $var_prefix);
794 my $cprefix = c_push_prefix
($e);
796 check_null_pointer_void
($switch_var);
798 pidl
"ndr_print_$e->{TYPE}(ndr, \"$e->{NAME}\", $switch_var, $cprefix$var_prefix$e->{NAME});";
802 #####################################################################
803 # parse scalars in a structure element - pull size
804 sub ParseElementPullScalar
($$$)
807 my($var_prefix) = shift;
808 my($ndr_flags) = shift;
809 my $cprefix = c_pull_prefix
($e);
810 my $sub_size = util
::has_property
($e, "subcontext");
814 if (is_inline_array
($e)) {
815 ParseArrayPull
($e, "r->", "NDR_SCALARS");
816 } elsif (need_wire_pointer
($e)) {
817 ParseElementPullPtr
($e, $var_prefix, $ndr_flags);
818 } elsif (need_alloc
($e)) {
819 # no scalar component
820 } elsif (my $switch = util
::has_property
($e, "switch_is")) {
821 ParseElementPullSwitch
($e, $var_prefix, $ndr_flags, $switch);
822 } elsif (defined $sub_size) {
823 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}));";
825 pidl
"NDR_CHECK(ndr_pull_$e->{TYPE}(ndr, $ndr_flags, $cprefix$var_prefix$e->{NAME}));";
827 if (my $range = util
::has_property
($e, "range")) {
828 my ($low, $high) = split(/ /, $range, 2);
829 pidl
"if ($var_prefix$e->{NAME} < $low || $var_prefix$e->{NAME} > $high) {";
830 pidl
"\treturn ndr_pull_error(ndr, NDR_ERR_RANGE, \"value out of range\");";
837 #####################################################################
838 # parse a pointer in a struct element or function
839 sub ParseElementPullPtr
($$$)
842 my($var_prefix) = shift;
843 my($ndr_flags) = shift;
845 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($ndr_flags) = shift;
865 my $cprefix = c_push_prefix
($e);
866 my $sub_size = util
::has_property
($e, "subcontext");
868 if (is_pure_scalar
($e)) {
874 if (need_wire_pointer
($e)) {
875 pidl
"if ($var_prefix$e->{NAME}) {";
877 if (util
::has_property
($e, "relative")) {
878 pidl
"NDR_CHECK(ndr_push_relative_ptr2(ndr, $var_prefix$e->{NAME}));";
882 if (is_inline_array
($e)) {
883 ParseArrayPush
($e, "r->", "NDR_BUFFERS");
884 } elsif (util
::array_size
($e)) {
885 ParseArrayPush
($e, "r->", "NDR_SCALARS|NDR_BUFFERS");
886 } elsif (my $switch = util
::has_property
($e, "switch_is")) {
887 if ($e->{POINTERS
}) {
888 ParseElementPushSwitch
($e, $var_prefix, "NDR_BUFFERS|NDR_SCALARS", $switch);
890 ParseElementPushSwitch
($e, $var_prefix, "NDR_BUFFERS", $switch);
892 } elsif (defined $sub_size) {
893 if ($e->{POINTERS
}) {
894 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}));";
896 } elsif ($e->{POINTERS
}) {
897 pidl
"NDR_CHECK(ndr_push_$e->{TYPE}(ndr, NDR_SCALARS|NDR_BUFFERS, $cprefix$var_prefix$e->{NAME}));";
899 pidl
"NDR_CHECK(ndr_push_$e->{TYPE}(ndr, $ndr_flags, $cprefix$var_prefix$e->{NAME}));";
902 if (need_wire_pointer
($e)) {
910 #####################################################################
911 # print buffers in a structure element
912 sub ParseElementPrintBuffer
($$)
915 my($var_prefix) = shift;
916 my $cprefix = c_push_prefix
($e);
918 if (need_wire_pointer
($e)) {
919 pidl
"if ($var_prefix$e->{NAME}) {";
923 if (util
::array_size
($e)) {
924 ParseArrayPrint
($e, $var_prefix)
925 } elsif (my $switch = util
::has_property
($e, "switch_is")) {
926 ParseElementPrintSwitch
($e, $var_prefix, $switch);
928 pidl
"ndr_print_$e->{TYPE}(ndr, \"$e->{NAME}\", $cprefix$var_prefix$e->{NAME});";
931 if (need_wire_pointer
($e)) {
937 #####################################################################
938 # parse buffers in a structure element - pull side
939 sub ParseElementPullBuffer
($$$)
942 my($var_prefix) = shift;
943 my($ndr_flags) = shift;
944 my $cprefix = c_pull_prefix
($e);
945 my $sub_size = util
::has_property
($e, "subcontext");
947 if (is_pure_scalar
($e)) {
953 if (need_wire_pointer
($e)) {
954 pidl
"if ($var_prefix$e->{NAME}) {";
956 if (util
::has_property
($e, "relative")) {
957 pidl
"struct ndr_pull_save _relative_save;";
958 pidl
"ndr_pull_save(ndr, &_relative_save);";
959 pidl
"NDR_CHECK(ndr_pull_relative_ptr2(ndr, $var_prefix$e->{NAME}));";
963 if (is_inline_array
($e)) {
964 ParseArrayPull
($e, "r->", "NDR_BUFFERS");
965 } elsif (util
::array_size
($e)) {
966 ParseArrayPull
($e, "r->", "NDR_SCALARS|NDR_BUFFERS");
967 } elsif (my $switch = util
::has_property
($e, "switch_is")) {
968 if ($e->{POINTERS
}) {
969 ParseElementPullSwitch
($e, $var_prefix, "NDR_SCALARS|NDR_BUFFERS", $switch);
971 ParseElementPullSwitch
($e, $var_prefix, "NDR_BUFFERS", $switch);
973 } elsif (defined $sub_size) {
974 if ($e->{POINTERS
}) {
975 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}));";
977 } elsif ($e->{POINTERS
}) {
978 pidl
"NDR_CHECK(ndr_pull_$e->{TYPE}(ndr, NDR_SCALARS|NDR_BUFFERS, $cprefix$var_prefix$e->{NAME}));";
980 pidl
"NDR_CHECK(ndr_pull_$e->{TYPE}(ndr, $ndr_flags, $cprefix$var_prefix$e->{NAME}));";
983 if (need_wire_pointer
($e)) {
984 if (util
::has_property
($e, "relative")) {
985 pidl
"ndr_pull_restore(ndr, &_relative_save);";
994 #####################################################################
996 sub ParseStructPush
($)
1000 return unless defined($struct->{ELEMENTS
});
1002 start_flags
($struct);
1004 # see if the structure contains a conformant array. If it
1005 # does, then it must be the last element of the structure, and
1006 # we need to push the conformant length early, as it fits on
1007 # the wire before the structure (and even before the structure
1009 my $e = $struct->{ELEMENTS
}[-1];
1010 if (is_conformant_array
($e) and is_surrounding_array
($e)) {
1011 ParseArrayPushPreceding
($e, "r->", "NDR_SCALARS");
1014 if (defined $e->{TYPE
} && $e->{TYPE
} eq "string"
1015 && util
::property_matches
($e, "flag", ".*LIBNDR_FLAG_STR_CONFORMANT.*")) {
1016 pidl
"NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_string_array_size(ndr, r->$e->{NAME})));";
1019 pidl
"if (!(ndr_flags & NDR_SCALARS)) goto buffers;";
1021 pidl
"NDR_CHECK(ndr_push_struct_start(ndr));";
1023 my $align = find_largest_alignment
($struct);
1024 pidl
"NDR_CHECK(ndr_push_align(ndr, $align));";
1026 foreach my $e (@
{$struct->{ELEMENTS
}}) {
1027 ParseElementPushScalar
($e, "r->", "NDR_SCALARS");
1031 pidl
"if (!(ndr_flags & NDR_BUFFERS)) goto done;";
1032 foreach my $e (@
{$struct->{ELEMENTS
}}) {
1033 ParseElementPushBuffer
($e, "r->", "NDR_BUFFERS");
1036 pidl
"ndr_push_struct_end(ndr);";
1043 #####################################################################
1044 # generate a push function for an enum
1045 sub ParseEnumPush
($)
1048 my($type_fn) = util
::enum_type_fn
($enum);
1052 pidl
"NDR_CHECK(ndr_push_$type_fn(ndr, NDR_SCALARS, r));";
1057 #####################################################################
1058 # generate a pull function for an enum
1059 sub ParseEnumPull
($)
1062 my($type_fn) = util
::enum_type_fn
($enum);
1063 my($type_v_decl) = util
::map_type
(util
::enum_type_fn
($enum));
1065 pidl
"$type_v_decl v;";
1067 pidl
"NDR_CHECK(ndr_pull_$type_fn(ndr, NDR_SCALARS, &v));";
1073 #####################################################################
1074 # generate a print function for an enum
1075 sub ParseEnumPrint
($)
1079 pidl
"const char *val = NULL;";
1084 pidl
"switch (r) {";
1086 my $els = \@
{$enum->{ELEMENTS
}};
1087 foreach my $i (0 .. $#{$els}) {
1088 my $e = ${$els}[$i];
1090 if ($e =~ /^(.*)=/) {
1093 pidl
"case $e: val = \"$e\"; break;";
1099 pidl
"ndr_print_enum(ndr, name, \"$enum->{TYPE}\", val, r);";
1107 return "struct ndr_push *ndr, int ndr_flags, enum $e->{NAME} r";
1110 sub ArgsEnumPrint
($)
1113 return "struct ndr_print *ndr, const char *name, enum $e->{NAME} r";
1119 return "struct ndr_pull *ndr, int ndr_flags, enum $e->{NAME} *r";
1122 $typefamily{ENUM
} = {
1123 PUSH_FN_BODY
=> \
&ParseEnumPush
,
1124 PUSH_FN_ARGS
=> \
&ArgsEnumPush
,
1125 PULL_FN_BODY
=> \
&ParseEnumPull
,
1126 PULL_FN_ARGS
=> \
&ArgsEnumPull
,
1127 PRINT_FN_BODY
=> \
&ParseEnumPrint
,
1128 PRINT_FN_ARGS
=> \
&ArgsEnumPrint
,
1129 ALIGN
=> sub { return align_type
(util
::enum_type_fn
(shift)); }
1132 #####################################################################
1133 # generate a push function for a bitmap
1134 sub ParseBitmapPush
($)
1136 my($bitmap) = shift;
1137 my($type_fn) = util
::bitmap_type_fn
($bitmap);
1139 start_flags
($bitmap);
1141 pidl
"NDR_CHECK(ndr_push_$type_fn(ndr, NDR_SCALARS, r));";
1146 #####################################################################
1147 # generate a pull function for an bitmap
1148 sub ParseBitmapPull
($)
1150 my($bitmap) = shift;
1151 my($type_fn) = util
::bitmap_type_fn
($bitmap);
1152 my($type_decl) = util
::bitmap_type_decl
($bitmap);
1154 pidl
"$type_decl v;";
1155 start_flags
($bitmap);
1156 pidl
"NDR_CHECK(ndr_pull_$type_fn(ndr, NDR_SCALARS, &v));";
1162 #####################################################################
1163 # generate a print function for an bitmap
1164 sub ParseBitmapPrintElement
($$)
1167 my($bitmap) = shift;
1168 my($type_decl) = util
::bitmap_type_decl
($bitmap);
1169 my($type_fn) = util
::bitmap_type_fn
($bitmap);
1170 my($name) = $bitmap->{PARENT
}->{NAME
};
1173 if ($e =~ /^(\w+) .*$/) {
1176 die "Bitmap: \"$name\" invalid Flag: \"$e\"";
1179 pidl
"ndr_print_bitmap_flag(ndr, sizeof($type_decl), \"$flag\", $flag, r);";
1182 #####################################################################
1183 # generate a print function for an bitmap
1184 sub ParseBitmapPrint
($)
1186 my($bitmap) = shift;
1187 my($type_decl) = util
::bitmap_type_decl
($bitmap);
1188 my($type_fn) = util
::bitmap_type_fn
($bitmap);
1190 start_flags
($bitmap);
1192 pidl
"ndr_print_$type_fn(ndr, name, r);";
1194 pidl
"ndr->depth++;";
1195 foreach my $e (@
{$bitmap->{ELEMENTS
}}) {
1196 ParseBitmapPrintElement
($e, $bitmap);
1198 pidl
"ndr->depth--;";
1203 sub ArgsBitmapPush
($)
1206 my $type_decl = util
::bitmap_type_decl
($e->{DATA
});
1207 return "struct ndr_push *ndr, int ndr_flags, $type_decl r";
1210 sub ArgsBitmapPrint
($)
1213 my $type_decl = util
::bitmap_type_decl
($e->{DATA
});
1214 return "struct ndr_print *ndr, const char *name, $type_decl r";
1217 sub ArgsBitmapPull
($)
1220 my $type_decl = util
::bitmap_type_decl
($e->{DATA
});
1221 return "struct ndr_pull *ndr, int ndr_flags, $type_decl *r";
1224 $typefamily{BITMAP
} = {
1225 PUSH_FN_BODY
=> \
&ParseBitmapPush
,
1226 PUSH_FN_ARGS
=> \
&ArgsBitmapPush
,
1227 PULL_FN_BODY
=> \
&ParseBitmapPull
,
1228 PULL_FN_ARGS
=> \
&ArgsBitmapPull
,
1229 PRINT_FN_BODY
=> \
&ParseBitmapPrint
,
1230 PRINT_FN_ARGS
=> \
&ArgsBitmapPrint
,
1231 ALIGN
=> sub { return align_type
(util
::bitmap_type_fn
(shift)); }
1234 #####################################################################
1235 # generate a struct print function
1236 sub ParseStructPrint
($)
1238 my($struct) = shift;
1239 my($name) = $struct->{PARENT
}->{NAME
};
1241 return unless defined $struct->{ELEMENTS
};
1243 pidl
"ndr_print_struct(ndr, name, \"$name\");";
1245 start_flags
($struct);
1247 pidl
"ndr->depth++;";
1248 foreach my $e (@
{$struct->{ELEMENTS
}}) {
1249 ParseElementPrintScalar
($e, "r->");
1251 pidl
"ndr->depth--;";
1256 #####################################################################
1257 # parse a struct - pull side
1258 sub ParseStructPull
($)
1260 my($struct) = shift;
1263 return unless defined $struct->{ELEMENTS
};
1265 # see if the structure contains a conformant array. If it
1266 # does, then it must be the last element of the structure, and
1267 # we need to pull the conformant length early, as it fits on
1268 # the wire before the structure (and even before the structure
1270 my $e = $struct->{ELEMENTS
}[-1];
1271 if (is_conformant_array
($e) and is_surrounding_array
($e)) {
1275 if (defined $e->{TYPE
} && $e->{TYPE
} eq "string"
1276 && util
::property_matches
($e, "flag", ".*LIBNDR_FLAG_STR_CONFORMANT.*")) {
1280 # declare any internal pointers we need
1281 foreach my $e (@
{$struct->{ELEMENTS
}}) {
1282 if (need_wire_pointer
($e)) {
1283 pidl
"uint32_t _ptr_$e->{NAME};";
1287 start_flags
($struct);
1289 pidl
"if (!(ndr_flags & NDR_SCALARS)) goto buffers;";
1291 pidl
"NDR_CHECK(ndr_pull_struct_start(ndr));";
1293 if (defined $conform_e) {
1294 ParseArrayPullPreceding
($conform_e, "r->", "NDR_SCALARS");
1297 my $align = find_largest_alignment
($struct);
1298 pidl
"NDR_CHECK(ndr_pull_align(ndr, $align));";
1300 foreach my $e (@
{$struct->{ELEMENTS
}}) {
1301 ParseElementPullScalar
($e, "r->", "NDR_SCALARS");
1305 pidl
"if (!(ndr_flags & NDR_BUFFERS)) goto done;";
1306 foreach my $e (@
{$struct->{ELEMENTS
}}) {
1307 ParseElementPullBuffer
($e, "r->", "NDR_BUFFERS");
1310 foreach my $e (@
{$struct->{ELEMENTS
}}) {
1311 CheckArraySizes
($e, "r->");
1314 pidl
"ndr_pull_struct_end(ndr);";
1321 #####################################################################
1322 # calculate size of ndr struct
1323 sub ParseStructNdrSize
($)
1326 my $static = fn_prefix
($t);
1329 pidl
"size_t ndr_size_$t->{NAME}(const struct $t->{NAME} *r, int flags)";
1332 if (my $flags = util
::has_property
($t, "flag")) {
1333 pidl
"flags |= $flags;";
1335 pidl
"return ndr_size_struct(r, flags, (ndr_push_flags_fn_t)ndr_push_$t->{NAME});";
1341 sub ArgsStructPush
($)
1344 return "struct ndr_push *ndr, int ndr_flags, struct $e->{NAME} *r";
1347 sub ArgsStructPrint
($)
1350 return "struct ndr_print *ndr, const char *name, struct $e->{NAME} *r";
1353 sub ArgsStructPull
($)
1356 return "struct ndr_pull *ndr, int ndr_flags, struct $e->{NAME} *r";
1359 $typefamily{STRUCT
} = {
1360 PUSH_FN_BODY
=> \
&ParseStructPush
,
1361 PUSH_FN_ARGS
=> \
&ArgsStructPush
,
1362 PULL_FN_BODY
=> \
&ParseStructPull
,
1363 PULL_FN_ARGS
=> \
&ArgsStructPull
,
1364 PRINT_FN_BODY
=> \
&ParseStructPrint
,
1365 PRINT_FN_ARGS
=> \
&ArgsStructPrint
,
1366 SIZE_FN
=> \
&ParseStructNdrSize
,
1367 ALIGN
=> \
&find_largest_alignment
1370 #####################################################################
1371 # calculate size of ndr struct
1372 sub ParseUnionNdrSize
($)
1375 my $static = fn_prefix
($t);
1378 pidl
"size_t ndr_size_$t->{NAME}(const union $t->{NAME} *r, int level, int flags)";
1381 if (my $flags = util
::has_property
($t, "flag")) {
1382 pidl
"flags |= $flags;";
1384 pidl
"return ndr_size_union(r, flags, level, (ndr_push_union_fn_t)ndr_push_$t->{NAME});";
1390 #####################################################################
1391 # parse a union - push side
1392 sub ParseUnionPush
($)
1395 my $have_default = 0;
1399 pidl
"if (!(ndr_flags & NDR_SCALARS)) goto buffers;";
1401 pidl
"NDR_CHECK(ndr_push_struct_start(ndr));";
1403 # my $align = union_alignment($e);
1404 # pidl "NDR_CHECK(ndr_push_align(ndr, $align));";
1406 pidl
"switch (level) {";
1408 foreach my $el (@
{$e->{ELEMENTS
}}) {
1409 if (util
::has_property
($el, "default")) {
1413 pidl
"case $el->{PROPERTIES}->{case}:";
1416 if ($el->{TYPE
} ne "EMPTY") {
1418 ParseElementPushScalar
($el, "r->", "NDR_SCALARS");
1424 if (! $have_default) {
1426 pidl
"\treturn ndr_push_error(ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value \%u\", level);";
1431 pidl
"if (!(ndr_flags & NDR_BUFFERS)) goto done;";
1432 pidl
"switch (level) {";
1434 foreach my $el (@
{$e->{ELEMENTS
}}) {
1435 if (util
::has_property
($el, "default")) {
1438 pidl
"case $el->{PROPERTIES}->{case}:";
1440 if ($el->{TYPE
} ne "EMPTY") {
1442 ParseElementPushBuffer
($el, "r->", "NDR_BUFFERS");
1448 if (! $have_default) {
1450 pidl
"\treturn ndr_push_error(ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value \%u\", level);";
1454 pidl
"ndr_push_struct_end(ndr);";
1459 #####################################################################
1461 sub ParseUnionPrint
($)
1464 my $have_default = 0;
1465 my($name) = $e->{PARENT
}->{NAME
};
1467 pidl
"ndr_print_union(ndr, name, level, \"$name\");";
1470 pidl
"switch (level) {";
1472 foreach my $el (@
{$e->{ELEMENTS
}}) {
1473 if (util
::has_property
($el, "default")) {
1477 pidl
"case $el->{PROPERTIES}->{case}:";
1479 if ($el->{TYPE
} ne "EMPTY") {
1481 ParseElementPrintScalar
($el, "r->");
1487 if (! $have_default) {
1489 pidl
"\tndr_print_bad_level(ndr, name, level);";
1497 #####################################################################
1498 # parse a union - pull side
1499 sub ParseUnionPull
($)
1502 my $have_default = 0;
1506 pidl
"if (!(ndr_flags & NDR_SCALARS)) goto buffers;";
1508 pidl
"NDR_CHECK(ndr_pull_struct_start(ndr));";
1510 # my $align = union_alignment($e);
1511 # pidl "\tNDR_CHECK(ndr_pull_align(ndr, $align));\n";
1513 pidl
"switch (level) {";
1515 foreach my $el (@
{$e->{ELEMENTS
}}) {
1516 if (util
::has_property
($el, "default")) {
1520 pidl
"case $el->{PROPERTIES}->{case}: {";
1522 if ($el->{TYPE
} ne "EMPTY") {
1524 if ($el->{POINTERS
}) {
1525 pidl
"uint32_t _ptr_$el->{NAME};";
1527 ParseElementPullScalar
($el, "r->", "NDR_SCALARS");
1533 if (! $have_default) {
1535 pidl
"\treturn ndr_pull_error(ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value \%u\", level);";
1540 pidl
"if (!(ndr_flags & NDR_BUFFERS)) goto done;";
1541 pidl
"switch (level) {";
1543 foreach my $el (@
{$e->{ELEMENTS
}}) {
1544 if (util
::has_property
($el, "default")) {
1547 pidl
"case $el->{PROPERTIES}->{case}:";
1549 if ($el->{TYPE
} ne "EMPTY") {
1551 ParseElementPullBuffer
($el, "r->", "NDR_BUFFERS");
1557 if (! $have_default) {
1559 pidl
"\treturn ndr_pull_error(ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value \%u\", level);";
1563 pidl
"ndr_pull_struct_end(ndr);";
1568 sub ArgsUnionPush
($)
1571 return "struct ndr_push *ndr, int ndr_flags, int level, union $e->{NAME} *r";
1574 sub ArgsUnionPrint
($)
1577 return "struct ndr_print *ndr, const char *name, int level, union $e->{NAME} *r";
1580 sub ArgsUnionPull
($)
1583 return "struct ndr_pull *ndr, int ndr_flags, int level, union $e->{NAME} *r";
1586 $typefamily{UNION
} = {
1587 PUSH_FN_BODY
=> \
&ParseUnionPush
,
1588 PUSH_FN_ARGS
=> \
&ArgsUnionPush
,
1589 PULL_FN_BODY
=> \
&ParseUnionPull
,
1590 PULL_FN_ARGS
=> \
&ArgsUnionPull
,
1591 PRINT_FN_BODY
=> \
&ParseUnionPrint
,
1592 PRINT_FN_ARGS
=> \
&ArgsUnionPrint
,
1593 SIZE_FN
=> \
&ParseUnionNdrSize
,
1594 ALIGN
=> \
&find_largest_alignment
1597 #####################################################################
1598 # parse a typedef - push side
1599 sub ParseTypedefPush
($)
1602 my $static = fn_prefix
($e);
1604 return unless needed
::is_needed
("push_$e->{NAME}");
1606 my $args = $typefamily{$e->{DATA
}->{TYPE
}}->{PUSH_FN_ARGS
}->($e);
1607 pidl
$static . "NTSTATUS ndr_push_$e->{NAME}($args)";
1611 $typefamily{$e->{DATA
}->{TYPE
}}->{PUSH_FN_BODY
}->($e->{DATA
});
1612 pidl
"return NT_STATUS_OK;";
1619 #####################################################################
1620 # parse a typedef - pull side
1621 sub ParseTypedefPull
($)
1624 my $static = fn_prefix
($e);
1626 return unless needed
::is_needed
("pull_$e->{NAME}");
1628 my $args = $typefamily{$e->{DATA
}->{TYPE
}}->{PULL_FN_ARGS
}->($e);
1630 pidl
$static . "NTSTATUS ndr_pull_$e->{NAME}($args)";
1634 $typefamily{$e->{DATA
}->{TYPE
}}->{PULL_FN_BODY
}->($e->{DATA
});
1635 pidl
"return NT_STATUS_OK;";
1641 #####################################################################
1642 # parse a typedef - print side
1643 sub ParseTypedefPrint
($)
1647 my $args = $typefamily{$e->{DATA
}->{TYPE
}}->{PRINT_FN_ARGS
}->($e);
1649 pidl
"void ndr_print_$e->{NAME}($args)";
1652 $typefamily{$e->{DATA
}->{TYPE
}}->{PRINT_FN_BODY
}->($e->{DATA
});
1657 #####################################################################
1658 ## calculate the size of a structure
1659 sub ParseTypedefNdrSize
($)
1663 return unless needed
::is_needed
("ndr_size_$t->{NAME}");
1665 $typefamily{$t->{DATA
}->{TYPE
}}->{SIZE_FN
}->($t);
1668 #####################################################################
1669 # parse a function - print side
1670 sub ParseFunctionPrint
($)
1674 pidl
"void ndr_print_$fn->{NAME}(struct ndr_print *ndr, const char *name, int flags, struct $fn->{NAME} *r)";
1677 pidl
"ndr_print_struct(ndr, name, \"$fn->{NAME}\");";
1678 pidl
"ndr->depth++;";
1680 pidl
"if (flags & NDR_SET_VALUES) {";
1681 pidl
"\tndr->flags |= LIBNDR_PRINT_SET_VALUES;";
1684 pidl
"if (flags & NDR_IN) {";
1686 pidl
"ndr_print_struct(ndr, \"in\", \"$fn->{NAME}\");";
1687 pidl
"ndr->depth++;";
1689 foreach my $e (@
{$fn->{ELEMENTS
}}) {
1690 if (util
::has_property
($e, "in")) {
1691 ParseElementPrintScalar
($e, "r->in.");
1694 pidl
"ndr->depth--;";
1698 pidl
"if (flags & NDR_OUT) {";
1700 pidl
"ndr_print_struct(ndr, \"out\", \"$fn->{NAME}\");";
1701 pidl
"ndr->depth++;";
1702 foreach my $e (@
{$fn->{ELEMENTS
}}) {
1703 if (util
::has_property
($e, "out")) {
1704 ParseElementPrintScalar
($e, "r->out.");
1707 if ($fn->{RETURN_TYPE
} && $fn->{RETURN_TYPE
} ne "void") {
1709 $cprefix = "" if (is_scalar_type
($fn->{RETURN_TYPE
})) ; # FIXME: Should really use util::c_push_prefix here
1710 pidl
"ndr_print_$fn->{RETURN_TYPE}(ndr, \"result\", $cprefix"."r->out.result);";
1712 pidl
"ndr->depth--;";
1716 pidl
"ndr->depth--;";
1722 #####################################################################
1723 # parse a function element
1724 sub ParseFunctionElementPush
($$)
1729 if (util
::array_size
($e)) {
1730 if (need_wire_pointer
($e)) {
1731 pidl
"NDR_CHECK(ndr_push_unique_ptr(ndr, r->$inout.$e->{NAME}));";
1732 pidl
"if (r->$inout.$e->{NAME}) {";
1734 ParseArrayPush
($e, "r->$inout.", "NDR_SCALARS|NDR_BUFFERS");
1738 ParseArrayPush
($e, "r->$inout.", "NDR_SCALARS|NDR_BUFFERS");
1741 ParseElementPushScalar
($e, "r->$inout.", "NDR_SCALARS|NDR_BUFFERS");
1743 if ($e->{POINTERS
}) {
1744 ParseElementPushBuffer
($e, "r->$inout.", "NDR_SCALARS|NDR_BUFFERS");
1749 #####################################################################
1751 sub ParseFunctionPush
($)
1754 my $static = fn_prefix
($fn);
1756 pidl
$static . "NTSTATUS ndr_push_$fn->{NAME}(struct ndr_push *ndr, int flags, struct $fn->{NAME} *r)";
1760 pidl
"if (!(flags & NDR_IN)) goto ndr_out;";
1763 foreach my $e (@
{$fn->{ELEMENTS
}}) {
1764 if (util
::has_property
($e, "in")) {
1765 ParseFunctionElementPush
($e, "in");
1770 pidl
"if (!(flags & NDR_OUT)) goto done;";
1773 foreach my $e (@
{$fn->{ELEMENTS
}}) {
1774 if (util
::has_property
($e, "out")) {
1775 ParseFunctionElementPush
($e, "out");
1779 if ($fn->{RETURN_TYPE
} && $fn->{RETURN_TYPE
} ne "void") {
1780 pidl
"NDR_CHECK(ndr_push_$fn->{RETURN_TYPE}(ndr, NDR_SCALARS, r->out.result));";
1784 pidl
"return NT_STATUS_OK;";
1790 #####################################################################
1791 # parse a function element
1792 sub ParseFunctionElementPull
($$)
1797 if (util
::array_size
($e)) {
1798 if (need_wire_pointer
($e)) {
1799 pidl
"NDR_CHECK(ndr_pull_unique_ptr(ndr, &_ptr_$e->{NAME}));";
1800 pidl
"r->$inout.$e->{NAME} = NULL;";
1801 pidl
"if (_ptr_$e->{NAME}) {";
1803 } elsif ($inout eq "out" && util
::has_property
($e, "ref")) {
1804 pidl
"if (r->$inout.$e->{NAME}) {";
1810 ParseArrayPull
($e, "r->$inout.", "NDR_SCALARS|NDR_BUFFERS");
1814 if ($inout eq "out" && util
::has_property
($e, "ref")) {
1815 pidl
"if (ndr->flags & LIBNDR_FLAG_REF_ALLOC) {";
1816 pidl
"\tNDR_ALLOC(ndr, r->out.$e->{NAME});";
1819 if ($inout eq "in" && util
::has_property
($e, "ref")) {
1820 pidl
"NDR_ALLOC(ndr, r->in.$e->{NAME});";
1823 ParseElementPullScalar
($e, "r->$inout.", "NDR_SCALARS|NDR_BUFFERS");
1824 if ($e->{POINTERS
}) {
1825 ParseElementPullBuffer
($e, "r->$inout.", "NDR_SCALARS|NDR_BUFFERS");
1830 ############################################################
1831 # allocate ref variables
1832 sub AllocateRefVars
($)
1835 my $asize = util
::array_size
($e);
1837 # note that if the variable is also an "in"
1838 # variable then we copy the initial value from
1841 if (!defined $asize) {
1842 # its a simple variable
1843 pidl
"NDR_ALLOC(ndr, r->out.$e->{NAME});";
1844 if (util
::has_property
($e, "in")) {
1845 pidl
"*r->out.$e->{NAME} = *r->in.$e->{NAME};";
1847 pidl
"ZERO_STRUCTP(r->out.$e->{NAME});";
1853 my $size = ParseExpr
($e, $asize, "r->out.");
1854 check_null_pointer
($size);
1855 pidl
"NDR_ALLOC_N(ndr, r->out.$e->{NAME}, $size);";
1856 if (util
::has_property
($e, "in")) {
1857 pidl
"memcpy(r->out.$e->{NAME},r->in.$e->{NAME},$size * sizeof(*r->in.$e->{NAME}));";
1859 pidl
"memset(r->out.$e->{NAME}, 0, $size * sizeof(*r->out.$e->{NAME}));";
1863 #####################################################################
1865 sub ParseFunctionPull
($)
1868 my $static = fn_prefix
($fn);
1870 # pull function args
1871 pidl
$static . "NTSTATUS ndr_pull_$fn->{NAME}(struct ndr_pull *ndr, int flags, struct $fn->{NAME} *r)";
1875 # declare any internal pointers we need
1876 foreach my $e (@
{$fn->{ELEMENTS
}}) {
1877 if (need_wire_pointer
($e)) {
1878 pidl
"uint32_t _ptr_$e->{NAME};";
1882 pidl
"if (!(flags & NDR_IN)) goto ndr_out;";
1885 # auto-init the out section of a structure. I originally argued that
1886 # this was a bad idea as it hides bugs, but coping correctly
1887 # with initialisation and not wiping ref vars is turning
1888 # out to be too tricky (tridge)
1889 foreach my $e (@
{$fn->{ELEMENTS
}}) {
1890 if (util
::has_property
($e, "out")) {
1891 pidl
"ZERO_STRUCT(r->out);";
1897 foreach my $e (@
{$fn->{ELEMENTS
}}) {
1898 if (util
::has_property
($e, "in")) {
1899 ParseFunctionElementPull
($e, "in");
1901 # we need to allocate any reference output variables, so that
1902 # a dcerpc backend can be sure they are non-null
1903 if (util
::has_property
($e, "out") && util
::has_property
($e, "ref")) {
1904 AllocateRefVars
($e);
1908 foreach my $e (@
{$fn->{ELEMENTS
}}) {
1909 if (util
::has_property
($e, "in")) {
1910 CheckArraySizes
($e, "r->in.");
1915 pidl
"if (!(flags & NDR_OUT)) goto done;";
1918 foreach my $e (@
{$fn->{ELEMENTS
}}) {
1919 if (util
::has_property
($e, "out")) {
1920 ParseFunctionElementPull
($e, "out");
1924 foreach my $e (@
{$fn->{ELEMENTS
}}) {
1925 if (util
::has_property
($e, "out")) {
1926 CheckArraySizes
($e, "r->out.");
1930 if ($fn->{RETURN_TYPE
} && $fn->{RETURN_TYPE
} ne "void") {
1931 pidl
"NDR_CHECK(ndr_pull_$fn->{RETURN_TYPE}(ndr, NDR_SCALARS, &r->out.result));";
1936 pidl
"return NT_STATUS_OK;";
1942 #####################################################################
1943 # produce a function call table
1944 sub FunctionTable
($)
1946 my($interface) = shift;
1947 my($data) = $interface->{INHERITED_DATA
};
1949 my $uname = uc $interface->{NAME
};
1951 foreach my $d (@
{$data}) {
1952 if ($d->{TYPE
} eq "FUNCTION") { $count++; }
1955 return if ($count == 0);
1957 pidl
"static const struct dcerpc_interface_call $interface->{NAME}\_calls[] = {";
1958 foreach my $d (@
{$data}) {
1959 if ($d->{TYPE
} eq "FUNCTION") {
1961 pidl
"\t\t\"$d->{NAME}\",";
1962 pidl
"\t\tsizeof(struct $d->{NAME}),";
1963 pidl
"\t\t(ndr_push_flags_fn_t) ndr_push_$d->{NAME},";
1964 pidl
"\t\t(ndr_pull_flags_fn_t) ndr_pull_$d->{NAME},";
1965 pidl
"\t\t(ndr_print_function_t) ndr_print_$d->{NAME}";
1969 pidl
"\t{ NULL, 0, NULL, NULL, NULL }";
1973 # If no endpoint is set, default to the interface name as a named pipe
1974 if (! defined $interface->{PROPERTIES
}->{endpoint
}) {
1975 $interface->{PROPERTIES
}->{endpoint
} = "\"ncacn_np:[\\\\pipe\\\\" . $interface->{NAME
} . "]\"";
1978 my @e = split / /, $interface->{PROPERTIES
}->{endpoint
};
1979 my $endpoint_count = $#e + 1;
1981 pidl
"static const char * const $interface->{NAME}\_endpoint_strings[] = {";
1982 foreach my $ep (@e) {
1988 pidl
"static const struct dcerpc_endpoint_list $interface->{NAME}\_endpoints = {";
1989 pidl
"\t$endpoint_count, $interface->{NAME}\_endpoint_strings";
1993 pidl
"\nconst struct dcerpc_interface_table dcerpc_table_$interface->{NAME} = {";
1994 pidl
"\t\"$interface->{NAME}\",";
1995 pidl
"\tDCERPC_$uname\_UUID,";
1996 pidl
"\tDCERPC_$uname\_VERSION,";
1997 pidl
"\tDCERPC_$uname\_HELPSTRING,";
1999 pidl
"\t$interface->{NAME}\_calls,";
2000 pidl
"\t&$interface->{NAME}\_endpoints";
2004 pidl
"static NTSTATUS dcerpc_ndr_$interface->{NAME}_init(void)";
2006 pidl
"\treturn librpc_register_interface(&dcerpc_table_$interface->{NAME});";
2011 #####################################################################
2012 # parse the interface definitions
2013 sub ParseInterface
($)
2015 my($interface) = shift;
2016 my($data) = $interface->{DATA
};
2019 foreach my $d (@
{$data}) {
2020 ($d->{TYPE
} eq "TYPEDEF") &&
2021 ParseTypedefPush
($d);
2022 ($d->{TYPE
} eq "FUNCTION") &&
2023 ParseFunctionPush
($d);
2027 foreach my $d (@
{$data}) {
2028 ($d->{TYPE
} eq "TYPEDEF") &&
2029 ParseTypedefPull
($d);
2030 ($d->{TYPE
} eq "FUNCTION") &&
2031 ParseFunctionPull
($d);
2035 foreach my $d (@
{$data}) {
2036 if ($d->{TYPE
} eq "TYPEDEF" &&
2037 !util
::has_property
($d, "noprint")) {
2038 ParseTypedefPrint
($d);
2040 if ($d->{TYPE
} eq "FUNCTION" &&
2041 !util
::has_property
($d, "noprint")) {
2042 ParseFunctionPrint
($d);
2047 foreach my $d (@
{$data}) {
2048 ($d->{TYPE
} eq "TYPEDEF") &&
2049 ParseTypedefNdrSize
($d);
2052 FunctionTable
($interface);
2055 sub RegistrationFunction
($$)
2058 my $filename = shift;
2060 $filename =~ /.*\/ndr_
(.*).c
/;
2062 pidl
"NTSTATUS dcerpc_$basename\_init(void)";
2065 pidl
"NTSTATUS status = NT_STATUS_OK;";
2066 foreach my $interface (@
{$idl}) {
2067 next if $interface->{TYPE
} ne "INTERFACE";
2069 my $data = $interface->{INHERITED_DATA
};
2071 foreach my $d (@
{$data}) {
2072 if ($d->{TYPE
} eq "FUNCTION") { $count++; }
2075 next if ($count == 0);
2077 pidl
"status = dcerpc_ndr_$interface->{NAME}_init();";
2078 pidl
"if (NT_STATUS_IS_ERR(status)) {";
2079 pidl
"\treturn status;";
2083 pidl
"return status;";
2089 sub CheckPointerTypes
($$)
2092 my $default = shift;
2094 foreach my $e (@
{$s->{ELEMENTS
}}) {
2095 if ($e->{POINTERS
}) {
2096 if (not defined(pointer_type
($e))) {
2097 $e->{PROPERTIES
}->{$default} = 1;
2100 if (pointer_type
($e) eq "ptr") {
2101 print "Warning: ptr is not supported by pidl yet\n";
2107 sub LoadInterface
($)
2111 if (not util
::has_property
($x, "pointer_default")) {
2112 # MIDL defaults to "ptr" in DCE compatible mode (/osf)
2113 # and "unique" in Microsoft Extensions mode (default)
2114 $x->{PROPERTIES
}->{pointer_default
} = "unique";
2117 foreach my $d (@
{$x->{DATA
}}) {
2118 if (($d->{TYPE
} eq "DECLARE") or ($d->{TYPE
} eq "TYPEDEF")) {
2119 $typedefs{$d->{NAME
}} = $d;
2120 if ($d->{DATA
}->{TYPE
} eq "STRUCT" or $d->{DATA
}->{TYPE
} eq "UNION") {
2121 CheckPointerTypes
($d->{DATA
}, $x->{PROPERTIES
}->{pointer_default
});
2124 if (defined($d->{PROPERTIES
}) && !defined($d->{DATA
}->{PROPERTIES
})) {
2125 $d->{DATA
}->{PROPERTIES
} = $d->{PROPERTIES
};
2128 if ($d->{TYPE
} eq "FUNCTION") {
2129 CheckPointerTypes
($d,
2130 $x->{PROPERTIES
}->{pointer_default
} # MIDL defaults to "ref"
2136 # Add ORPC specific bits to an interface.
2137 sub InterfaceORPC
($)
2140 # Add [in] ORPCTHIS *this, [out] ORPCTHAT *that
2141 # for 'object' interfaces
2142 if (util
::has_property
($x, "object")) {
2143 foreach my $e (@
{$x->{DATA
}}) {
2144 if($e->{TYPE
} eq "FUNCTION") {
2145 $e->{PROPERTIES
}->{object
} = 1;
2146 unshift(@
{$e->{ELEMENTS
}},
2147 { 'NAME' => 'ORPCthis',
2149 'PROPERTIES' => { 'in' => '1' },
2150 'TYPE' => 'ORPCTHIS'
2152 unshift(@
{$e->{ELEMENTS
}},
2153 { 'NAME' => 'ORPCthat',
2155 'PROPERTIES' => { 'out' => '1' },
2156 'TYPE' => 'ORPCTHAT'
2167 foreach my $x (@
{$idl}) {
2172 #####################################################################
2173 # parse a parsed IDL structure back into an IDL file
2177 my($filename) = shift;
2178 my $h_filename = $filename;
2183 if ($h_filename =~ /(.*)\.c/) {
2184 $h_filename = "$1.h";
2187 pidl
"/* parser auto-generated by pidl */";
2189 pidl
"#include \"includes.h\"";
2190 pidl
"#include \"$h_filename\"";
2193 foreach my $x (@
{$idl}) {
2194 if ($x->{TYPE
} eq "INTERFACE") {
2195 needed
::BuildNeeded
($x);
2200 RegistrationFunction
($idl, $filename);
2205 RegisterPrimitives
();