sub is_varying_array($)
{
my $e = shift;
- return 1 if (util::has_property($e, "length_is"));
- return 0;
+ return util::has_property($e, "length_is");
}
# return 1 if this is a surrounding array (sometimes
sub need_buffers_section($)
{
my $e = shift;
- if ((is_scalar_type($e->{TYPE}) || util::has_property($e, "subcontext")) &&
- $e->{POINTERS} == 0 &&
+ if (!can_contain_deferred($e) &&
!util::array_size($e)) {
return 0;
}
{
my $e = shift;
- return 0 if (util::has_property($e, "ref"));
+ return 0 if (util::has_property($e, "ref") && $e->{PARENT}->{TYPE} eq "FUNCTION");
return 1 if ($e->{POINTERS} || util::array_size($e));
return 0;
}
if ($e->{TYPE} =~ "string") {
$ret = "";
- } elsif (is_scalar_type($e->{TYPE}) &&
- $e->{POINTERS}) {
- $ret = "*";
+ } elsif (is_scalar_type($e->{TYPE}) and $e->{POINTERS} and
+ !util::array_size($e)) {
+ $ret .="*";
} elsif (!is_scalar_type($e->{TYPE}) &&
!$e->{POINTERS} &&
!util::array_size($e)) {
return $tmp;
}
+#####################################################################
+# see if a type contains any deferred data
+sub can_contain_deferred
+{
+ my $e = shift;
+
+ return 1 if ($e->{POINTERS});
+ return 0 if (is_scalar_type($e->{TYPE}));
+ return 0 if (util::has_property($e, "subcontext"));
+ return 1 unless (typelist::hasType($e->{TYPE})); # assume the worst
+
+ my $type = typelist::getType($e->{TYPE});
+
+ foreach my $x (@{$type->{DATA}->{ELEMENTS}}) {
+ return 1 if (can_contain_deferred ($x));
+ }
+
+ return 0;
+}
+
#####################################################################
# parse array preceding data - push side
sub ParseArrayPushPreceding($$$)
my $ndr = shift;
my $var_prefix = shift;
my $ndr_flags = shift;
+ my $cprefix = c_push_prefix($e);
my $size = ParseExpr($e, util::array_size($e), $var_prefix);
}
if (is_scalar_type($e->{TYPE})) {
- pidl "NDR_CHECK(ndr_push_array_$e->{TYPE}($ndr, $ndr_flags, $var_prefix$e->{NAME}, $size));";
+ pidl "NDR_CHECK(ndr_push_array_$e->{TYPE}($ndr, $ndr_flags, $cprefix$var_prefix$e->{NAME}, $size));";
} else {
- 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}));";
+ pidl "NDR_CHECK(ndr_push_array($ndr, $ndr_flags, $cprefix$var_prefix$e->{NAME}, sizeof($cprefix$var_prefix$e->{NAME}\[0]), $size, (ndr_push_flags_fn_t)ndr_push_$e->{TYPE}));";
}
}
my $e = shift;
my $var_prefix = shift;
my $size = ParseExpr($e, util::array_size($e), $var_prefix);
- my $ptr_prefix = c_ptr_prefix($e);
+ my $cprefix = c_push_prefix($e);
if (is_varying_array($e)) {
$size = ParseExpr($e, util::has_property($e, "length_is"), $var_prefix);
}
if (is_scalar_type($e->{TYPE})) {
- pidl "ndr_print_array_$e->{TYPE}(ndr, \"$e->{NAME}\", $var_prefix$e->{NAME}, $size);";
+ pidl "ndr_print_array_$e->{TYPE}(ndr, \"$e->{NAME}\", $cprefix$var_prefix$e->{NAME}, $size);";
} else {
- 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});";
+ pidl "ndr_print_array(ndr, \"$e->{NAME}\", $cprefix$var_prefix$e->{NAME}, sizeof($cprefix$var_prefix$e->{NAME}\[0]), $size, (ndr_print_fn_t)ndr_print_$e->{TYPE});";
}
}
my $e = shift;
my $var_prefix = shift;
- if (!is_surrounding_array($e) && is_conformant_array($e)) {
+ if (is_conformant_array($e)) {
my $size = ParseExpr($e, util::array_size($e), $var_prefix);
pidl "if ($var_prefix$e->{NAME}) {";
indent;
my $var_prefix = shift;
my $ndr_flags = shift;
- my $size = ParseExpr($e, util::array_size($e), $var_prefix);
- my $alloc_size = $size;
+ my $cprefix = c_pull_prefix($e);
+ my $length = ParseExpr($e, util::array_size($e), $var_prefix);
+ my $size = $length;
+
+ if (is_conformant_array($e)) {
+ $length = $size = "ndr_get_array_size($ndr, &$var_prefix$e->{NAME})";
+ }
# if this is a conformant array then we use that size to allocate, and make sure
# we allocate enough to pull the elements
- if (is_conformant_array($e) and is_surrounding_array($e)) {
- $alloc_size = "ndr_get_array_size($ndr, &$var_prefix$e->{NAME})";
- check_null_pointer($size);
- pidl "if ($size > $alloc_size) {";
- indent;
- pidl "return ndr_pull_error($ndr, NDR_ERR_CONFORMANT_SIZE, \"Bad conformant size %u should be %u\", $alloc_size, $size);";
- deindent;
- pidl "}";
- } elsif (!is_inline_array($e)) {
- if ($var_prefix =~ /^r->out/ && $size =~ /^\*r->in/) {
- my $size2 = substr($size, 1);
- pidl "if (ndr->flags & LIBNDR_FLAG_REF_ALLOC) { NDR_ALLOC($ndr, $size2); }";
+ if (!is_inline_array($e) and not is_surrounding_array($e)) {
+ if ($var_prefix =~ /^r->out/ && $length =~ /^\*r->in/) {
+ my $length2 = substr($length, 1);
+ pidl "if (ndr->flags & LIBNDR_FLAG_REF_ALLOC) { NDR_ALLOC($ndr, $length2); }";
}
ParseArrayPullPreceding($e, $var_prefix, $ndr_flags);
+ }
+
+ if (is_varying_array($e)) {
+ pidl "NDR_CHECK(ndr_pull_array_length($ndr, &$var_prefix$e->{NAME}));";
+ $length = "ndr_get_array_length($ndr, &$var_prefix$e->{NAME})";
+ }
+
+ check_null_pointer($length);
- $alloc_size = "ndr_get_array_size($ndr, &$var_prefix$e->{NAME})";
+ if ($length ne $size) {
+ pidl "if ($length > $size) {";
+ indent;
+ pidl "return ndr_pull_error($ndr, NDR_ERR_CONFORMANT_SIZE, \"Bad conformant size %u should be %u\", $size, $length);";
+ deindent;
+ pidl "}";
}
if ((need_alloc($e) && !is_fixed_array($e)) ||
($var_prefix eq "r->in." && util::has_property($e, "ref"))) {
if (!is_inline_array($e) || $ndr_flags eq "NDR_SCALARS") {
- pidl "NDR_ALLOC_N($ndr, $var_prefix$e->{NAME}, $alloc_size);";
+ pidl "NDR_ALLOC_N($ndr, $var_prefix$e->{NAME}, $size);";
}
}
if (($var_prefix eq "r->out." && util::has_property($e, "ref"))) {
if (!is_inline_array($e) || $ndr_flags eq "NDR_SCALARS") {
pidl "if ($ndr->flags & LIBNDR_FLAG_REF_ALLOC) {";
- pidl "\tNDR_ALLOC_N($ndr, $var_prefix$e->{NAME}, $alloc_size);";
+ pidl "\tNDR_ALLOC_N($ndr, $var_prefix$e->{NAME}, $size);";
pidl "}";
}
}
- if (is_varying_array($e)) {
- pidl "NDR_CHECK(ndr_pull_array_length($ndr, &$var_prefix$e->{NAME}));";
- $size = "ndr_get_array_length($ndr, &$var_prefix$e->{NAME})";
- }
-
- check_null_pointer($size);
-
if (is_scalar_type($e->{TYPE})) {
- pidl "NDR_CHECK(ndr_pull_array_$e->{TYPE}($ndr, $ndr_flags, $var_prefix$e->{NAME}, $size));";
+ pidl "NDR_CHECK(ndr_pull_array_$e->{TYPE}($ndr, $ndr_flags, $cprefix$var_prefix$e->{NAME}, $length));";
} else {
- 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}));";
+ pidl "NDR_CHECK(ndr_pull_array($ndr, $ndr_flags, (void **)$cprefix$var_prefix$e->{NAME}, sizeof($cprefix$var_prefix$e->{NAME}\[0]), $length, (ndr_pull_flags_fn_t)ndr_pull_$e->{TYPE}));";
}
}
ParseArrayPush($e, $ndr, "r->", "NDR_SCALARS");
} elsif (need_alloc($e)) {
# no scalar component
- } elsif (my $switch = util::has_property($e, "switch_is")) {
- ParseSwitchPush($e, $ndr, $var_prefix, $ndr_flags, $switch);
} else {
+ if (my $switch = util::has_property($e, "switch_is")) {
+ ParseSwitchPush($e, $ndr, $var_prefix, $ndr_flags, $switch);
+ }
+
pidl "NDR_CHECK(ndr_push_$e->{TYPE}($ndr, $ndr_flags, $cprefix$var_prefix$e->{NAME}));";
}
my $e = shift;
my $var_prefix = shift;
- if (util::has_property($e, "relative")) {
+ if (util::has_property($e, "ref")) {
+ pidl "NDR_CHECK(ndr_push_ref_ptr(ndr, $var_prefix$e->{NAME}));";
+ } elsif (util::has_property($e, "relative")) {
pidl "NDR_CHECK(ndr_push_relative_ptr1(ndr, $var_prefix$e->{NAME}));";
} else {
pidl "NDR_CHECK(ndr_push_unique_ptr(ndr, $var_prefix$e->{NAME}));";
check_null_pointer($switch_var);
- if (!defined $utype ||
- !util::has_property($utype, "nodiscriminant")) {
- my $e2 = util::find_sibling($e, $switch);
- my $type_decl = typelist::mapType($e2);
- pidl "if (($ndr_flags) & NDR_SCALARS) {";
- indent;
- pidl "$type_decl _level;";
- pidl "NDR_CHECK(ndr_pull_$e2->{TYPE}($ndr, NDR_SCALARS, &_level));";
- if ($switch_var =~ /r->in/) {
- pidl "if (!($ndr->flags & LIBNDR_FLAG_REF_ALLOC) && _level != $switch_var) {";
- indent;
- } else {
- pidl "if (_level != $switch_var) {";
- indent;
- }
- pidl "return ndr_pull_error($ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value %u in $e->{NAME}\", _level);";
- deindent;
- if ($switch_var =~ /r->/) {
- pidl "} else { $switch_var = _level; }";
- } else {
- pidl "}";
- }
- deindent;
- pidl "}";
- }
+ pidl "NDR_CHECK(ndr_pull_set_switch_value($ndr, $cprefix$var_prefix$e->{NAME}, $switch_var));";
- pidl "NDR_CHECK(ndr_pull_$e->{TYPE}($ndr, $ndr_flags, $switch_var, $cprefix$var_prefix$e->{NAME}));";
}
#####################################################################
check_null_pointer($switch_var);
- my $utype = typelist::getType($e->{TYPE});
- if (!defined $utype ||
- !util::has_property($utype, "nodiscriminant")) {
- my $e2 = util::find_sibling($e, $switch);
- pidl "if (($ndr_flags) & NDR_SCALARS) {";
- pidl "\tNDR_CHECK(ndr_push_$e2->{TYPE}($ndr, NDR_SCALARS, $switch_var));";
- pidl "}";
- }
+ pidl "NDR_CHECK(ndr_push_set_switch_value($ndr, $cprefix$var_prefix$e->{NAME}, $switch_var));";
- pidl "NDR_CHECK(ndr_push_$e->{TYPE}($ndr, $ndr_flags, $switch_var, $cprefix$var_prefix$e->{NAME}));";
}
#####################################################################
} elsif (need_wire_pointer($e)) {
ParsePtrPull($e, $ptr_prefix.$var_prefix);
} elsif (is_surrounding_array($e)) {
- } elsif (my $switch = util::has_property($e, "switch_is")) {
- ParseSwitchPull($e, $ndr, $var_prefix, $ndr_flags, $switch);
} else {
+ if (my $switch = util::has_property($e, "switch_is")) {
+ ParseSwitchPull($e, $ndr, $var_prefix, $ndr_flags, $switch);
+ }
+
pidl "NDR_CHECK(ndr_pull_$e->{TYPE}($ndr, $ndr_flags, $cprefix$var_prefix$e->{NAME}));";
}
my($e) = shift;
my($var_prefix) = shift;
- pidl "NDR_CHECK(ndr_pull_unique_ptr(ndr, &_ptr_$e->{NAME}));";
+ if (util::has_property($e, "ref")) {
+ pidl "NDR_CHECK(ndr_pull_ref_ptr(ndr, &_ptr_$e->{NAME}));";
+ } else {
+ pidl "NDR_CHECK(ndr_pull_unique_ptr(ndr, &_ptr_$e->{NAME}));";
+ }
pidl "if (_ptr_$e->{NAME}) {";
indent;
pidl "NDR_ALLOC(ndr, $var_prefix$e->{NAME});";
if (util::array_size($e)) {
ParseArrayPush($e, $ndr, "r->", $ndr_flags);
- } elsif (my $switch = util::has_property($e, "switch_is")) {
- ParseSwitchPush($e, $ndr, $var_prefix, $ndr_flags, $switch);
} else {
+ if (my $switch = util::has_property($e, "switch_is")) {
+ ParseSwitchPush($e, $ndr, $var_prefix, $ndr_flags, $switch);
+ }
+
pidl "NDR_CHECK(ndr_push_$e->{TYPE}(ndr, $ndr_flags, $cprefix$var_prefix$e->{NAME}));";
}
if (util::array_size($e)) {
ParseArrayPull($e, $ndr, "r->", $ndr_flags);
- } elsif (my $switch = util::has_property($e, "switch_is")) {
- ParseSwitchPull($e, $ndr, $var_prefix, $ndr_flags, $switch);
} else {
+ if (my $switch = util::has_property($e, "switch_is")) {
+ ParseSwitchPull($e, $ndr, $var_prefix, $ndr_flags, $switch);
+ }
+
pidl "NDR_CHECK(ndr_pull_$e->{TYPE}($ndr, $ndr_flags, $cprefix$var_prefix$e->{NAME}));";
}
my $e = shift;
my $have_default = 0;
+ pidl "int level;";
+
start_flags($e);
+ pidl "level = ndr_push_get_switch_value(ndr, r);";
+
pidl "if (!(ndr_flags & NDR_SCALARS)) goto buffers;";
+ if (!util::has_property($e, "nodiscriminant")) {
+ my $switch_type = util::has_property($e, "switch_type");
+ $switch_type = "uint32" unless (defined ($switch_type));
+ pidl "NDR_CHECK(ndr_push_$switch_type(ndr, NDR_SCALARS, level));";
+ }
+
pidl "NDR_CHECK(ndr_push_struct_start(ndr));";
# my $align = union_alignment($e);
{
my $e = shift;
my $have_default = 0;
+ my $switch_type = util::has_property($e, "switch_type");
+ $switch_type = "uint32" unless defined($switch_type);
+
+ pidl "int level;";
+ if (!util::has_property($e, "nodiscriminant")) {
+ if (typelist::typeIs($switch_type, "ENUM")) {
+ $switch_type = typelist::enum_type_fn(typelist::getType($switch_type));
+ }
+ pidl typelist::mapScalarType($switch_type) . " _level;";
+ }
start_flags($e);
+ pidl "level = ndr_pull_get_switch_value(ndr, r);";
+
pidl "if (!(ndr_flags & NDR_SCALARS)) goto buffers;";
+ if (!util::has_property($e, "nodiscriminant")) {
+ pidl "NDR_CHECK(ndr_pull_$switch_type(ndr, NDR_SCALARS, &_level));";
+ pidl "if (_level != level) {";
+ pidl "\treturn ndr_pull_error(ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value %u for $e->{PARENT}->{NAME}\", _level);";
+ pidl "}";
+ }
+
pidl "NDR_CHECK(ndr_pull_struct_start(ndr));";
# my $align = union_alignment($e);
sub ArgsUnionPush($)
{
my $e = shift;
- return "struct ndr_push *ndr, int ndr_flags, int level, union $e->{NAME} *r";
+ return "struct ndr_push *ndr, int ndr_flags, union $e->{NAME} *r";
}
sub ArgsUnionPrint($)
sub ArgsUnionPull($)
{
my $e = shift;
- return "struct ndr_pull *ndr, int ndr_flags, int level, union $e->{NAME} *r";
+ return "struct ndr_pull *ndr, int ndr_flags, union $e->{NAME} *r";
}
sub ArgsUnionNdrSize($)
if (util::array_size($e)) {
if (need_wire_pointer($e)) {
- pidl "NDR_CHECK(ndr_push_unique_ptr(ndr, r->$inout.$e->{NAME}));";
+ ParsePtrPush($e, "r->$inout.");
pidl "if (r->$inout.$e->{NAME}) {";
indent;
ParseArrayPush($e, "ndr", "r->$inout.", "NDR_SCALARS|NDR_BUFFERS");
foreach my $e (@{$fn->{ELEMENTS}}) {
if (util::has_property($e, "in")) {
+ if (util::has_property($e, "ref")) {
+ check_null_pointer("*r->in.$e->{NAME}");
+ }
ParseFunctionElementPush($e, "in");
}
}
foreach my $e (@{$fn->{ELEMENTS}}) {
if (util::has_property($e, "out")) {
+ if (util::has_property($e, "ref")) {
+ check_null_pointer("*r->out.$e->{NAME}");
+ }
ParseFunctionElementPush($e, "out");
}
}