use Parse::Pidl::Typelist qw(hasType getType mapTypeName typeHasBody);
use Parse::Pidl::Util qw(has_property ParseExpr ParseExprExt print_uuid unmake_str);
use Parse::Pidl::CUtil qw(get_pointer_to get_value_of get_array_element);
-use Parse::Pidl::NDR qw(GetPrevLevel GetNextLevel ContainsDeferred is_charset_array);
+use Parse::Pidl::NDR qw(GetPrevLevel GetNextLevel ContainsDeferred ContainsPipe is_charset_array);
use Parse::Pidl::Samba4 qw(is_intree choose_header ArrayDynamicallyAllocated);
use Parse::Pidl::Samba4::Header qw(GenerateFunctionInEnv GenerateFunctionOutEnv EnvSubstituteValue GenerateStructEnv);
use Parse::Pidl qw(warning);
} else {
$size = $length = "ndr_string_length($var_name, sizeof(*$var_name))";
}
+ if (defined($l->{SIZE_IS})) {
+ $size = ParseExpr($l->{SIZE_IS}, $env, $e);
+ }
+ if (defined($l->{LENGTH_IS})) {
+ $length = ParseExpr($l->{LENGTH_IS}, $env, $e);
+ }
} else {
$size = ParseExpr($l->{SIZE_IS}, $env, $e);
$length = ParseExpr($l->{LENGTH_IS}, $env, $e);
}
if ((!$l->{IS_SURROUNDING}) and $l->{IS_CONFORMANT}) {
- $self->pidl("NDR_CHECK(ndr_push_uint32($ndr, NDR_SCALARS, $size));");
+ $self->pidl("NDR_CHECK(ndr_push_uint3264($ndr, NDR_SCALARS, $size));");
}
-
+
if ($l->{IS_VARYING}) {
- $self->pidl("NDR_CHECK(ndr_push_uint32($ndr, NDR_SCALARS, 0));"); # array offset
- $self->pidl("NDR_CHECK(ndr_push_uint32($ndr, NDR_SCALARS, $length));");
- }
+ $self->pidl("NDR_CHECK(ndr_push_uint3264($ndr, NDR_SCALARS, 0));"); # array offset
+ $self->pidl("NDR_CHECK(ndr_push_uint3264($ndr, NDR_SCALARS, $length));");
+ }
return $length;
}
$nump = $_->{POINTER_INDEX}+1;
}
}
- warning($element->{ORIGINAL}, "Got pointer for `$e->{NAME}', expected fully derefenced variable") if ($nump > length($ptr));
+ warning($element->{ORIGINAL}, "Got pointer for `$e->{NAME}', expected fully dereferenced variable") if ($nump > length($ptr));
return ($origvar);
}
}
}
}
-#####################################################################
-# parse an array - pull side
-sub ParseArrayPullHeader($$$$$$)
+sub is_deferred_switch_non_empty($)
+{
+ # 1 if there needs to be a deferred branch in an ndr_pull/push,
+ # 0 otherwise.
+ my ($e) = @_;
+ my $have_default = 0;
+ foreach my $el (@{$e->{ELEMENTS}}) {
+ if ($el->{CASE} eq "default") {
+ $have_default = 1;
+ }
+ if ($el->{TYPE} ne "EMPTY") {
+ if (ContainsDeferred($el, $el->{LEVELS}[0])) {
+ return 1;
+ }
+ }
+ }
+ return ! $have_default;
+}
+
+sub ParseArrayPullGetSize($$$$$$)
{
my ($self,$e,$l,$ndr,$var_name,$env) = @_;
- my $length;
my $size;
if ($l->{IS_CONFORMANT}) {
- $length = $size = "ndr_get_array_size($ndr, " . get_pointer_to($var_name) . ")";
- } elsif ($l->{IS_ZERO_TERMINATED}) { # Noheader arrays
- $length = $size = "ndr_get_string_size($ndr, sizeof(*$var_name))";
+ $size = "ndr_get_array_size($ndr, " . get_pointer_to($var_name) . ")";
+ } elsif ($l->{IS_ZERO_TERMINATED} and $l->{SIZE_IS} == 0 and $l->{LENGTH_IS} == 0) { # Noheader arrays
+ $size = "ndr_get_string_size($ndr, sizeof(*$var_name))";
} else {
- $length = $size = ParseExprExt($l->{SIZE_IS}, $env, $e->{ORIGINAL},
+ $size = ParseExprExt($l->{SIZE_IS}, $env, $e->{ORIGINAL},
check_null_pointer($e, $env, sub { $self->pidl(shift); },
"return ndr_pull_error($ndr, NDR_ERR_INVALID_POINTER, \"NULL Pointer for size_is()\");"),
check_fully_dereferenced($e, $env));
}
+ $self->pidl("size_$e->{NAME}_$l->{LEVEL_INDEX} = $size;");
+ my $array_size = "size_$e->{NAME}_$l->{LEVEL_INDEX}";
+
+ if (my $range = has_property($e, "range")) {
+ my ($low, $high) = split(/,/, $range, 2);
+ if ($low < 0) {
+ warning(0, "$low is invalid for the range of an array size");
+ }
+ if ($low == 0) {
+ $self->pidl("if ($array_size > $high) {");
+ } else {
+ $self->pidl("if ($array_size < $low || $array_size > $high) {");
+ }
+ $self->pidl("\treturn ndr_pull_error($ndr, NDR_ERR_RANGE, \"value out of range\");");
+ $self->pidl("}");
+ }
+
+ return $array_size;
+}
+
+#####################################################################
+# parse an array - pull side
+sub ParseArrayPullGetLength($$$$$$;$)
+{
+ my ($self,$e,$l,$ndr,$var_name,$env,$array_size) = @_;
+
+ if (not defined($array_size)) {
+ $array_size = $self->ParseArrayPullGetSize($e, $l, $ndr, $var_name, $env);
+ }
+
+ if (not $l->{IS_VARYING}) {
+ return $array_size;
+ }
+
+ my $length = "ndr_get_array_length($ndr, " . get_pointer_to($var_name) .")";
+ $self->pidl("length_$e->{NAME}_$l->{LEVEL_INDEX} = $length;");
+ my $array_length = "length_$e->{NAME}_$l->{LEVEL_INDEX}";
+
+ if (my $range = has_property($e, "range")) {
+ my ($low, $high) = split(/,/, $range, 2);
+ if ($low < 0) {
+ warning(0, "$low is invalid for the range of an array size");
+ }
+ if ($low == 0) {
+ $self->pidl("if ($array_length > $high) {");
+ } else {
+ $self->pidl("if ($array_length < $low || $array_length > $high) {");
+ }
+ $self->pidl("\treturn ndr_pull_error($ndr, NDR_ERR_RANGE, \"value out of range\");");
+ $self->pidl("}");
+ }
+
+ return $array_length;
+}
+
+#####################################################################
+# parse an array - pull side
+sub ParseArrayPullHeader($$$$$$)
+{
+ my ($self,$e,$l,$ndr,$var_name,$env) = @_;
+
if ((!$l->{IS_SURROUNDING}) and $l->{IS_CONFORMANT}) {
$self->pidl("NDR_CHECK(ndr_pull_array_size($ndr, " . get_pointer_to($var_name) . "));");
}
if ($l->{IS_VARYING}) {
$self->pidl("NDR_CHECK(ndr_pull_array_length($ndr, " . get_pointer_to($var_name) . "));");
- $length = "ndr_get_array_length($ndr, " . get_pointer_to($var_name) .")";
}
- if ($length ne $size) {
- $self->pidl("if ($length > $size) {");
+ my $array_size = $self->ParseArrayPullGetSize($e, $l, $ndr, $var_name, $env);
+ my $array_length = $self->ParseArrayPullGetLength($e, $l, $ndr, $var_name, $env, $array_size);
+
+ if ($array_length ne $array_size) {
+ $self->pidl("if ($array_length > $array_size) {");
$self->indent;
- $self->pidl("return ndr_pull_error($ndr, NDR_ERR_ARRAY_SIZE, \"Bad array size %u should exceed array length %u\", $size, $length);");
+ $self->pidl("return ndr_pull_error($ndr, NDR_ERR_ARRAY_SIZE, \"Bad array size %u should exceed array length %u\", $array_size, $array_length);");
$self->deindent;
$self->pidl("}");
}
- if ($l->{IS_CONFORMANT} and not $l->{IS_ZERO_TERMINATED}) {
+ if ($l->{IS_CONFORMANT} and (defined($l->{SIZE_IS}) or not $l->{IS_ZERO_TERMINATED})) {
$self->defer("if ($var_name) {");
$self->defer_indent;
my $size = ParseExprExt($l->{SIZE_IS}, $env, $e->{ORIGINAL},
$self->defer("}");
}
- if ($l->{IS_VARYING} and not $l->{IS_ZERO_TERMINATED}) {
+ if ($l->{IS_VARYING} and (defined($l->{LENGTH_IS}) or not $l->{IS_ZERO_TERMINATED})) {
$self->defer("if ($var_name) {");
$self->defer_indent;
my $length = ParseExprExt($l->{LENGTH_IS}, $env, $e->{ORIGINAL},
}
if (ArrayDynamicallyAllocated($e,$l) and not is_charset_array($e,$l)) {
- $self->AllocateArrayLevel($e,$l,$ndr,$var_name,$size);
+ $self->AllocateArrayLevel($e,$l,$ndr,$var_name,$array_size);
}
- return $length;
+ return $array_length;
}
sub compression_alg($$)
my $comndr = "$ndr\_compressed";
my $alg = compression_alg($e, $l);
my $dlen = compression_dlen($e, $l, $env);
+ my $clen = compression_clen($e, $l, $env);
$self->pidl("{");
$self->indent;
$self->pidl("struct ndr_pull *$comndr;");
- $self->pidl("NDR_CHECK(ndr_pull_compression_start($ndr, &$comndr, $alg, $dlen));");
+ $self->pidl("NDR_CHECK(ndr_pull_compression_start($ndr, &$comndr, $alg, $dlen, $clen));");
return $comndr;
}
# Allow speedups for arrays of scalar types
if (is_charset_array($e,$l)) {
- $self->pidl("NDR_CHECK(ndr_push_charset($ndr, $ndr_flags, $var_name, $length, sizeof(" . mapTypeName($nl->{DATA_TYPE}) . "), CH_$e->{PROPERTIES}->{charset}));");
+ if ($l->{IS_TO_NULL}) {
+ $self->pidl("NDR_CHECK(ndr_push_charset_to_null($ndr, $ndr_flags, $var_name, $length, sizeof(" . mapTypeName($nl->{DATA_TYPE}) . "), CH_$e->{PROPERTIES}->{charset}));");
+ } else {
+ $self->pidl("NDR_CHECK(ndr_push_charset($ndr, $ndr_flags, $var_name, $length, sizeof(" . mapTypeName($nl->{DATA_TYPE}) . "), CH_$e->{PROPERTIES}->{charset}));");
+ }
return;
} elsif (has_fast_array($e,$l)) {
$self->pidl("NDR_CHECK(ndr_push_array_$nl->{DATA_TYPE}($ndr, $ndr_flags, $var_name, $length));");
}
}
- if ($l->{TYPE} eq "POINTER" and $deferred) {
+ if ($l->{TYPE} eq "POINTER" and $l->{POINTER_TYPE} eq "ignore") {
+ $self->pidl("/* [ignore] '$e->{NAME}' */");
+ } elsif ($l->{TYPE} eq "POINTER" and $deferred) {
+ my $rel_var_name = $var_name;
if ($l->{POINTER_TYPE} ne "ref") {
$self->pidl("if ($var_name) {");
$self->indent;
if ($l->{POINTER_TYPE} eq "relative") {
- $self->pidl("NDR_CHECK(ndr_push_relative_ptr2($ndr, $var_name));");
+ $self->pidl("NDR_CHECK(ndr_push_relative_ptr2_start($ndr, $rel_var_name));");
+ }
+ if ($l->{POINTER_TYPE} eq "relative_short") {
+ $self->pidl("NDR_CHECK(ndr_push_short_relative_ptr2($ndr, $var_name));");
}
}
$var_name = get_value_of($var_name);
$self->ParseElementPushLevel($e, GetNextLevel($e, $l), $ndr, $var_name, $env, 1, 1);
if ($l->{POINTER_TYPE} ne "ref") {
+ if ($l->{POINTER_TYPE} eq "relative") {
+ $self->pidl("NDR_CHECK(ndr_push_relative_ptr2_end($ndr, $rel_var_name));");
+ }
$self->deindent;
$self->pidl("}");
}
my $length = ParseExpr($l->{LENGTH_IS}, $env, $e->{ORIGINAL});
my $counter = "cntr_$e->{NAME}_$l->{LEVEL_INDEX}";
+ my $array_pointless = ($length eq "0");
+
+ if ($array_pointless) {
+ warning($e->{ORIGINAL}, "pointless array `$e->{NAME}' will always have size 0");
+ }
+
$var_name = get_array_element($var_name, $counter);
- if (($primitives and not $l->{IS_DEFERRED}) or ($deferred and $l->{IS_DEFERRED})) {
- $self->pidl("for ($counter = 0; $counter < $length; $counter++) {");
+ if ((($primitives and not $l->{IS_DEFERRED}) or ($deferred and $l->{IS_DEFERRED})) and not $array_pointless) {
+ $self->pidl("for ($counter = 0; $counter < ($length); $counter++) {");
$self->indent;
$self->ParseElementPushLevel($e, GetNextLevel($e, $l), $ndr, $var_name, $env, 1, 0);
$self->deindent;
$self->pidl("}");
}
- if ($deferred and ContainsDeferred($e, $l)) {
- $self->pidl("for ($counter = 0; $counter < $length; $counter++) {");
+ if ($deferred and ContainsDeferred($e, $l) and not $array_pointless) {
+ $self->pidl("for ($counter = 0; $counter < ($length); $counter++) {");
$self->indent;
$self->ParseElementPushLevel($e, GetNextLevel($e, $l), $ndr, $var_name, $env, 0, 1);
$self->deindent;
$self->pidl("}");
- }
+ }
} elsif ($l->{TYPE} eq "SWITCH") {
$self->ParseElementPushLevel($e, GetNextLevel($e, $l), $ndr, $var_name, $env, $primitives, $deferred);
}
my $var_name = $env->{$e->{NAME}};
+ if (has_property($e, "skip") or has_property($e, "skip_noinit")) {
+ $self->pidl("/* [skip] '$var_name' */");
+ return;
+ }
+
+ return if ContainsPipe($e, $e->{LEVELS}[0]);
+
return unless $primitives or ($deferred and ContainsDeferred($e, $e->{LEVELS}[0]));
# Representation type is different from transmit_as
my ($self,$e,$l,$ndr,$var_name) = @_;
if ($l->{POINTER_TYPE} eq "ref") {
- $self->pidl("if ($var_name == NULL) {");
- $self->indent;
- $self->pidl("return ndr_push_error($ndr, NDR_ERR_INVALID_POINTER, \"NULL [ref] pointer\");");
- $self->deindent;
- $self->pidl("}");
+ if ($l->{LEVEL_INDEX} > 0) {
+ $self->pidl("if ($var_name == NULL) {");
+ $self->indent;
+ $self->pidl("return ndr_push_error($ndr, NDR_ERR_INVALID_POINTER, \"NULL [ref] pointer\");");
+ $self->deindent;
+ $self->pidl("}");
+ }
if ($l->{LEVEL} eq "EMBEDDED") {
- $self->pidl("NDR_CHECK(ndr_push_ref_ptr(ndr));");
+ $self->pidl("NDR_CHECK(ndr_push_ref_ptr(ndr)); /* $var_name */");
}
} elsif ($l->{POINTER_TYPE} eq "relative") {
$self->pidl("NDR_CHECK(ndr_push_relative_ptr1($ndr, $var_name));");
+ } elsif ($l->{POINTER_TYPE} eq "relative_short") {
+ $self->pidl("NDR_CHECK(ndr_push_short_relative_ptr1($ndr, $var_name));");
} elsif ($l->{POINTER_TYPE} eq "unique") {
$self->pidl("NDR_CHECK(ndr_push_unique_ptr($ndr, $var_name));");
} elsif ($l->{POINTER_TYPE} eq "full") {
$self->pidl("NDR_CHECK(ndr_push_full_ptr($ndr, $var_name));");
+ } elsif ($l->{POINTER_TYPE} eq "ignore") {
+ # We don't want this pointer to appear on the wire at all
+ $self->pidl("NDR_CHECK(ndr_push_uint3264(ndr, NDR_SCALARS, 0));");
} else {
die("Unhandled pointer type $l->{POINTER_TYPE}");
}
my($self, $e, $ndr, $var_name, $env) = @_;
return if (has_property($e, "noprint"));
+ my $cur_depth = 0;
+ my $ignore_depth = 0xFFFF;
+ $self->start_flags($e, $ndr);
if ($e->{REPRESENTATION_TYPE} ne $e->{TYPE}) {
$self->pidl("ndr_print_$e->{REPRESENTATION_TYPE}($ndr, \"$e->{NAME}\", $var_name);");
+ $self->end_flags($e, $ndr);
return;
}
}
foreach my $l (@{$e->{LEVELS}}) {
+ $cur_depth += 1;
+
+ if ($cur_depth > $ignore_depth) {
+ next;
+ }
+
if ($l->{TYPE} eq "POINTER") {
$self->pidl("ndr_print_ptr($ndr, \"$e->{NAME}\", $var_name);");
+ if ($l->{POINTER_TYPE} eq "ignore") {
+ $self->pidl("/* [ignore] '$e->{NAME}' */");
+ $ignore_depth = $cur_depth;
+ last;
+ }
$self->pidl("$ndr->depth++;");
if ($l->{POINTER_TYPE} ne "ref") {
$self->pidl("if ($var_name) {");
$var_name = get_pointer_to($var_name);
}
- if ($l->{IS_ZERO_TERMINATED}) {
+ if ($l->{IS_ZERO_TERMINATED} and not defined($l->{LENGTH_IS})) {
$length = "ndr_string_length($var_name, sizeof(*$var_name))";
} else {
$length = ParseExprExt($l->{LENGTH_IS}, $env, $e->{ORIGINAL},
$self->pidl("$ndr->print($ndr, \"\%s: ARRAY(\%d)\", \"$e->{NAME}\", (int)$length);");
$self->pidl("$ndr->depth++;");
- $self->pidl("for ($counter=0;$counter<$length;$counter++) {");
- $self->indent;
- $self->pidl("char *idx_$l->{LEVEL_INDEX}=NULL;");
- $self->pidl("if (asprintf(&idx_$l->{LEVEL_INDEX}, \"[\%d]\", $counter) != -1) {");
+ $self->pidl("for ($counter = 0; $counter < ($length); $counter++) {");
$self->indent;
$var_name = get_array_element($var_name, $counter);
}
foreach my $l (reverse @{$e->{LEVELS}}) {
+ $cur_depth -= 1;
+
+ if ($cur_depth > $ignore_depth) {
+ next;
+ }
+
if ($l->{TYPE} eq "POINTER") {
+ if ($l->{POINTER_TYPE} eq "ignore") {
+ next;
+ }
+
if ($l->{POINTER_TYPE} ne "ref") {
$self->deindent;
$self->pidl("}");
} elsif (($l->{TYPE} eq "ARRAY")
and not is_charset_array($e,$l)
and not has_fast_array($e,$l)) {
- $self->pidl("free(idx_$l->{LEVEL_INDEX});");
- $self->deindent;
- $self->pidl("}");
$self->deindent;
$self->pidl("}");
$self->pidl("$ndr->depth--;");
}
}
+
+ $self->end_flags($e, $ndr);
}
#####################################################################
$self->pidl("NDR_CHECK(".TypeFunctionName("ndr_pull", $l->{DATA_TYPE})."($ndr, $ndr_flags, $var_name));");
- if (my $range = has_property($e, "range")) {
+ my $pl = GetPrevLevel($e, $l);
+
+ my $range = has_property($e, "range");
+ if ($range and $pl->{TYPE} ne "ARRAY") {
$var_name = get_value_of($var_name);
my $signed = Parse::Pidl::Typelist::is_signed($l->{DATA_TYPE});
my ($low, $high) = split(/,/, $range, 2);
my ($self, $e, $l) = @_;
return undef unless ($l->{TYPE} eq "POINTER" or $l->{TYPE} eq "ARRAY");
+ return undef if (($l->{TYPE} eq "POINTER") and ($l->{POINTER_TYPE} eq "ignore"));
return undef unless ($l->{TYPE} ne "ARRAY" or ArrayDynamicallyAllocated($e,$l));
return undef if has_fast_array($e, $l);
if (($l->{TYPE} eq "POINTER") and ($l->{POINTER_TYPE} eq "ref")) {
my $nl = GetNextLevel($e, $l);
- my $next_is_array = ($nl->{TYPE} eq "ARRAY");
- my $next_is_string = (($nl->{TYPE} eq "DATA") and
- ($nl->{DATA_TYPE} eq "string"));
- if ($next_is_array or $next_is_string) {
- return undef;
- } elsif ($l->{LEVEL} eq "TOP") {
+ return undef if ($nl->{TYPE} eq "PIPE");
+ return undef if ($nl->{TYPE} eq "ARRAY");
+ return undef if (($nl->{TYPE} eq "DATA") and ($nl->{DATA_TYPE} eq "string"));
+
+ if ($l->{LEVEL} eq "TOP") {
$mem_flags = "LIBNDR_FLAG_REF_ALLOC";
}
}
my($self,$e,$l,$ndr,$var_name,$env,$primitives,$deferred) = @_;
my $ndr_flags = CalcNdrFlags($l, $primitives, $deferred);
+ my $array_length = undef;
+
+ if (has_property($e, "skip") or has_property($e, "skip_noinit")) {
+ $self->pidl("/* [skip] '$var_name' */");
+ if (not has_property($e, "skip_noinit")) {
+ $self->pidl("NDR_ZERO_STRUCT($var_name);");
+ }
+ return;
+ }
if ($l->{TYPE} eq "ARRAY" and ($l->{IS_VARYING} or $l->{IS_CONFORMANT})) {
$var_name = get_pointer_to($var_name);
$self->ParseSubcontextPullEnd($e, $l, $ndr, $env);
} elsif ($l->{TYPE} eq "ARRAY") {
my $length = $self->ParseArrayPullHeader($e, $l, $ndr, $var_name, $env);
+ $array_length = $length;
my $nl = GetNextLevel($e, $l);
if ($l->{IS_ZERO_TERMINATED}) {
$self->CheckStringTerminator($ndr, $e, $l, $length);
}
- $self->pidl("NDR_CHECK(ndr_pull_charset($ndr, $ndr_flags, ".get_pointer_to($var_name).", $length, sizeof(" . mapTypeName($nl->{DATA_TYPE}) . "), CH_$e->{PROPERTIES}->{charset}));");
+ if ($l->{IS_TO_NULL}) {
+ $self->pidl("NDR_CHECK(ndr_pull_charset_to_null($ndr, $ndr_flags, ".get_pointer_to($var_name).", $length, sizeof(" . mapTypeName($nl->{DATA_TYPE}) . "), CH_$e->{PROPERTIES}->{charset}));");
+ } else {
+ $self->pidl("NDR_CHECK(ndr_pull_charset($ndr, $ndr_flags, ".get_pointer_to($var_name).", $length, sizeof(" . mapTypeName($nl->{DATA_TYPE}) . "), CH_$e->{PROPERTIES}->{charset}));");
+ }
return;
} elsif (has_fast_array($e, $l)) {
if ($l->{IS_ZERO_TERMINATED}) {
}
# add additional constructions
- if ($l->{TYPE} eq "POINTER" and $deferred) {
+ if ($l->{TYPE} eq "POINTER" and $l->{POINTER_TYPE} eq "ignore") {
+ $self->pidl("/* [ignore] '$e->{NAME}' */");
+ } elsif ($l->{TYPE} eq "POINTER" and $deferred) {
if ($l->{POINTER_TYPE} ne "ref") {
$self->pidl("if ($var_name) {");
$self->indent;
- if ($l->{POINTER_TYPE} eq "relative") {
+ if ($l->{POINTER_TYPE} eq "relative" or $l->{POINTER_TYPE} eq "relative_short") {
$self->pidl("uint32_t _relative_save_offset;");
$self->pidl("_relative_save_offset = $ndr->offset;");
$self->pidl("NDR_CHECK(ndr_pull_relative_ptr2($ndr, $var_name));");
$self->ParseMemCtxPullEnd($e, $l, $ndr);
if ($l->{POINTER_TYPE} ne "ref") {
- if ($l->{POINTER_TYPE} eq "relative") {
+ if ($l->{POINTER_TYPE} eq "relative" or $l->{POINTER_TYPE} eq "relative_short") {
+ $self->pidl("if ($ndr->offset > $ndr->relative_highest_offset) {");
+ $self->indent;
+ $self->pidl("$ndr->relative_highest_offset = $ndr->offset;");
+ $self->deindent;
+ $self->pidl("}");
$self->pidl("$ndr->offset = _relative_save_offset;");
}
$self->deindent;
}
} elsif ($l->{TYPE} eq "ARRAY" and
not has_fast_array($e,$l) and not is_charset_array($e, $l)) {
- my $length = ParseExpr($l->{LENGTH_IS}, $env, $e->{ORIGINAL});
+ my $length = $array_length;
my $counter = "cntr_$e->{NAME}_$l->{LEVEL_INDEX}";
my $array_name = $var_name;
+ if (not defined($length)) {
+ $length = $self->ParseArrayPullGetLength($e, $l, $ndr, $var_name, $env);
+ }
+
$var_name = get_array_element($var_name, $counter);
$self->ParseMemCtxPullStart($e, $l, $ndr, $array_name);
$self->CheckStringTerminator($ndr,$e,$l,$length);
}
- $self->pidl("for ($counter = 0; $counter < $length; $counter++) {");
+ $self->pidl("for ($counter = 0; $counter < ($length); $counter++) {");
$self->indent;
$self->ParseElementPullLevel($e, $nl, $ndr, $var_name, $env, 1, 0);
$self->deindent;
}
if ($deferred and ContainsDeferred($e, $l)) {
- $self->pidl("for ($counter = 0; $counter < $length; $counter++) {");
+ $self->pidl("for ($counter = 0; $counter < ($length); $counter++) {");
$self->indent;
$self->ParseElementPullLevel($e,GetNextLevel($e,$l), $ndr, $var_name, $env, 0, 1);
$self->deindent;
my $represent_name;
my $transmit_name;
+ return if ContainsPipe($e, $e->{LEVELS}[0]);
+
return unless $primitives or ($deferred and ContainsDeferred($e, $e->{LEVELS}[0]));
if ($e->{REPRESENTATION_TYPE} ne $e->{TYPE}) {
$self->pidl("\tNDR_PULL_ALLOC($ndr, $var_name);");
$self->pidl("}");
}
-
+
return;
} elsif ($l->{POINTER_TYPE} eq "ref" and $l->{LEVEL} eq "EMBEDDED") {
$self->pidl("NDR_CHECK(ndr_pull_ref_ptr($ndr, &_ptr_$e->{NAME}));");
($l->{POINTER_TYPE} eq "relative") or
($l->{POINTER_TYPE} eq "full")) {
$self->pidl("NDR_CHECK(ndr_pull_generic_ptr($ndr, &_ptr_$e->{NAME}));");
+ } elsif ($l->{POINTER_TYPE} eq "relative_short") {
+ $self->pidl("NDR_CHECK(ndr_pull_relative_ptr_short($ndr, &_ptr_$e->{NAME}));");
+ } elsif ($l->{POINTER_TYPE} eq "ignore") {
+ #We want to consume the pointer bytes, but ignore the pointer value
+ $self->pidl("NDR_CHECK(ndr_pull_uint3264(ndr, NDR_SCALARS, &_ptr_$e->{NAME}));");
+ $self->pidl("_ptr_$e->{NAME} = 0;");
} else {
die("Unhandled pointer type $l->{POINTER_TYPE}");
}
$self->pidl("if (_ptr_$e->{NAME}) {");
$self->indent;
- # Don't do this for arrays, they're allocated at the actual level
- # of the array
- unless ($next_is_array or $next_is_string) {
- $self->pidl("NDR_PULL_ALLOC($ndr, $var_name);");
+ if ($l->{POINTER_TYPE} eq "ignore") {
+ # Don't do anything, we don't want to do the
+ # allocation, as we forced it to NULL just above, and
+ # we may not know the declared type anyway.
} else {
- # FIXME: Yes, this is nasty.
- # We allocate an array twice
- # - once just to indicate that it's there,
- # - then the real allocation...
- $self->pidl("NDR_PULL_ALLOC($ndr, $var_name);");
+ # Don't do this for arrays, they're allocated at the actual level
+ # of the array
+ unless ($next_is_array or $next_is_string) {
+ $self->pidl("NDR_PULL_ALLOC($ndr, $var_name);");
+ } else {
+ # FIXME: Yes, this is nasty.
+ # We allocate an array twice
+ # - once just to indicate that it's there,
+ # - then the real allocation...
+ $self->pidl("NDR_PULL_ALLOC($ndr, $var_name);");
+ }
}
#$self->pidl("memset($var_name, 0, sizeof($var_name));");
- if ($l->{POINTER_TYPE} eq "relative") {
+ if ($l->{POINTER_TYPE} eq "relative" or $l->{POINTER_TYPE} eq "relative_short") {
$self->pidl("NDR_CHECK(ndr_pull_relative_ptr1($ndr, $var_name, _ptr_$e->{NAME}));");
}
$self->deindent;
$self->pidl("}");
}
+sub CheckRefPtrs($$$$)
+{
+ my ($self,$e,$ndr,$env) = @_;
+
+ return if ContainsPipe($e, $e->{LEVELS}[0]);
+ return if ($e->{LEVELS}[0]->{TYPE} ne "POINTER");
+ return if ($e->{LEVELS}[0]->{POINTER_TYPE} ne "ref");
+
+ my $var_name = $env->{$e->{NAME}};
+ $var_name = append_prefix($e, $var_name);
+
+ $self->pidl("if ($var_name == NULL) {");
+ $self->indent;
+ $self->pidl("return ndr_push_error($ndr, NDR_ERR_INVALID_POINTER, \"NULL [ref] pointer\");");
+ $self->deindent;
+ $self->pidl("}");
+}
+
sub ParseStructPushPrimitives($$$$$)
{
my ($self, $struct, $ndr, $varname, $env) = @_;
+ $self->CheckRefPtrs($_, $ndr, $env) foreach (@{$struct->{ELEMENTS}});
+
# see if the structure contains a conformant array. If it
# does, then it must be the last element of the structure, and
# we need to push the conformant length early, as it fits on
} else {
$size = "ndr_string_length($varname->$e->{NAME}, sizeof(*$varname->$e->{NAME}))";
}
+ if (defined($e->{LEVELS}[0]->{SIZE_IS})) {
+ $size = ParseExpr($e->{LEVELS}[0]->{SIZE_IS}, $env, $e->{ORIGINAL});
+ }
} else {
$size = ParseExpr($e->{LEVELS}[0]->{SIZE_IS}, $env, $e->{ORIGINAL});
}
- $self->pidl("NDR_CHECK(ndr_push_uint32($ndr, NDR_SCALARS, $size));");
+ $self->pidl("NDR_CHECK(ndr_push_uint3264($ndr, NDR_SCALARS, $size));");
} else {
- $self->pidl("NDR_CHECK(ndr_push_uint32($ndr, NDR_SCALARS, ndr_string_array_size($ndr, $varname->$e->{NAME})));");
+ $self->pidl("NDR_CHECK(ndr_push_uint3264($ndr, NDR_SCALARS, ndr_string_array_size($ndr, $varname->$e->{NAME})));");
}
}
}
$self->ParseElementPush($_, $ndr, $env, 1, 0) foreach (@{$struct->{ELEMENTS}});
+
+ $self->pidl("NDR_CHECK(ndr_push_trailer_align($ndr, $struct->{ALIGN}));");
}
sub ParseStructPushDeferred($$$$)
EnvSubstituteValue($env, $struct);
- $self->DeclareArrayVariables($_) foreach (@{$struct->{ELEMENTS}});
+ $self->DeclareArrayVariablesNoZero($_, $env) foreach (@{$struct->{ELEMENTS}});
$self->start_flags($struct, $ndr);
+ $self->pidl("NDR_PUSH_CHECK_FLAGS(ndr, ndr_flags);");
$self->pidl("if (ndr_flags & NDR_SCALARS) {");
$self->indent;
$self->ParseStructPushPrimitives($struct, $ndr, $varname, $env);
my($type_fn) = $enum->{BASE_TYPE};
$self->start_flags($enum, $ndr);
- $self->pidl("NDR_CHECK(ndr_push_$type_fn($ndr, NDR_SCALARS, $varname));");
+ $self->pidl("NDR_CHECK(ndr_push_enum_$type_fn($ndr, NDR_SCALARS, $varname));");
$self->end_flags($enum, $ndr);
}
$self->pidl("$type_v_decl v;");
$self->start_flags($enum, $ndr);
- $self->pidl("NDR_CHECK(ndr_pull_$type_fn($ndr, NDR_SCALARS, &v));");
+ $self->pidl("NDR_CHECK(ndr_pull_enum_$type_fn($ndr, NDR_SCALARS, &v));");
$self->pidl("*$varname = v;");
$self->end_flags($enum, $ndr);
$self->DeclareArrayVariables($_) foreach (@{$struct->{ELEMENTS}});
$self->pidl("ndr_print_struct($ndr, name, \"$name\");");
+ $self->pidl("if (r == NULL) { ndr_print_null($ndr); return; }");
$self->start_flags($struct, $ndr);
sub DeclarePtrVariables($$)
{
my ($self,$e) = @_;
+
+ if (has_property($e, "skip") or has_property($e, "skip_noinit")) {
+ return;
+ }
+
foreach my $l (@{$e->{LEVELS}}) {
+ my $size = 32;
if ($l->{TYPE} eq "POINTER" and
not ($l->{POINTER_TYPE} eq "ref" and $l->{LEVEL} eq "TOP")) {
- $self->pidl("uint32_t _ptr_$e->{NAME};");
+ if ($l->{POINTER_TYPE} eq "relative_short") {
+ $size = 16;
+ }
+ $self->pidl("uint${size}_t _ptr_$e->{NAME};");
last;
}
}
}
-sub DeclareArrayVariables($$)
+sub DeclareArrayVariables($$;$)
{
- my ($self,$e) = @_;
+ my ($self,$e,$pull) = @_;
+
+ if (has_property($e, "skip") or has_property($e, "skip_noinit")) {
+ return;
+ }
foreach my $l (@{$e->{LEVELS}}) {
+ next if ($l->{TYPE} ne "ARRAY");
+ if (defined($pull)) {
+ $self->pidl("uint32_t size_$e->{NAME}_$l->{LEVEL_INDEX} = 0;");
+ if ($l->{IS_VARYING}) {
+ $self->pidl("uint32_t length_$e->{NAME}_$l->{LEVEL_INDEX} = 0;");
+ }
+ }
next if has_fast_array($e,$l);
next if is_charset_array($e,$l);
- if ($l->{TYPE} eq "ARRAY") {
+ $self->pidl("uint32_t cntr_$e->{NAME}_$l->{LEVEL_INDEX};");
+ }
+}
+
+sub DeclareArrayVariablesNoZero($$$)
+{
+ my ($self,$e,$env) = @_;
+
+ if (has_property($e, "skip") or has_property($e, "skip_noinit")) {
+ return;
+ }
+
+ foreach my $l (@{$e->{LEVELS}}) {
+ next if ($l->{TYPE} ne "ARRAY");
+ next if has_fast_array($e,$l);
+ next if is_charset_array($e,$l);
+ my $length = ParseExpr($l->{LENGTH_IS}, $env, $e->{ORIGINAL});
+ if ($length eq "0") {
+ warning($e->{ORIGINAL}, "pointless array cntr: 'cntr_$e->{NAME}_$l->{LEVEL_INDEX}': length=$length");
+ } else {
$self->pidl("uint32_t cntr_$e->{NAME}_$l->{LEVEL_INDEX};");
}
}
sub DeclareMemCtxVariables($$)
{
my ($self,$e) = @_;
+
+ if (has_property($e, "skip") or has_property($e, "skip_noinit")) {
+ return;
+ }
+
foreach my $l (@{$e->{LEVELS}}) {
my $mem_flags = $self->ParseMemCtxPullFlags($e, $l);
+
+ if (($l->{TYPE} eq "POINTER") and ($l->{POINTER_TYPE} eq "ignore")) {
+ last;
+ }
+
if (defined($mem_flags)) {
- $self->pidl("TALLOC_CTX *_mem_save_$e->{NAME}_$l->{LEVEL_INDEX};");
+ $self->pidl("TALLOC_CTX *_mem_save_$e->{NAME}_$l->{LEVEL_INDEX} = NULL;");
}
}
}
$self->ParseElementPull($_, $ndr, $env, 1, 0) foreach (@{$struct->{ELEMENTS}});
$self->add_deferred();
+
+ $self->pidl("NDR_CHECK(ndr_pull_trailer_align($ndr, $struct->{ALIGN}));");
}
sub ParseStructPullDeferred($$$$$)
# declare any internal pointers we need
foreach my $e (@{$struct->{ELEMENTS}}) {
$self->DeclarePtrVariables($e);
- $self->DeclareArrayVariables($e);
+ $self->DeclareArrayVariables($e, "pull");
$self->DeclareMemCtxVariables($e);
}
my $env = GenerateStructEnv($struct, $varname);
+ $self->pidl("NDR_PULL_CHECK_FLAGS(ndr, ndr_flags);");
$self->pidl("if (ndr_flags & NDR_SCALARS) {");
$self->indent;
$self->ParseStructPullPrimitives($struct,$ndr,$varname,$env);
if (my $flags = has_property($t, "flag")) {
$self->pidl("flags |= $flags;");
}
- $self->pidl("return ndr_size_struct($varname, flags, (ndr_push_flags_fn_t)ndr_push_$name, ic);");
+ $self->pidl("return ndr_size_struct($varname, flags, (ndr_push_flags_fn_t)ndr_push_$name);");
}
sub DeclStruct($$$$)
sub ArgsStructNdrSize($$$)
{
my ($d, $name, $varname) = @_;
- return "const struct $name *$varname, struct smb_iconv_convenience *ic, int flags";
+ return "const struct $name *$varname, int flags";
}
$typefamily{STRUCT} = {
$self->pidl("flags |= $flags;");
}
- $self->pidl("return ndr_size_union($varname, flags, level, (ndr_push_flags_fn_t)ndr_push_$name, ic);");
+ $self->pidl("return ndr_size_union($varname, flags, level, (ndr_push_flags_fn_t)ndr_push_$name);");
}
sub ParseUnionPushPrimitives($$$$)
my $have_default = 0;
- $self->pidl("int level = ndr_push_get_switch_value($ndr, $varname);");
+ $self->pidl("uint32_t level = ndr_push_get_switch_value($ndr, $varname);");
if (defined($e->{SWITCH_TYPE})) {
+ if (defined($e->{ALIGN})) {
+ $self->pidl("NDR_CHECK(ndr_push_union_align($ndr, $e->{ALIGN}));");
+ }
+
$self->pidl("NDR_CHECK(ndr_push_$e->{SWITCH_TYPE}($ndr, NDR_SCALARS, level));");
}
+ if (defined($e->{ALIGN})) {
+ if ($e->{IS_MS_UNION}) {
+ $self->pidl("/* ms_union is always aligned to the largest union arm*/");
+ $self->pidl("NDR_CHECK(ndr_push_align($ndr, $e->{ALIGN}));");
+ } else {
+ $self->pidl("NDR_CHECK(ndr_push_union_align($ndr, $e->{ALIGN}));");
+ }
+ }
+
$self->pidl("switch (level) {");
$self->indent;
foreach my $el (@{$e->{ELEMENTS}}) {
$self->pidl("NDR_CHECK(ndr_push_setup_relative_base_offset1($ndr, $varname, $ndr->offset));");
}
$self->DeclareArrayVariables($el);
- $self->ParseElementPush($el, $ndr, {$el->{NAME} => "$varname->$el->{NAME}"}, 1, 0);
+ my $el_env = {$el->{NAME} => "$varname->$el->{NAME}"};
+ $self->CheckRefPtrs($el, $ndr, $el_env);
+ $self->ParseElementPush($el, $ndr, $el_env, 1, 0);
$self->deindent;
}
$self->pidl("break; }");
}
if (! $have_default) {
$self->pidl("default:");
- $self->pidl("\treturn ndr_push_error($ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value \%u\", level);");
+ $self->pidl("\treturn ndr_push_error($ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value \%u at \%s\", level, __location__);");
}
$self->deindent;
$self->pidl("}");
my $have_default = 0;
- $self->pidl("int level = ndr_push_get_switch_value($ndr, $varname);");
+ $self->pidl("uint32_t level = ndr_push_get_switch_value($ndr, $varname);");
if (defined($e->{PROPERTIES}{relative_base})) {
# retrieve the current offset as base for relative pointers
# based on the toplevel struct/union
}
if (! $have_default) {
$self->pidl("default:");
- $self->pidl("\treturn ndr_push_error($ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value \%u\", level);");
+ $self->pidl("\treturn ndr_push_error($ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value \%u at \%s\", level, __location__);");
}
$self->deindent;
$self->pidl("}");
$self->start_flags($e, $ndr);
+ $self->pidl("NDR_PUSH_CHECK_FLAGS(ndr, ndr_flags);");
$self->pidl("if (ndr_flags & NDR_SCALARS) {");
$self->indent;
$self->ParseUnionPushPrimitives($e, $ndr, $varname);
$self->deindent;
$self->pidl("}");
- $self->pidl("if (ndr_flags & NDR_BUFFERS) {");
- $self->indent;
- $self->ParseUnionPushDeferred($e, $ndr, $varname);
- $self->deindent;
- $self->pidl("}");
+ if (is_deferred_switch_non_empty($e)) {
+ $self->pidl("if (ndr_flags & NDR_BUFFERS) {");
+ $self->indent;
+ $self->ParseUnionPushDeferred($e, $ndr, $varname);
+ $self->deindent;
+ $self->pidl("}");
+ }
$self->end_flags($e, $ndr);
}
my ($self,$e,$ndr,$name,$varname) = @_;
my $have_default = 0;
- $self->pidl("int level;");
+ $self->pidl("uint32_t level;");
foreach my $el (@{$e->{ELEMENTS}}) {
$self->DeclareArrayVariables($el);
}
my ($self,$e,$ndr,$varname,$switch_type) = @_;
my $have_default = 0;
+
if (defined($switch_type)) {
+ if (defined($e->{ALIGN})) {
+ $self->pidl("NDR_CHECK(ndr_pull_union_align($ndr, $e->{ALIGN}));");
+ }
+
$self->pidl("NDR_CHECK(ndr_pull_$switch_type($ndr, NDR_SCALARS, &_level));");
$self->pidl("if (_level != level) {");
- $self->pidl("\treturn ndr_pull_error($ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value %u for $varname\", _level);");
+ $self->pidl("\treturn ndr_pull_error($ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value %u for $varname at \%s\", _level, __location__);");
$self->pidl("}");
}
+ if (defined($e->{ALIGN})) {
+ if ($e->{IS_MS_UNION}) {
+ $self->pidl("/* ms_union is always aligned to the largest union arm*/");
+ $self->pidl("NDR_CHECK(ndr_pull_align($ndr, $e->{ALIGN}));");
+ } else {
+ $self->pidl("NDR_CHECK(ndr_pull_union_align($ndr, $e->{ALIGN}));");
+ }
+ }
+
$self->pidl("switch (level) {");
$self->indent;
foreach my $el (@{$e->{ELEMENTS}}) {
if ($el->{TYPE} ne "EMPTY") {
$self->indent;
- $self->DeclarePtrVariables($el);
- $self->DeclareArrayVariables($el);
if (defined($e->{PROPERTIES}{relative_base})) {
$self->pidl("NDR_CHECK(ndr_pull_align($ndr, $el->{ALIGN}));");
# set the current offset as base for relative pointers
}
if (! $have_default) {
$self->pidl("default:");
- $self->pidl("\treturn ndr_pull_error($ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value \%u\", level);");
+ $self->pidl("\treturn ndr_pull_error($ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value \%u at \%s\", level, __location__);");
}
$self->deindent;
$self->pidl("}");
}
if (! $have_default) {
$self->pidl("default:");
- $self->pidl("\treturn ndr_pull_error($ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value \%u\", level);");
+ $self->pidl("\treturn ndr_pull_error($ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value \%u at \%s\", level, __location__);");
}
$self->deindent;
$self->pidl("}");
{
my ($self,$e,$ndr,$varname) = @_;
my $switch_type = $e->{SWITCH_TYPE};
-
- $self->pidl("int level;");
+ my $needs_deferred_switch = is_deferred_switch_non_empty($e);
+ $self->pidl("uint32_t level;");
if (defined($switch_type)) {
if (Parse::Pidl::Typelist::typeIs($switch_type, "ENUM")) {
$switch_type = Parse::Pidl::Typelist::enum_type_fn(getType($switch_type)->{DATA});
next if ($el->{TYPE} eq "EMPTY");
next if ($double_cases{"$el->{NAME}"});
$self->DeclareMemCtxVariables($el);
+ $self->DeclarePtrVariables($el);
+ $self->DeclareArrayVariables($el, "pull");
$double_cases{"$el->{NAME}"} = 1;
}
$self->start_flags($e, $ndr);
- $self->pidl("level = ndr_pull_get_switch_value($ndr, $varname);");
-
+ $self->pidl("NDR_PULL_CHECK_FLAGS(ndr, ndr_flags);");
$self->pidl("if (ndr_flags & NDR_SCALARS) {");
$self->indent;
+ if (! $needs_deferred_switch) {
+ $self->pidl("/* This token is not used again */");
+ $self->pidl("level = ndr_pull_steal_switch_value($ndr, $varname);");
+ } else {
+ $self->pidl("level = ndr_pull_get_switch_value($ndr, $varname);");
+ }
$self->ParseUnionPullPrimitives($e,$ndr,$varname,$switch_type);
$self->deindent;
$self->pidl("}");
-
- $self->pidl("if (ndr_flags & NDR_BUFFERS) {");
- $self->indent;
- $self->ParseUnionPullDeferred($e,$ndr,$varname);
- $self->deindent;
- $self->pidl("}");
-
+ if ($needs_deferred_switch) {
+ $self->pidl("if (ndr_flags & NDR_BUFFERS) {");
+ $self->indent;
+ $self->pidl("/* The token is not needed after this. */");
+ $self->pidl("level = ndr_pull_steal_switch_value($ndr, $varname);");
+ $self->ParseUnionPullDeferred($e,$ndr,$varname);
+ $self->deindent;
+ $self->pidl("}");
+ }
$self->add_deferred();
$self->end_flags($e, $ndr);
sub ArgsUnionNdrSize($$)
{
my ($d,$name) = @_;
- return "const union $name *r, uint32_t level, struct smb_iconv_convenience *ic, int flags";
+ return "const union $name *r, uint32_t level, int flags";
}
$typefamily{UNION} = {
SIZE_FN_BODY => \&ParseTypedefNdrSize,
};
+sub ParsePipePushChunk($$)
+{
+ my ($self, $t) = @_;
+
+ my $pipe = $t;
+ $pipe = $t->{DATA} if ($t->{TYPE} eq "TYPEDEF");
+ my $struct = $pipe->{DATA};
+
+ my $name = "$struct->{NAME}";
+ my $ndr = "ndr";
+ my $varname = "r";
+
+ my $args = $typefamily{$struct->{TYPE}}->{DECL}->($struct, "push", $name, $varname);
+
+ $self->fn_declare("push", $struct, "enum ndr_err_code ndr_push_$name(struct ndr_push *$ndr, int ndr_flags, $args)") or return;
+
+ return if has_property($t, "nopush");
+
+ $self->pidl("{");
+ $self->indent;
+ $self->pidl("uint64_t _flags_save = $ndr->flags;");
+ $self->pidl("ndr_set_flags(&$ndr->flags, LIBNDR_FLAG_WITHIN_PIPE);");
+
+ $self->ParseStructPush($struct, $ndr, $varname);
+ $self->pidl("");
+
+ $self->pidl("NDR_CHECK(ndr_push_pipe_chunk_trailer(ndr, ndr_flags, $varname->count));");
+ $self->pidl("");
+
+ $self->pidl("$ndr->flags = _flags_save;");
+ $self->pidl("return NDR_ERR_SUCCESS;");
+ $self->deindent;
+ $self->pidl("}");
+ $self->pidl("");
+}
+
+sub ParsePipePullChunk($$)
+{
+ my ($self, $t) = @_;
+
+ my $pipe = $t;
+ $pipe = $t->{DATA} if ($t->{TYPE} eq "TYPEDEF");
+ my $struct = $pipe->{DATA};
+
+ my $name = "$struct->{NAME}";
+ my $ndr = "ndr";
+ my $varname = "r";
+
+ my $args = $typefamily{$struct->{TYPE}}->{DECL}->($struct, "pull", $name, $varname);
+
+ $self->fn_declare("pull", $struct, "enum ndr_err_code ndr_pull_$name(struct ndr_pull *$ndr, int ndr_flags, $args)") or return;
+
+ return if has_property($struct, "nopull");
+
+ $self->pidl("{");
+ $self->indent;
+ $self->pidl("uint64_t _flags_save = $ndr->flags;");
+ $self->pidl("ndr_set_flags(&$ndr->flags, LIBNDR_FLAG_WITHIN_PIPE);");
+
+ $self->ParseStructPull($struct, $ndr, $varname);
+ $self->pidl("");
+
+ $self->pidl("NDR_CHECK(ndr_check_pipe_chunk_trailer($ndr, ndr_flags, $varname->count));");
+ $self->pidl("");
+
+ $self->pidl("$ndr->flags = _flags_save;");
+ $self->pidl("return NDR_ERR_SUCCESS;");
+ $self->deindent;
+ $self->pidl("}");
+ $self->pidl("");
+}
+
+sub ParsePipePrintChunk($$)
+{
+ my ($self, $t) = @_;
+
+ my $pipe = $t;
+ $pipe = $t->{DATA} if ($t->{TYPE} eq "TYPEDEF");
+ my $struct = $pipe->{DATA};
+
+ my $name = "$struct->{NAME}";
+ my $ndr = "ndr";
+ my $varname = "r";
+
+ my $args = $typefamily{$struct->{TYPE}}->{DECL}->($struct, "print", $name, $varname);
+
+ $self->pidl_hdr("void ndr_print_$name(struct ndr_print *ndr, const char *name, $args);");
+
+ return if (has_property($t, "noprint"));
+
+ $self->pidl("_PUBLIC_ void ndr_print_$name(struct ndr_print *$ndr, const char *name, $args)");
+ $self->pidl("{");
+ $self->indent;
+ $self->pidl("uint64_t _flags_save = $ndr->flags;");
+ $self->pidl("ndr_set_flags(&$ndr->flags, LIBNDR_FLAG_WITHIN_PIPE);");
+ $self->ParseTypePrint($struct, $ndr, $varname);
+ $self->pidl("$ndr->flags = _flags_save;");
+ $self->deindent;
+ $self->pidl("}");
+ $self->pidl("");
+}
+
#####################################################################
# parse a function - print side
sub ParseFunctionPrint($$)
}
$self->pidl("ndr_print_struct($ndr, name, \"$fn->{NAME}\");");
+ $self->pidl("if (r == NULL) { ndr_print_null($ndr); return; }");
$self->pidl("$ndr->depth++;");
$self->pidl("if (flags & NDR_SET_VALUES) {");
$self->DeclareArrayVariables($e);
}
+ $self->pidl("NDR_PUSH_CHECK_FN_FLAGS(ndr, flags);");
+
$self->pidl("if (flags & NDR_IN) {");
$self->indent;
EnvSubstituteValue($env, $fn);
+ foreach my $e (@{$fn->{ELEMENTS}}) {
+ if (grep(/in/,@{$e->{DIRECTION}})) {
+ $self->CheckRefPtrs($e, $ndr, $env);
+ }
+ }
+
foreach my $e (@{$fn->{ELEMENTS}}) {
if (grep(/in/,@{$e->{DIRECTION}})) {
$self->ParseElementPush($e, $ndr, $env, 1, 1);
$self->indent;
$env = GenerateFunctionOutEnv($fn);
+ EnvSubstituteValue($env, $fn);
+
+ foreach my $e (@{$fn->{ELEMENTS}}) {
+ if (grep(/out/,@{$e->{DIRECTION}})) {
+ $self->CheckRefPtrs($e, $ndr, $env);
+ }
+ }
+
foreach my $e (@{$fn->{ELEMENTS}}) {
if (grep(/out/,@{$e->{DIRECTION}})) {
$self->ParseElementPush($e, $ndr, $env, 1, 1);
$self->pidl("}");
if (grep(/in/,@{$e->{DIRECTION}}) and
grep(/out/,@{$e->{DIRECTION}})) {
- $self->pidl("memcpy(r->out.$e->{NAME}, r->in.$e->{NAME}, $size * sizeof(*r->in.$e->{NAME}));");
+ $self->pidl("memcpy(r->out.$e->{NAME}, r->in.$e->{NAME}, ($size) * sizeof(*r->in.$e->{NAME}));");
}
return;
}
# declare any internal pointers we need
foreach my $e (@{$fn->{ELEMENTS}}) {
$self->DeclarePtrVariables($e);
- $self->DeclareArrayVariables($e);
+ $self->DeclareArrayVariables($e, "pull");
}
my %double_cases = ();
$double_cases{"$e->{NAME}"} = 1;
}
+ $self->pidl("NDR_PULL_CHECK_FN_FLAGS(ndr, flags);");
+
$self->pidl("if (flags & NDR_IN) {");
$self->indent;
# out to be too tricky (tridge)
foreach my $e (@{$fn->{ELEMENTS}}) {
next unless grep(/out/, @{$e->{DIRECTION}});
- $self->pidl("ZERO_STRUCT(r->out);");
+ $self->pidl("NDR_ZERO_STRUCT(r->out);");
$self->pidl("");
last;
}
$e->{LEVELS}[0]->{POINTER_TYPE} eq "ref");
next if (($e->{LEVELS}[1]->{TYPE} eq "DATA") and
($e->{LEVELS}[1]->{DATA_TYPE} eq "string"));
+ next if ($e->{LEVELS}[1]->{TYPE} eq "PIPE");
next if (($e->{LEVELS}[1]->{TYPE} eq "ARRAY")
and $e->{LEVELS}[1]->{IS_ZERO_TERMINATED});
} else {
$self->pidl("memset(r->out.$e->{NAME}, 0, ($size) * sizeof(*r->out.$e->{NAME}));");
}
+ } elsif ($e->{LEVELS}[1]->{TYPE} eq "ARRAY") {
+ if (grep(/in/, @{$e->{DIRECTION}})) {
+ $self->pidl("r->out.$e->{NAME} = r->in.$e->{NAME};");
+ } else {
+ $self->pidl("r->out.$e->{NAME} = NULL;");
+ }
} else {
$self->pidl("NDR_PULL_ALLOC($ndr, r->out.$e->{NAME});");
if (grep(/in/, @{$e->{DIRECTION}})) {
$self->pidl("*r->out.$e->{NAME} = *r->in.$e->{NAME};");
} else {
- $self->pidl("ZERO_STRUCTP(r->out.$e->{NAME});");
+ $self->pidl("NDR_ZERO_STRUCTP(r->out.$e->{NAME});");
}
}
}
$self->pidl("");
}
-sub FunctionCallEntry($$)
+sub ParseGeneratePipeArray($$$)
+{
+ my ($self, $fn, $direction) = @_;
+
+ $self->pidl("static const struct ndr_interface_call_pipe $fn->{NAME}\_$direction\_pipes[] = {");
+ $self->indent;
+
+ foreach my $e (@{$fn->{ELEMENTS}}) {
+ next unless ContainsPipe($e, $e->{LEVELS}[0]);
+ next unless (grep(/$direction/, @{$e->{DIRECTION}}));
+
+ my $cname = "$e->{TYPE}_chunk";
+
+ $self->pidl("{");
+ $self->indent;
+ $self->pidl("\"$direction.$e->{NAME}\",");
+ $self->pidl("\"$cname\",");
+ $self->pidl("sizeof(struct $cname),");
+ $self->pidl("(ndr_push_flags_fn_t) ndr_push_$cname,");
+ $self->pidl("(ndr_pull_flags_fn_t) ndr_pull_$cname,");
+ $self->pidl("(ndr_print_fn_t) ndr_print_$cname,");
+ $self->deindent;
+ $self->pidl("},");
+ }
+ $self->pidl("{ .name = NULL }");
+ $self->deindent;
+ $self->pidl("};");
+ $self->pidl("");
+}
+
+sub FunctionCallPipes($$)
{
my ($self, $d) = @_;
return if not defined($d->{OPNUM});
+
+ my $in_pipes = 0;
+ my $out_pipes = 0;
+
+ foreach my $e (@{$d->{ELEMENTS}}) {
+ next unless ContainsPipe($e, $e->{LEVELS}[0]);
+
+ if (grep(/in/, @{$e->{DIRECTION}})) {
+ $in_pipes++;
+ }
+ if (grep(/out/, @{$e->{DIRECTION}})) {
+ $out_pipes++;
+ }
+ }
+
+ if ($in_pipes) {
+ $self->ParseGeneratePipeArray($d, "in");
+ }
+
+ if ($out_pipes) {
+ $self->ParseGeneratePipeArray($d, "out");
+ }
+}
+
+sub FunctionCallEntry($$)
+{
+ my ($self, $d) = @_;
+ return 0 if not defined($d->{OPNUM});
+
+ my $in_pipes = 0;
+ my $out_pipes = 0;
+
+ foreach my $e (@{$d->{ELEMENTS}}) {
+ next unless ContainsPipe($e, $e->{LEVELS}[0]);
+
+ if (grep(/in/, @{$e->{DIRECTION}})) {
+ $in_pipes++;
+ }
+ if (grep(/out/, @{$e->{DIRECTION}})) {
+ $out_pipes++;
+ }
+ }
+
+ my $in_pipes_ptr = "NULL";
+ my $out_pipes_ptr = "NULL";
+
+ if ($in_pipes) {
+ $in_pipes_ptr = "$d->{NAME}_in_pipes";
+ }
+
+ if ($out_pipes) {
+ $out_pipes_ptr = "$d->{NAME}_out_pipes";
+ }
+
$self->pidl("\t{");
$self->pidl("\t\t\"$d->{NAME}\",");
$self->pidl("\t\tsizeof(struct $d->{NAME}),");
$self->pidl("\t\t(ndr_push_flags_fn_t) ndr_push_$d->{NAME},");
$self->pidl("\t\t(ndr_pull_flags_fn_t) ndr_pull_$d->{NAME},");
$self->pidl("\t\t(ndr_print_function_t) ndr_print_$d->{NAME},");
- $self->pidl("\t\t".($d->{ASYNC}?"true":"false").",");
+ $self->pidl("\t\t{ $in_pipes, $in_pipes_ptr },");
+ $self->pidl("\t\t{ $out_pipes, $out_pipes_ptr },");
$self->pidl("\t},");
+ return 1;
}
#####################################################################
return if ($#{$interface->{FUNCTIONS}}+1 == 0);
return unless defined ($interface->{PROPERTIES}->{uuid});
+ foreach my $d (@{$interface->{INHERITED_FUNCTIONS}},@{$interface->{FUNCTIONS}}) {
+ $self->FunctionCallPipes($d);
+ }
+
$self->pidl("static const struct ndr_interface_call $interface->{NAME}\_calls[] = {");
foreach my $d (@{$interface->{INHERITED_FUNCTIONS}},@{$interface->{FUNCTIONS}}) {
- $self->FunctionCallEntry($d);
- $count++;
+ $count += $self->FunctionCallEntry($d);
}
- $self->pidl("\t{ NULL, 0, NULL, NULL, NULL, false }");
+ $self->pidl("\t{ .name = NULL }");
$self->pidl("};");
$self->pidl("");
if (defined $interface->{PROPERTIES}->{uuid}) {
my $name = uc $interface->{NAME};
$self->pidl_hdr("#define NDR_$name\_UUID " .
- Parse::Pidl::Util::make_str(lc($interface->{PROPERTIES}->{uuid})));
+ Parse::Pidl::Util::make_str(lc($interface->{UUID})));
- if(!defined $interface->{PROPERTIES}->{version}) { $interface->{PROPERTIES}->{version} = "0.0"; }
- $self->pidl_hdr("#define NDR_$name\_VERSION $interface->{PROPERTIES}->{version}");
+ $self->pidl_hdr("#define NDR_$name\_VERSION $interface->{VERSION}");
$self->pidl_hdr("#define NDR_$name\_NAME \"$interface->{NAME}\"");
# Typedefs
foreach my $d (@{$interface->{TYPES}}) {
+ if (Parse::Pidl::Typelist::typeIs($d, "PIPE")) {
+ ($needed->{TypeFunctionName("ndr_push", $d)}) &&
+ $self->ParsePipePushChunk($d);
+ ($needed->{TypeFunctionName("ndr_pull", $d)}) &&
+ $self->ParsePipePullChunk($d);
+ ($needed->{TypeFunctionName("ndr_print", $d)}) &&
+ $self->ParsePipePrintChunk($d);
+
+ $needed->{TypeFunctionName("ndr_pull", $d)} = 0;
+ $needed->{TypeFunctionName("ndr_push", $d)} = 0;
+ $needed->{TypeFunctionName("ndr_print", $d)} = 0;
+ next;
+ }
+
next unless(typeHasBody($d));
($needed->{TypeFunctionName("ndr_push", $d)}) && $self->ParseTypePushFunction($d, "r");
($needed->{"ndr_push_$d->{NAME}"}) && $self->ParseFunctionPush($d);
($needed->{"ndr_pull_$d->{NAME}"}) && $self->ParseFunctionPull($d);
($needed->{"ndr_print_$d->{NAME}"}) && $self->ParseFunctionPrint($d);
-
- # Make sure we don't generate a function twice...
- $needed->{"ndr_push_$d->{NAME}"} = $needed->{"ndr_pull_$d->{NAME}"} =
- $needed->{"ndr_print_$d->{NAME}"} = 0;
}
$self->FunctionTable($interface);
if (is_intree()) {
$self->pidl("#include \"includes.h\"");
} else {
+ $self->pidl("#ifndef _GNU_SOURCE");
$self->pidl("#define _GNU_SOURCE");
+ $self->pidl("#endif");
$self->pidl("#include <stdint.h>");
$self->pidl("#include <stdlib.h>");
$self->pidl("#include <stdio.h>");
my ($t,$needed,$req) = @_;
NeededType($t->{DATA}, $needed, $req) if ($t->{TYPE} eq "TYPEDEF");
+ NeededType($t->{DATA}, $needed, $req) if ($t->{TYPE} eq "PIPE");
if ($t->{TYPE} eq "STRUCT" or $t->{TYPE} eq "UNION") {
return unless defined($t->{ELEMENTS});
my ($interface,$needed) = @_;
NeededFunction($_, $needed) foreach (@{$interface->{FUNCTIONS}});
foreach (reverse @{$interface->{TYPES}}) {
+
if (has_property($_, "public")) {
$needed->{TypeFunctionName("ndr_pull", $_)} = $needed->{TypeFunctionName("ndr_push", $_)} =
$needed->{TypeFunctionName("ndr_print", $_)} = 1;