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::Samba4 qw(is_intree choose_header);
+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);
}
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;
if ($l->{IS_CONFORMANT}) {
$length = $size = "ndr_get_array_size($ndr, " . get_pointer_to($var_name) . ")";
- } elsif ($l->{IS_ZERO_TERMINATED}) { # Noheader arrays
+ } elsif ($l->{IS_ZERO_TERMINATED} and $l->{SIZE_IS} == 0 and $l->{LENGTH_IS} == 0) { # Noheader arrays
$length = $size = "ndr_get_string_size($ndr, sizeof(*$var_name))";
} else {
$length = $size = ParseExprExt($l->{SIZE_IS}, $env, $e->{ORIGINAL},
$self->defer("}");
}
- if (not $l->{IS_FIXED} and not is_charset_array($e, $l)) {
+ if (ArrayDynamicallyAllocated($e,$l) and not is_charset_array($e,$l)) {
$self->AllocateArrayLevel($e,$l,$ndr,$var_name,$size);
}
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})) {
+ 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->pidl("}");
}
- if ($deferred and ContainsDeferred($e, $l)) {
+ 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);
if (my $range = has_property($e, "range")) {
$var_name = get_value_of($var_name);
+ my $signed = Parse::Pidl::Typelist::is_signed($l->{DATA_TYPE});
my ($low, $high) = split(/,/, $range, 2);
- $self->pidl("if ($var_name < $low || $var_name > $high) {");
+ if ($low < 0 and not $signed) {
+ warning(0, "$low is invalid for the range of an unsigned type");
+ }
+ if ($low == 0 and not $signed) {
+ $self->pidl("if ($var_name > $high) {");
+ } else {
+ $self->pidl("if ($var_name < $low || $var_name > $high) {");
+ }
$self->pidl("\treturn ndr_pull_error($ndr, NDR_ERR_RANGE, \"value out of range\");");
$self->pidl("}");
}
return undef unless ($l->{TYPE} eq "POINTER" or $l->{TYPE} eq "ARRAY");
- return undef if ($l->{TYPE} eq "ARRAY" and $l->{IS_FIXED});
+ return undef unless ($l->{TYPE} ne "ARRAY" or ArrayDynamicallyAllocated($e,$l));
return undef if has_fast_array($e, $l);
return undef if is_charset_array($e, $l);
my $counter = "cntr_$e->{NAME}_$l->{LEVEL_INDEX}";
my $array_name = $var_name;
+ if ($l->{IS_VARYING}) {
+ $length = "ndr_get_array_length($ndr, " . get_pointer_to($var_name) .")";
+ }
+
$var_name = get_array_element($var_name, $counter);
$self->ParseMemCtxPullStart($e, $l, $ndr, $array_name);
$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})));");
}
}
EnvSubstituteValue($env, $struct);
- $self->DeclareArrayVariables($_) foreach (@{$struct->{ELEMENTS}});
+ $self->DeclareArrayVariablesNoZero($_, $env) foreach (@{$struct->{ELEMENTS}});
$self->start_flags($struct, $ndr);
}
}
+sub DeclareArrayVariablesNoZero($$$)
+{
+ my ($self,$e,$env) = @_;
+
+ foreach my $l (@{$e->{LEVELS}}) {
+ next if has_fast_array($e,$l);
+ next if is_charset_array($e,$l);
+ if ($l->{TYPE} eq "ARRAY") {
+ 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 (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);");
+ $self->pidl("return ndr_size_struct($varname, flags, (ndr_push_flags_fn_t)ndr_push_$name, ic);");
}
sub DeclStruct($$$$)
sub ArgsStructNdrSize($$$)
{
my ($d, $name, $varname) = @_;
- return "const struct $name *$varname, int flags";
+ return "const struct $name *$varname, struct smb_iconv_convenience *ic, 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);");
+ $self->pidl("return ndr_size_union($varname, flags, level, (ndr_push_flags_fn_t)ndr_push_$name, ic);");
}
sub ParseUnionPushPrimitives($$$$)
}
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("}");
}
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("}");
if (defined($switch_type)) {
$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 (! $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("}");
sub ArgsUnionNdrSize($$)
{
my ($d,$name) = @_;
- return "const union $name *r, uint32_t level, int flags";
+ return "const union $name *r, uint32_t level, struct smb_iconv_convenience *ic, int flags";
}
$typefamily{UNION} = {
sub FunctionCallEntry($$)
{
my ($self, $d) = @_;
- return if not defined($d->{OPNUM});
+ return 0 if not defined($d->{OPNUM});
$self->pidl("\t{");
$self->pidl("\t\t\"$d->{NAME}\",");
$self->pidl("\t\tsizeof(struct $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},");
+ return 1;
}
#####################################################################
$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("};");
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>");