From ec3c9ebfd0de287411ce399967409f902653d5c6 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Wed, 21 Feb 2007 10:31:14 +0000 Subject: [PATCH] r21484: Fix Needed* for nested datastructures. --- source/pidl/lib/Parse/Pidl/NDR.pm | 16 ++++++ source/pidl/lib/Parse/Pidl/Samba4/EJS.pm | 76 +++++++++++-------------- source/pidl/lib/Parse/Pidl/Samba4/NDR/Parser.pm | 70 +++++++++++++++-------- source/pidl/tests/samba-ndr.pl | 38 +++++++------ 4 files changed, 115 insertions(+), 85 deletions(-) diff --git a/source/pidl/lib/Parse/Pidl/NDR.pm b/source/pidl/lib/Parse/Pidl/NDR.pm index a921e5cbe50..7322856cdd7 100644 --- a/source/pidl/lib/Parse/Pidl/NDR.pm +++ b/source/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/source/pidl/lib/Parse/Pidl/Samba4/EJS.pm b/source/pidl/lib/Parse/Pidl/Samba4/EJS.pm index 59dc5f001d2..13a8460a810 100644 --- a/source/pidl/lib/Parse/Pidl/Samba4/EJS.pm +++ b/source/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/source/pidl/lib/Parse/Pidl/Samba4/NDR/Parser.pm b/source/pidl/lib/Parse/Pidl/Samba4/NDR/Parser.pm index 45662790095..2ae4a3b17ef 100644 --- a/source/pidl/lib/Parse/Pidl/Samba4/NDR/Parser.pm +++ b/source/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/source/pidl/tests/samba-ndr.pl b/source/pidl/tests/samba-ndr.pl index 1167f77aeee..d956402e64c 100755 --- a/source/pidl/tests/samba-ndr.pl +++ b/source/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}); -- 2.11.4.GIT