mirror of
https://github.com/samba-team/samba.git
synced 2024-12-23 17:34:34 +03:00
r7695: Add support for the [string] attribute that works in the traditional sense. Not
used anywhere yet.
(This used to be commit a73a35cfc7
)
This commit is contained in:
parent
5b19286df0
commit
cd39847e81
@ -1,38 +1,10 @@
|
||||
- Fix string support.
|
||||
This would make strings a special kind of arrays flagged by the
|
||||
[string] attribute. Pidl itself would support a couple of extra
|
||||
attributes for it's own use while being compatible with other IDL
|
||||
compilers.
|
||||
Proposed extensions for pidl (to arrays):
|
||||
[convert(t)] attribute for forcing conversions from CH_UCS2, etc to UTF8
|
||||
[noheader] attribute -> Indicating the string is not preceded
|
||||
|
||||
Implement:
|
||||
ndr.pm:
|
||||
- represent a string as an array with length set to "STRING"
|
||||
- [string] implies is_varying unless noheader is specified.
|
||||
ndr_parser.pm:
|
||||
- if [charset()] specified, use instead of the for loops (call ndr_pu{ll,sh}_charset()
|
||||
- calculate length using helper function if [string] is specified
|
||||
|
||||
The various flags for strings would change as follows:
|
||||
|
||||
LIBNDR_FLAG_STR_ASCII -> [convert(CH_ASCII)]
|
||||
LIBNDR_FLAG_STR_LEN4 -> [string]
|
||||
LIBNDR_FLAG_STR_SIZE4 -> [size_is()] or if needed [conformant]
|
||||
LIBNDR_FLAG_STR_NOTERM -> array
|
||||
LIBNDR_FLAG_STR_NULLTERM -> [noheader]
|
||||
LIBNDR_FLAG_STR_SIZE2 -> uint16 length; [string] char data[length]
|
||||
LIBNDR_FLAG_STR_BYTESIZE -> uint16 length; [string] char data[length]
|
||||
LIBNDR_FLAG_STR_FIXLEN32 -> [32]
|
||||
LIBNDR_FLAG_STR_CONFORMANT -> no longer needed
|
||||
LIBNDR_FLAG_STR_CHARLEN -> ???
|
||||
LIBNDR_FLAG_STR_UTF8 -> Nothing (but UCS2 has [convert(CH_UCS2)]
|
||||
LIBNDR_FLAG_STR_FIXLEN15 -> [15]
|
||||
|
||||
- True multiple dimension array / strings in arrays support (closely related to
|
||||
things specified above)
|
||||
|
||||
- compatibility mode for generating MIDL-readable data:
|
||||
- strip out pidl-specific properties
|
||||
- convert subcontext() to an array of chars.
|
||||
- convert subcontext() to an array of uint8.
|
||||
|
@ -48,15 +48,20 @@ sub GetElementLevelTable($)
|
||||
my $is_surrounding = 0;
|
||||
my $is_varying = 0;
|
||||
my $is_conformant = 0;
|
||||
my $is_string = 0;
|
||||
|
||||
if ($d eq "*") {
|
||||
$is_conformant = 1;
|
||||
unless ($size = shift @size_is) {
|
||||
if ($size = shift @size_is) {
|
||||
} elsif ((scalar(@size_is) == 0) and util::has_property($e, "string")) {
|
||||
$is_string = 1;
|
||||
delete($e->{PROPERTIES}->{string});
|
||||
} else {
|
||||
print "$e->{FILE}:$e->{LINE}: Must specify size_is() for conformant array!\n";
|
||||
exit 1;
|
||||
}
|
||||
|
||||
if ($length = shift @length_is) {
|
||||
if (($length = shift @length_is) or $is_string) {
|
||||
$is_varying = 1;
|
||||
} else {
|
||||
$length = $size;
|
||||
@ -73,9 +78,8 @@ sub GetElementLevelTable($)
|
||||
SIZE_IS => $size,
|
||||
LENGTH_IS => $length,
|
||||
IS_DEFERRED => "$is_deferred",
|
||||
# Inline arrays (which are a pidl extension) are never encoded
|
||||
# as surrounding the struct they're part of
|
||||
IS_SURROUNDING => "$is_surrounding",
|
||||
IS_ZERO_TERMINATED => "$is_string",
|
||||
IS_VARYING => "$is_varying",
|
||||
IS_CONFORMANT => "$is_conformant",
|
||||
IS_FIXED => (not $is_conformant and util::is_constant($size)),
|
||||
@ -104,30 +108,43 @@ sub GetElementLevelTable($)
|
||||
# everything that follows will be deferred
|
||||
$is_deferred = 1 if ($e->{PARENT}->{TYPE} ne "FUNCTION");
|
||||
|
||||
my $array_size;
|
||||
my $array_size = shift @size_is;
|
||||
my $array_length;
|
||||
if ($array_size = shift @size_is) {
|
||||
my $is_varying = 0;
|
||||
my $is_varying;
|
||||
my $is_conformant;
|
||||
my $is_string = 0;
|
||||
if ($array_size) {
|
||||
$is_conformant = 1;
|
||||
if ($array_length = shift @length_is) {
|
||||
$is_varying = 1;
|
||||
} else {
|
||||
$array_length = $array_size;
|
||||
$is_varying =0;
|
||||
}
|
||||
}
|
||||
|
||||
if (scalar(@size_is) == 0 and util::has_property($e, "string")) {
|
||||
$is_string = 1;
|
||||
$is_varying = $is_conformant = util::has_property($e, "noheader")?0:1;
|
||||
delete($e->{PROPERTIES}->{string});
|
||||
}
|
||||
|
||||
if ($array_size or $is_string) {
|
||||
push (@$order, {
|
||||
TYPE => "ARRAY",
|
||||
IS_ZERO_TERMINATED => "$is_string",
|
||||
SIZE_IS => $array_size,
|
||||
LENGTH_IS => $array_length,
|
||||
IS_DEFERRED => "$is_deferred",
|
||||
IS_SURROUNDING => 0,
|
||||
IS_VARYING => "$is_varying",
|
||||
IS_CONFORMANT => 1,
|
||||
IS_CONFORMANT => "$is_conformant",
|
||||
IS_FIXED => 0,
|
||||
IS_INLINE => 0,
|
||||
});
|
||||
|
||||
$is_deferred = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (defined(util::has_property($e, "subcontext"))) {
|
||||
|
@ -237,8 +237,15 @@ sub ParseArrayPushHeader($$$$$)
|
||||
$var_name = get_pointer_to($var_name);
|
||||
}
|
||||
|
||||
my $size = ParseExpr($l->{SIZE_IS}, $env);
|
||||
my $length = ParseExpr($l->{LENGTH_IS}, $env);
|
||||
my $size;
|
||||
my $length;
|
||||
|
||||
if ($l->{IS_ZERO_TERMINATED}) {
|
||||
$size = $length = "ndr_string_length($var_name, sizeof(*$var_name))";
|
||||
} else {
|
||||
$size = ParseExpr($l->{SIZE_IS}, $env);
|
||||
$length = ParseExpr($l->{LENGTH_IS}, $env);
|
||||
}
|
||||
|
||||
if ((!$l->{IS_SURROUNDING}) and $l->{IS_CONFORMANT}) {
|
||||
pidl "NDR_CHECK(ndr_push_uint32($ndr, NDR_SCALARS, $size));";
|
||||
@ -262,17 +269,17 @@ sub ParseArrayPullHeader($$$$$)
|
||||
$var_name = get_pointer_to($var_name);
|
||||
}
|
||||
|
||||
# $var_name contains the name of the first argument here
|
||||
|
||||
my $length = ParseExpr($l->{SIZE_IS}, $env);
|
||||
my $size = $length;
|
||||
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))";
|
||||
} else {
|
||||
$length = $size = ParseExpr($l->{SIZE_IS}, $env);
|
||||
}
|
||||
|
||||
# if this is a conformant array then we use that size to allocate, and make sure
|
||||
# we allocate enough to pull the elements
|
||||
if ((!$l->{IS_SURROUNDING}) and $l->{IS_CONFORMANT}) {
|
||||
pidl "NDR_CHECK(ndr_pull_array_size(ndr, " . get_pointer_to($var_name) . "));";
|
||||
}
|
||||
@ -293,13 +300,13 @@ sub ParseArrayPullHeader($$$$$)
|
||||
pidl "}";
|
||||
}
|
||||
|
||||
if ($l->{IS_CONFORMANT}) {
|
||||
if ($l->{IS_CONFORMANT} and not $l->{IS_ZERO_TERMINATED}) {
|
||||
my $size = ParseExpr($l->{SIZE_IS}, $env);
|
||||
check_null_pointer($size);
|
||||
pidl "NDR_CHECK(ndr_check_array_size(ndr, (void*)" . get_pointer_to($var_name) . ", $size));";
|
||||
}
|
||||
|
||||
if ($l->{IS_VARYING}) {
|
||||
if ($l->{IS_VARYING} and not $l->{IS_ZERO_TERMINATED}) {
|
||||
my $length = ParseExpr($l->{LENGTH_IS}, $env);
|
||||
check_null_pointer($length);
|
||||
pidl "NDR_CHECK(ndr_check_array_length(ndr, (void*)" . get_pointer_to($var_name) . ", $length));";
|
||||
@ -541,7 +548,9 @@ sub ParseElementPushLevel
|
||||
$var_name = get_pointer_to($var_name);
|
||||
}
|
||||
|
||||
pidl "NDR_CHECK(ndr_push_array_$e->{TYPE}($ndr, $ndr_flags, $var_name, $length));";
|
||||
my $nl = Ndr::GetNextLevel($e, $l);
|
||||
|
||||
pidl "NDR_CHECK(ndr_push_array_$nl->{DATA_TYPE}($ndr, $ndr_flags, $var_name, $length));";
|
||||
return;
|
||||
}
|
||||
} elsif ($l->{TYPE} eq "SWITCH") {
|
||||
@ -666,13 +675,21 @@ sub ParseElementPrint($$$)
|
||||
}
|
||||
$var_name = get_value_of($var_name);
|
||||
} elsif ($l->{TYPE} eq "ARRAY") {
|
||||
my $length = ParseExpr($l->{LENGTH_IS}, $env);
|
||||
my $length;
|
||||
|
||||
if (is_scalar_array($e, $l) and ($l->{IS_CONFORMANT} or $l->{IS_VARYING})){
|
||||
$var_name = get_pointer_to($var_name);
|
||||
}
|
||||
|
||||
if ($l->{IS_ZERO_TERMINATED}) {
|
||||
$length = "ndr_string_length($var_name, sizeof(*$var_name))";
|
||||
} else {
|
||||
$length = ParseExpr($l->{LENGTH_IS}, $env);
|
||||
}
|
||||
|
||||
if (is_scalar_array($e, $l)) {
|
||||
if ($l->{IS_CONFORMANT} or $l->{IS_VARYING}){
|
||||
$var_name = get_pointer_to($var_name);
|
||||
}
|
||||
pidl "ndr_print_array_$e->{TYPE}(ndr, \"$e->{NAME}\", $var_name, $length);";
|
||||
my $nl = Ndr::GetNextLevel($e, $l);
|
||||
pidl "ndr_print_array_$nl->{DATA_TYPE}(ndr, \"$e->{NAME}\", $var_name, $length);";
|
||||
last;
|
||||
}
|
||||
|
||||
@ -825,8 +842,13 @@ sub ParseElementPullLevel
|
||||
if ($l->{IS_VARYING} or $l->{IS_CONFORMANT}) {
|
||||
$var_name = get_pointer_to($var_name);
|
||||
}
|
||||
my $nl = Ndr::GetNextLevel($e, $l);
|
||||
|
||||
pidl "NDR_CHECK(ndr_pull_array_$e->{TYPE}($ndr, $ndr_flags, $var_name, $length));";
|
||||
pidl "NDR_CHECK(ndr_pull_array_$nl->{DATA_TYPE}($ndr, $ndr_flags, $var_name, $length));";
|
||||
if ($l->{IS_ZERO_TERMINATED}) {
|
||||
# Make sure last element is zero!
|
||||
pidl "NDR_CHECK(ndr_check_string_terminator($ndr, $var_name, ndr_get_array_length(ndr, " . get_pointer_to($var_name) . "), sizeof(*$var_name)));";
|
||||
}
|
||||
return;
|
||||
}
|
||||
} elsif ($l->{TYPE} eq "POINTER") {
|
||||
@ -876,6 +898,11 @@ sub ParseElementPullLevel
|
||||
ParseElementPullLevel($e,Ndr::GetNextLevel($e,$l), $ndr, $var_name, $env, 1, 0);
|
||||
deindent;
|
||||
pidl "}";
|
||||
|
||||
if ($l->{IS_ZERO_TERMINATED}) {
|
||||
# Make sure last element is zero!
|
||||
pidl "NDR_CHECK(ndr_check_string_terminator($ndr, $var_name, ndr_get_array_length(ndr, " . get_pointer_to($var_name) . "), sizeof(*$var_name)));";
|
||||
}
|
||||
}
|
||||
|
||||
if ($deferred and Ndr::ContainsDeferred($e, $l)) {
|
||||
@ -1846,14 +1873,15 @@ sub AllocateArrayLevel($$$$$)
|
||||
my $pl = Ndr::GetPrevLevel($e, $l);
|
||||
if (defined($pl) and
|
||||
$pl->{TYPE} eq "POINTER" and
|
||||
$pl->{POINTER_TYPE} eq "ref") {
|
||||
$pl->{POINTER_TYPE} eq "ref"
|
||||
and not $l->{IS_ZERO_TERMINATED}) {
|
||||
pidl "if (ndr->flags & LIBNDR_FLAG_REF_ALLOC) {";
|
||||
pidl "\tNDR_ALLOC_N($ndr, $var, $size);";
|
||||
pidl "}";
|
||||
} else {
|
||||
pidl "NDR_ALLOC_N($ndr, $var, $size);";
|
||||
}
|
||||
#pidl "memset($var, 0, $size * sizeof(" . $var . "[0]));";
|
||||
|
||||
if (grep(/in/,@{$e->{DIRECTION}}) and
|
||||
grep(/out/,@{$e->{DIRECTION}})) {
|
||||
pidl "memcpy(r->out.$e->{NAME},r->in.$e->{NAME},$size * sizeof(*r->in.$e->{NAME}));";
|
||||
@ -1909,6 +1937,8 @@ sub ParseFunctionPull($)
|
||||
$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 "ARRAY")
|
||||
and $e->{LEVELS}[1]->{IS_ZERO_TERMINATED});
|
||||
|
||||
if ($e->{LEVELS}[1]->{TYPE} eq "ARRAY") {
|
||||
my $size = ParseExpr($e->{LEVELS}[1]->{SIZE_IS}, $env);
|
||||
|
@ -131,6 +131,7 @@ my %property_list = (
|
||||
"range" => ["ELEMENT"],
|
||||
"size_is" => ["ELEMENT"],
|
||||
"string" => ["ELEMENT"],
|
||||
"noheader" => ["ELEMENT"],
|
||||
"charset" => ["ELEMENT"],
|
||||
"length_is" => ["ELEMENT"],
|
||||
);
|
||||
|
@ -569,3 +569,30 @@ void ndr_print_string_array(struct ndr_print *ndr, const char *name, const char
|
||||
}
|
||||
ndr->depth--;
|
||||
}
|
||||
|
||||
/* Return number of elements in a string including the last (zeroed) element */
|
||||
uint32_t ndr_string_length(void *_var, uint32_t element_size)
|
||||
{
|
||||
uint32_t i;
|
||||
uint8_t zero[4] = {0,0,0,0};
|
||||
char *var = _var;
|
||||
|
||||
for (i = 0; memcmp(var+i*element_size,zero,element_size) != 0; i++);
|
||||
|
||||
return i+1;
|
||||
}
|
||||
|
||||
NTSTATUS ndr_check_string_terminator(struct ndr_pull *ndr, const void *_var, uint32_t count, uint32_t element_size)
|
||||
{
|
||||
const char *var = _var;
|
||||
uint32_t i;
|
||||
|
||||
for (i = 0; i < element_size; i++) {
|
||||
if (var+element_size*(count-1)+i != 0) {
|
||||
return NT_STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
}
|
||||
|
||||
return NT_STATUS_OK;
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user