r21484: Fix Needed* for nested datastructures.
authorJelmer Vernooij <jelmer@samba.org>
Wed, 21 Feb 2007 10:31:14 +0000 (10:31 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 19:48:41 +0000 (14:48 -0500)
(This used to be commit ec3c9ebfd0de287411ce399967409f902653d5c6)

source4/pidl/lib/Parse/Pidl/NDR.pm
source4/pidl/lib/Parse/Pidl/Samba4/EJS.pm
source4/pidl/lib/Parse/Pidl/Samba4/NDR/Parser.pm
source4/pidl/tests/samba-ndr.pl

index a921e5cbe5018112593a2ccbdafbd9b22aa8b351..7322856cdd771e5c721460b265e723c82a5f5ce1 100644 (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);
                }
        }
 
index 59dc5f001d2e6a53631e8e1b533273d9b32979e2..13a8460a810b9eff46645d61cb3e412a90009a90 100644 (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";
index 4566279009527a89152c49eb19697dfd011a1696..2ae4a3b17ef9752b04724f58f708695b0f60c7a5 100644 (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;
index 1167f77aeeee45a44c65e6c780e5d59706cce747..d956402e64c5eeeed9a5e4645ae797a546d896a4 100755 (executable)
@@ -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});