1
0
mirror of https://github.com/samba-team/samba.git synced 2024-12-28 07:21:54 +03:00

r21484: Fix Needed* for nested datastructures.

This commit is contained in:
Jelmer Vernooij 2007-02-21 10:31:14 +00:00 committed by Gerald (Jerry) Carter
parent 17d1da1947
commit ec3c9ebfd0
4 changed files with 115 additions and 85 deletions

View File

@ -588,6 +588,21 @@ sub CheckPointerTypes($$)
}
}
sub FindNestedTypes($$)
{
sub FindNestedTypes($$);
my ($l, $t) = @_;
return if not defined($t->{ELEMENTS});
foreach (@{$t->{ELEMENTS}}) {
if (ref($_->{TYPE}) eq "HASH") {
push (@$l, $_->{TYPE}) if (defined($_->{TYPE}->{NAME}));
FindNestedTypes($l, $_->{TYPE});
}
}
}
sub ParseInterface($)
{
my $idl = shift;
@ -620,6 +635,7 @@ sub ParseInterface($)
push (@consts, ParseConst($idl, $d));
} else {
push (@types, ParseType($d, $idl->{PROPERTIES}->{pointer_default}));
FindNestedTypes(\@types, $d);
}
}

View File

@ -8,7 +8,8 @@ package Parse::Pidl::Samba4::EJS;
use strict;
use Parse::Pidl::Typelist;
use Parse::Pidl::Util qw(has_property);
use Parse::Pidl::Util qw(has_property ParseExpr);
use Parse::Pidl::NDR qw(GetPrevLevel GetNextLevel);
use vars qw($VERSION);
$VERSION = '0.01';
@ -45,7 +46,6 @@ sub deindent()
$tabs = substr($tabs, 0, -1);
}
# this should probably be in ndr.pm
sub GenerateStructEnv($)
{
my $x = shift;
@ -177,7 +177,7 @@ sub EjsPullPointer($$$$$)
indent;
pidl "EJS_ALLOC(ejs, $var);";
$var = get_value_of($var);
EjsPullElement($e, Parse::Pidl::NDR::GetNextLevel($e, $l), $var, $name, $env);
EjsPullElement($e, GetNextLevel($e, $l), $var, $name, $env);
deindent;
pidl "}";
}
@ -187,7 +187,7 @@ sub EjsPullPointer($$$$$)
sub EjsPullString($$$$$)
{
my ($e, $l, $var, $name, $env) = @_;
my $pl = Parse::Pidl::NDR::GetPrevLevel($e, $l);
my $pl = GetPrevLevel($e, $l);
$var = get_pointer_to($var);
if (defined($pl) and $pl->{TYPE} eq "POINTER") {
$var = get_pointer_to($var);
@ -201,10 +201,10 @@ sub EjsPullString($$$$$)
sub EjsPullArray($$$$$)
{
my ($e, $l, $var, $name, $env) = @_;
my $nl = Parse::Pidl::NDR::GetNextLevel($e, $l);
my $length = Parse::Pidl::Util::ParseExpr($l->{LENGTH_IS}, $env, $e);
my $size = Parse::Pidl::Util::ParseExpr($l->{SIZE_IS}, $env, $e);
my $pl = Parse::Pidl::NDR::GetPrevLevel($e, $l);
my $nl = GetNextLevel($e, $l);
my $length = ParseExpr($l->{LENGTH_IS}, $env, $e);
my $size = ParseExpr($l->{SIZE_IS}, $env, $e);
my $pl = GetPrevLevel($e, $l);
if ($pl && $pl->{TYPE} eq "POINTER") {
$var = get_pointer_to($var);
}
@ -242,9 +242,9 @@ sub EjsPullArray($$$$$)
sub EjsPullSwitch($$$$$)
{
my ($e, $l, $var, $name, $env) = @_;
my $switch_var = Parse::Pidl::Util::ParseExpr($l->{SWITCH_IS}, $env, $e);
my $switch_var = ParseExpr($l->{SWITCH_IS}, $env, $e);
pidl "ejs_set_switch(ejs, $switch_var);";
EjsPullElement($e, Parse::Pidl::NDR::GetNextLevel($e, $l), $var, $name, $env);
EjsPullElement($e, GetNextLevel($e, $l), $var, $name, $env);
}
###########################
@ -271,10 +271,9 @@ sub EjsPullElement($$$$$)
# pull a structure/union element at top level
sub EjsPullElementTop($$)
{
my $e = shift;
my $env = shift;
my ($e, $env) = @_;
my $l = $e->{LEVELS}[0];
my $var = Parse::Pidl::Util::ParseExpr($e->{NAME}, $env, $e);
my $var = ParseExpr($e->{NAME}, $env, $e);
my $name = "\"$e->{NAME}\"";
EjsPullElement($e, $l, $var, $name, $env);
}
@ -283,8 +282,7 @@ sub EjsPullElementTop($$)
# pull a struct
sub EjsStructPull($$)
{
my $name = shift;
my $d = shift;
my ($name, $d) = @_;
my $env = GenerateStructEnv($d);
fn_declare($d, "NTSTATUS ejs_pull_$name(struct ejs_rpc *ejs, struct MprVar *v, const char *name, struct $name *r)");
pidl "{";
@ -302,10 +300,8 @@ sub EjsStructPull($$)
# pull a union
sub EjsUnionPull($$)
{
my $name = shift;
my $d = shift;
my ($name, $d) = @_;
my $have_default = 0;
my $env = GenerateStructEnv($d);
fn_declare($d, "NTSTATUS ejs_pull_$name(struct ejs_rpc *ejs, struct MprVar *v, const char *name, union $name *r)");
pidl "{";
indent;
@ -319,7 +315,7 @@ sub EjsUnionPull($$)
pidl "$e->{CASE}:";
indent;
if ($e->{TYPE} ne "EMPTY") {
EjsPullElementTop($e, $env);
EjsPullElementTop($e, { $e->{NAME} => "r->$e->{NAME}"});
}
pidl "break;";
deindent;
@ -359,8 +355,7 @@ sub EjsEnumConstant($)
# pull a enum
sub EjsEnumPull($$)
{
my $name = shift;
my $d = shift;
my ($name, $d) = @_;
EjsEnumConstant($d);
fn_declare($d, "NTSTATUS ejs_pull_$name(struct ejs_rpc *ejs, struct MprVar *v, const char *name, enum $name *r)");
pidl "{";
@ -377,8 +372,7 @@ sub EjsEnumPull($$)
# pull a bitmap
sub EjsBitmapPull($$)
{
my $name = shift;
my $d = shift;
my ($name, $d) = @_;
my $type_fn = $d->{BASE_TYPE};
my($type_decl) = Parse::Pidl::Typelist::mapTypeName($d->{BASE_TYPE});
fn_declare($d, "NTSTATUS ejs_pull_$name(struct ejs_rpc *ejs, struct MprVar *v, const char *name, $type_decl *r)");
@ -449,7 +443,7 @@ sub EjsPushScalar($$$$$)
{
my ($e, $l, $var, $name, $env) = @_;
# have to handle strings specially :(
my $pl = Parse::Pidl::NDR::GetPrevLevel($e, $l);
my $pl = GetPrevLevel($e, $l);
if ((not Parse::Pidl::Typelist::scalar_is_reference($e->{TYPE}))
or (defined($pl) and $pl->{TYPE} eq "POINTER")) {
@ -463,7 +457,7 @@ sub EjsPushScalar($$$$$)
sub EjsPushString($$$$$)
{
my ($e, $l, $var, $name, $env) = @_;
my $pl = Parse::Pidl::NDR::GetPrevLevel($e, $l);
my $pl = GetPrevLevel($e, $l);
if (defined($pl) and $pl->{TYPE} eq "POINTER") {
$var = get_pointer_to($var);
}
@ -486,7 +480,7 @@ sub EjsPushPointer($$$$$)
pidl "} else {";
indent;
$var = get_value_of($var);
EjsPushElement($e, Parse::Pidl::NDR::GetNextLevel($e, $l), $var, $name, $env);
EjsPushElement($e, GetNextLevel($e, $l), $var, $name, $env);
deindent;
pidl "}";
}
@ -496,9 +490,9 @@ sub EjsPushPointer($$$$$)
sub EjsPushSwitch($$$$$)
{
my ($e, $l, $var, $name, $env) = @_;
my $switch_var = Parse::Pidl::Util::ParseExpr($l->{SWITCH_IS}, $env, $e);
my $switch_var = ParseExpr($l->{SWITCH_IS}, $env, $e);
pidl "ejs_set_switch(ejs, $switch_var);";
EjsPushElement($e, Parse::Pidl::NDR::GetNextLevel($e, $l), $var, $name, $env);
EjsPushElement($e, GetNextLevel($e, $l), $var, $name, $env);
}
@ -507,9 +501,9 @@ sub EjsPushSwitch($$$$$)
sub EjsPushArray($$$$$)
{
my ($e, $l, $var, $name, $env) = @_;
my $nl = Parse::Pidl::NDR::GetNextLevel($e, $l);
my $length = Parse::Pidl::Util::ParseExpr($l->{LENGTH_IS}, $env, $e);
my $pl = Parse::Pidl::NDR::GetPrevLevel($e, $l);
my $nl = GetNextLevel($e, $l);
my $length = ParseExpr($l->{LENGTH_IS}, $env, $e);
my $pl = GetPrevLevel($e, $l);
if ($pl && $pl->{TYPE} eq "POINTER") {
$var = get_pointer_to($var);
}
@ -558,10 +552,9 @@ sub EjsPushElement($$$$$)
# push a structure/union element at top level
sub EjsPushElementTop($$)
{
my $e = shift;
my $env = shift;
my ($e, $env) = @_;
my $l = $e->{LEVELS}[0];
my $var = Parse::Pidl::Util::ParseExpr($e->{NAME}, $env, $e);
my $var = ParseExpr($e->{NAME}, $env, $e);
my $name = "\"$e->{NAME}\"";
EjsPushElement($e, $l, $var, $name, $env);
}
@ -570,8 +563,7 @@ sub EjsPushElementTop($$)
# push a struct
sub EjsStructPush($$)
{
my $name = shift;
my $d = shift;
my ($name, $d) = @_;
my $env = GenerateStructEnv($d);
fn_declare($d, "NTSTATUS ejs_push_$name(struct ejs_rpc *ejs, struct MprVar *v, const char *name, const struct $name *r)");
pidl "{";
@ -589,10 +581,8 @@ sub EjsStructPush($$)
# push a union
sub EjsUnionPush($$)
{
my $name = shift;
my $d = shift;
my ($name, $d) = @_;
my $have_default = 0;
my $env = GenerateStructEnv($d);
fn_declare($d, "NTSTATUS ejs_push_$name(struct ejs_rpc *ejs, struct MprVar *v, const char *name, const union $name *r)");
pidl "{";
indent;
@ -606,7 +596,7 @@ sub EjsUnionPush($$)
pidl "$e->{CASE}:";
indent;
if ($e->{TYPE} ne "EMPTY") {
EjsPushElementTop($e, $env);
EjsPushElementTop($e, { $e->{NAME} => "r->$e->{NAME}"} );
}
pidl "break;";
deindent;
@ -645,8 +635,7 @@ sub EjsEnumPush($$)
# push a bitmap
sub EjsBitmapPush($$)
{
my $name = shift;
my $d = shift;
my ($name, $d) = @_;
my $type_fn = $d->{BASE_TYPE};
my($type_decl) = Parse::Pidl::Typelist::mapTypeName($d->{BASE_TYPE});
# put the bitmap elements in the constants array
@ -719,8 +708,7 @@ sub EjsPushFunction($)
# generate a ejs mapping function
sub EjsFunction($$)
{
my $d = shift;
my $iface = shift;
my ($d, $iface) = @_;
my $name = $d->{NAME};
my $callnum = uc("DCERPC_$name");
my $table = "&dcerpc_table_$iface";

View File

@ -12,7 +12,7 @@ require Exporter;
@EXPORT = qw(is_charset_array);
@EXPORT_OK = qw(check_null_pointer GenerateFunctionInEnv
GenerateFunctionOutEnv EnvSubstituteValue GenerateStructEnv NeededFunction
NeededElement NeededType $res);
NeededElement NeededType $res NeededInterface);
use strict;
use Parse::Pidl::Typelist qw(hasType getType mapTypeName);
@ -2651,17 +2651,32 @@ sub NeededElement($$$)
return if ($e->{TYPE} eq "EMPTY");
my ($t, $rt);
if (ref($e->{TYPE}) eq "HASH") {
$t = $e->{TYPE}->{TYPE}."_".$e->{TYPE}->{NAME};
} else {
$t = $e->{TYPE};
}
if (ref($e->{REPRESENTATION_TYPE}) eq "HASH") {
$rt = $e->{REPRESENTATION_TYPE}->{TYPE}."_".$e->{REPRESENTATION_TYPE}->{NAME};
} else {
$rt = $e->{REPRESENTATION_TYPE};
}
die ("$e->{NAME} $t, $rt FOO") unless ($rt ne "");
my @fn = ();
if ($dir eq "print") {
push(@fn, "print_$e->{REPRESENTATION_TYPE}");
push(@fn, "print_$rt");
} elsif ($dir eq "pull") {
push (@fn, "pull_$e->{TYPE}");
push (@fn, "ndr_$e->{TYPE}_to_$e->{REPRESENTATION_TYPE}")
if ($e->{REPRESENTATION_TYPE} ne $e->{TYPE});
push (@fn, "pull_$t");
push (@fn, "ndr_$t\_to_$rt")
if ($rt ne $t);
} elsif ($dir eq "push") {
push (@fn, "push_$e->{TYPE}");
push (@fn, "ndr_$e->{REPRESENTATION_TYPE}_to_$e->{TYPE}")
if ($e->{REPRESENTATION_TYPE} ne $e->{TYPE});
push (@fn, "push_$t");
push (@fn, "ndr_$rt\_to_$t")
if ($rt ne $t);
} else {
die("invalid direction `$dir'");
}
@ -2685,28 +2700,21 @@ sub NeededFunction($$)
}
}
sub NeededType($$)
sub NeededType($$$)
{
my ($t,$needed) = @_;
if (has_property($t, "public")) {
$needed->{"pull_$t->{NAME}"} = 1;
$needed->{"push_$t->{NAME}"} = 1;
$needed->{"print_$t->{NAME}"} = 1;
}
sub NeededType($$$);
my ($t,$needed,$req) = @_;
if ($t->{DATA}->{TYPE} eq "STRUCT" or $t->{DATA}->{TYPE} eq "UNION") {
if (has_property($t, "gensize")) {
$needed->{"ndr_size_$t->{NAME}"} = 1;
}
NeededType($t->{DATA}, $needed, $req) if ($t->{TYPE} eq "TYPEDEF");
for my $e (@{$t->{DATA}->{ELEMENTS}}) {
$e->{PARENT} = $t->{DATA};
if ($t->{TYPE} eq "STRUCT" or $t->{TYPE} eq "UNION") {
for my $e (@{$t->{ELEMENTS}}) {
$e->{PARENT} = $t;
if (has_property($e, "compression")) {
$needed->{"compression"} = 1;
}
NeededElement($e, "pull", $needed) if ($needed->{"pull_$t->{NAME}"});
NeededElement($e, "push", $needed) if ($needed->{"push_$t->{NAME}"});
NeededElement($e, "print", $needed) if ($needed->{"print_$t->{NAME}"});
NeededElement($e, $req, $needed);
NeededType($e->{TYPE}, $needed, $req) if (ref($e->{TYPE}) eq "HASH");
}
}
}
@ -2717,7 +2725,19 @@ sub NeededInterface($$)
{
my ($interface,$needed) = @_;
NeededFunction($_, $needed) foreach (@{$interface->{FUNCTIONS}});
NeededType($_, $needed) foreach (reverse @{$interface->{TYPES}});
foreach (reverse @{$interface->{TYPES}}) {
if (has_property($_, "public")) {
$needed->{"pull\_$_->{NAME}"} = $needed->{"push\_$_->{NAME}"} =
$needed->{"print\_$_->{NAME}"} = 1;
}
NeededType($_, $needed, "pull") if ($needed->{"pull_$_->{NAME}"});
NeededType($_, $needed, "push") if ($needed->{"push_$_->{NAME}"});
NeededType($_, $needed, "print") if ($needed->{"print_$_->{NAME}"});
if (has_property($_, "gensize")) {
$needed->{"ndr_size_$_->{NAME}"} = 1;
}
}
}
1;

View File

@ -11,7 +11,8 @@ use Util;
use Parse::Pidl::Util qw(MyDumper);
use Parse::Pidl::Samba4::NDR::Parser qw(check_null_pointer
GenerateFunctionInEnv GenerateFunctionOutEnv GenerateStructEnv
EnvSubstituteValue NeededFunction NeededElement NeededType $res);
EnvSubstituteValue NeededFunction NeededElement NeededType $res
NeededInterface);
my $output;
sub print_fn($) { my $x = shift; $output.=$x; }
@ -209,46 +210,51 @@ is_deeply($needed, { pull_foo => 1, print_foo => 1, push_foo => 1,
# public structs are always needed
$needed = {};
NeededType({ NAME => "bla", DATA => { TYPE => "STRUCT", ELEMENTS => [] } },
$needed);
NeededType({ NAME => "bla", TYPE => "TYPEDEF",
DATA => { TYPE => "STRUCT", ELEMENTS => [] } },
$needed, "pull");
is_deeply($needed, { });
$needed = {};
NeededType({ PROPERTIES => { public => 1 }, NAME => "bla",
DATA => { TYPE => "STRUCT", ELEMENTS => [] } },
NeededInterface({ TYPES => [ { PROPERTIES => { public => 1 }, NAME => "bla",
TYPE => "TYPEDEF",
DATA => { TYPE => "STRUCT", ELEMENTS => [] } } ] },
$needed);
is_deeply($needed, { pull_bla => 1, print_bla => 1, push_bla => 1 });
is_deeply($needed, { pull_bla => 1, push_bla => 1, print_bla => 1 });
# make sure types for elements are set too
$needed = {};
NeededType({ PROPERTIES => { public => 1 }, NAME => "bla",
NeededInterface({ TYPES => [ { PROPERTIES => { public => 1 }, NAME => "bla",
TYPE => "TYPEDEF",
DATA => { TYPE => "STRUCT",
ELEMENTS => [ { TYPE => "bar", REPRESENTATION_TYPE => "bar" } ] } },
ELEMENTS => [ { TYPE => "bar", REPRESENTATION_TYPE => "bar" } ] } } ] },
$needed);
is_deeply($needed, { pull_bla => 1, print_bla => 1, push_bla => 1,
pull_bar => 1, print_bar => 1, push_bar => 1});
is_deeply($needed, { pull_bla => 1, pull_bar => 1, push_bla => 1, push_bar => 1,
print_bla => 1, print_bar => 1});
$needed = {};
NeededType({ PROPERTIES => { gensize => 1}, NAME => "bla",
NeededInterface({ TYPES => [ { PROPERTIES => { gensize => 1}, NAME => "bla",
TYPE => "TYPEDEF",
DATA => { TYPE => "STRUCT",
ELEMENTS => [ { TYPE => "bar", REPRESENTATION_TYPE => "bar" } ] } },
ELEMENTS => [ { TYPE => "bar", REPRESENTATION_TYPE => "bar" } ] } } ] },
$needed);
is_deeply($needed, { ndr_size_bla => 1 });
# make sure types for elements are set too
$needed = { pull_bla => 1 };
NeededType({ NAME => "bla",
TYPE => "TYPEDEF",
DATA => { TYPE => "STRUCT",
ELEMENTS => [ { TYPE => "bar", REPRESENTATION_TYPE => "bar" } ] } },
$needed);
$needed, "pull");
is_deeply($needed, { pull_bla => 1, pull_bar => 1 });
$needed = {};
NeededType({ PROPERTIES => { public => 1},
NeededInterface({ TYPES => [ { PROPERTIES => { public => 1},
NAME => "bla",
TYPE => "TYPEDEF",
DATA => { TYPE => "STRUCT",
ELEMENTS => [ { TYPE => "bar", REPRESENTATION_TYPE => "rep" } ] } },
$needed);
ELEMENTS => [ { TYPE => "bar", REPRESENTATION_TYPE => "rep" } ] } } ] }, $needed);
is_deeply($needed, { pull_bla => 1, push_bla => 1, print_bla => 1, print_rep => 1,
pull_bar => 1, push_bar => 1,
ndr_bar_to_rep => 1, ndr_rep_to_bar => 1});