summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJelmer Vernooij <jelmer@samba.org>2007-02-21 10:31:14 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 14:48:41 -0500
commit90789cb08b84d3b916df3ed11fa9c68dd3075600 (patch)
tree2019a692662d5748079a92dab4db72bd936a3099
parent9f420a6c6d10f76e923881e768ed42eb918e2d52 (diff)
downloadsamba-90789cb08b84d3b916df3ed11fa9c68dd3075600.tar.gz
samba-90789cb08b84d3b916df3ed11fa9c68dd3075600.tar.bz2
samba-90789cb08b84d3b916df3ed11fa9c68dd3075600.zip
r21484: Fix Needed* for nested datastructures.
(This used to be commit ec3c9ebfd0de287411ce399967409f902653d5c6)
-rw-r--r--source4/pidl/lib/Parse/Pidl/NDR.pm16
-rw-r--r--source4/pidl/lib/Parse/Pidl/Samba4/EJS.pm76
-rw-r--r--source4/pidl/lib/Parse/Pidl/Samba4/NDR/Parser.pm70
-rwxr-xr-xsource4/pidl/tests/samba-ndr.pl38
4 files changed, 115 insertions, 85 deletions
diff --git a/source4/pidl/lib/Parse/Pidl/NDR.pm b/source4/pidl/lib/Parse/Pidl/NDR.pm
index a921e5cbe5..7322856cdd 100644
--- a/source4/pidl/lib/Parse/Pidl/NDR.pm
+++ b/source4/pidl/lib/Parse/Pidl/NDR.pm
@@ -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);
}
}
diff --git a/source4/pidl/lib/Parse/Pidl/Samba4/EJS.pm b/source4/pidl/lib/Parse/Pidl/Samba4/EJS.pm
index 59dc5f001d..13a8460a81 100644
--- a/source4/pidl/lib/Parse/Pidl/Samba4/EJS.pm
+++ b/source4/pidl/lib/Parse/Pidl/Samba4/EJS.pm
@@ -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";
diff --git a/source4/pidl/lib/Parse/Pidl/Samba4/NDR/Parser.pm b/source4/pidl/lib/Parse/Pidl/Samba4/NDR/Parser.pm
index 4566279009..2ae4a3b17e 100644
--- a/source4/pidl/lib/Parse/Pidl/Samba4/NDR/Parser.pm
+++ b/source4/pidl/lib/Parse/Pidl/Samba4/NDR/Parser.pm
@@ -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;
diff --git a/source4/pidl/tests/samba-ndr.pl b/source4/pidl/tests/samba-ndr.pl
index 1167f77aee..d956402e64 100755
--- a/source4/pidl/tests/samba-ndr.pl
+++ b/source4/pidl/tests/samba-ndr.pl
@@ -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});