Rev 11553: Fix Needed* for nested datastructures. in file:///home/jelmer/bzr.samba/SAMBA_4_0/

Jelmer Vernooij jelmer at samba.org
Tue Feb 20 23:35:01 GMT 2007


At file:///home/jelmer/bzr.samba/SAMBA_4_0/

------------------------------------------------------------
revno: 11553
revision-id: jelmer at samba.org-20070220233449-wfnj0vjg0gp9eeqz
parent: svn-v2:21477 at 0c0555d6-39d7-0310-84fc-f1cc0bd64818-branches%2fSAMBA_4_0
committer: Jelmer Vernooij <jelmer at samba.org>
branch nick: SAMBA_4_0
timestamp: Wed 2007-02-21 00:34:49 +0100
message:
  Fix Needed* for nested datastructures.
modified:
  source/pidl/lib/Parse/Pidl/NDR.pm svn-v2:9460 at 0c0555d6-39d7-0310-84fc-f1cc0bd64818-branches%2fSAMBA_4_0-source%2fpidl%2flib%2fParse%2fPidl%2fNDR.pm
  source/pidl/lib/Parse/Pidl/Samba4/EJS.pm svn-v2:12463 at 0c0555d6-39d7-0310-84fc-f1cc0bd64818-branches%2fSAMBA_4_0-source%2fpidl%2flib%2fParse%2fPidl%2fSamba4%2fEJS.pm
  source/pidl/lib/Parse/Pidl/Samba4/NDR/Parser.pm svn-v2:12463 at 0c0555d6-39d7-0310-84fc-f1cc0bd64818-branches%2fSAMBA_4_0-source%2fpidl%2flib%2fParse%2fPidl%2fSamba4%2fNDR%2fParser.pm
  source/pidl/tests/samba-ndr.pl svn-v2:20637 at 0c0555d6-39d7-0310-84fc-f1cc0bd64818-branches%2fSAMBA_4_0-source%2fpidl%2ftests%2fsamba%2dndr.pl
=== modified file 'source/pidl/lib/Parse/Pidl/NDR.pm'
--- a/source/pidl/lib/Parse/Pidl/NDR.pm	2007-02-19 22:10:23 +0000
+++ b/source/pidl/lib/Parse/Pidl/NDR.pm	2007-02-20 23:34:49 +0000
@@ -588,6 +588,21 @@
 	}
 }
 
+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 @@
 			push (@consts, ParseConst($idl, $d));
 		} else {
 			push (@types, ParseType($d, $idl->{PROPERTIES}->{pointer_default}));
+			FindNestedTypes(\@types, $d);
 		}
 	}
 

=== modified file 'source/pidl/lib/Parse/Pidl/Samba4/EJS.pm'
--- a/source/pidl/lib/Parse/Pidl/Samba4/EJS.pm	2007-02-18 18:44:56 +0000
+++ b/source/pidl/lib/Parse/Pidl/Samba4/EJS.pm	2007-02-20 23:34:49 +0000
@@ -8,7 +8,8 @@
 
 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 @@
 	$tabs = substr($tabs, 0, -1);
 }
 
-# this should probably be in ndr.pm
 sub GenerateStructEnv($)
 {
 	my $x = shift;
@@ -177,7 +177,7 @@
 	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 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 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 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 @@
 # 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 @@
 # 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 @@
 # 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 @@
 		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 @@
 # 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 @@
 # 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 @@
 {
 	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 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 @@
 	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 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 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 @@
 # 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 @@
 # 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 @@
 # 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 @@
 		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 @@
 # 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 @@
 # 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";

=== modified file 'source/pidl/lib/Parse/Pidl/Samba4/NDR/Parser.pm'
--- a/source/pidl/lib/Parse/Pidl/Samba4/NDR/Parser.pm	2007-02-20 01:27:48 +0000
+++ b/source/pidl/lib/Parse/Pidl/Samba4/NDR/Parser.pm	2007-02-20 23:34:49 +0000
@@ -12,7 +12,7 @@
 @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 @@
 
 	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 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;
-	}
-
-	if ($t->{DATA}->{TYPE} eq "STRUCT" or $t->{DATA}->{TYPE} eq "UNION") {
-		if (has_property($t, "gensize")) {
-			$needed->{"ndr_size_$t->{NAME}"} = 1;
-		}
-
-		for my $e (@{$t->{DATA}->{ELEMENTS}}) {
-			$e->{PARENT} = $t->{DATA};
+	sub NeededType($$$);
+	my ($t,$needed,$req) = @_;
+
+	NeededType($t->{DATA}, $needed, $req) if ($t->{TYPE} eq "TYPEDEF");
+
+	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 @@
 {
 	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;

=== modified file 'source/pidl/tests/samba-ndr.pl'
--- a/source/pidl/tests/samba-ndr.pl	2007-02-20 01:27:48 +0000
+++ b/source/pidl/tests/samba-ndr.pl	2007-02-20 23:34:49 +0000
@@ -11,7 +11,8 @@
 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 @@
 
 # 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});



More information about the samba-cvs mailing list