r10742: Support multi-level pointers + ref pointer fixes
authorJelmer Vernooij <jelmer@samba.org>
Wed, 5 Oct 2005 22:18:59 +0000 (22:18 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 18:39:26 +0000 (13:39 -0500)
(This used to be commit 258b762dc62b257f99d1d859c5a3d850aba3e9fa)

source4/pidl/lib/Parse/Pidl/NDR.pm
source4/pidl/lib/Parse/Pidl/Samba3/Client.pm
source4/pidl/lib/Parse/Pidl/Samba3/Header.pm
source4/pidl/lib/Parse/Pidl/Samba3/Parser.pm

index 6bb92a3b504166262157e1e6745b6902d5835587..64190e87b81b0f10ab1528e486d37d701b2c90d3 100644 (file)
@@ -80,6 +80,7 @@ sub GetElementLevelTable($)
        my @bracket_array = ();
        my @length_is = ();
        my @size_is = ();
+       my $pointer_idx = 0;
 
        if (has_property($e, "size_is")) {
                @size_is = split /,/, has_property($e, "size_is");
@@ -153,9 +154,12 @@ sub GetElementLevelTable($)
                        TYPE => "POINTER",
                        # for now, there can only be one pointer type per element
                        POINTER_TYPE => pointer_type($e),
+                       POINTER_INDEX => $pointer_idx,
                        IS_DEFERRED => "$is_deferred",
                        LEVEL => $level
                });
+
+               $pointer_idx++;
                
                # everything that follows will be deferred
                $is_deferred = 1 if ($e->{PARENT}->{TYPE} ne "FUNCTION");
index b48a1b519fd13be59eb9dc1f76da3aa89d15853b..164f53d06bae3ecd301c80d45ff89dc540d37559 100644 (file)
@@ -20,6 +20,28 @@ sub indent() { $tabs.="\t"; }
 sub deindent() { $tabs = substr($tabs, 1); }
 sub pidl($) { $res .= $tabs.(shift)."\n"; }
 sub fatal($$) { my ($e,$s) = @_; die("$e->{FILE}:$e->{LINE}: $s\n"); }
+sub warning($$) { my ($e,$s) = @_; warn("$e->{FILE}:$e->{LINE}: $s\n"); }
+
+sub CopyLevel($$$$)
+{
+       sub CopyLevel($$$$);
+       my ($e,$l,$argument,$member) = @_;
+
+       if ($l->{TYPE} eq "DATA") {
+               pidl "*$argument = $member;";
+       } elsif ($l->{TYPE} eq "POINTER") {
+               pidl "if (r.ptr$l->{POINTER_INDEX}_$e->{NAME}) {";
+               indent;
+               pidl "*$argument = talloc_size(mem_ctx, sizeof(void *));";
+               CopyLevel($e,GetNextLevel($e,$l),"*$argument", $member);
+               deindent;
+               pidl "}";
+       } elsif ($l->{TYPE} eq "SWITCH") {
+               CopyLevel($e,GetNextLevel($e,$l),$argument,$member);    
+       } elsif ($l->{TYPE} eq "ARRAY") {
+               pidl "*$argument = $member;";
+       }
+}
 
 sub ParseFunction($$)
 {
@@ -59,10 +81,14 @@ sub ParseFunction($$)
        pidl "\tNT_STATUS_UNSUCCESSFUL);";
        pidl "";
        pidl "/* Return variables */";
-       foreach (@{$fn->{ELEMENTS}}) {
-               next unless (grep(/out/, @{$_->{DIRECTION}}));
-
-               pidl "*$_->{NAME} = r.$_->{NAME};";
+       foreach my $e (@{$fn->{ELEMENTS}}) {
+               next unless (grep(/out/, @{$e->{DIRECTION}}));
+               
+               if ($e->{LEVELS}[0]->{TYPE} ne "POINTER") {
+                       warning($e->{ORIGINAL}, "First element not a pointer for [out] argument");
+                       next;
+               }
+               CopyLevel($e, $e->{LEVELS}[1], $e->{NAME}, "r.$e->{NAME}");
        }
 
        pidl"";
index 4579ae2ec00d784d16eb0829f18cd8a3da2aa25a..1bcaa5c67262c831d794a71a538b40c559192e98 100644 (file)
@@ -29,7 +29,7 @@ sub ParseElement($)
        foreach my $l (@{$e->{LEVELS}}) {
                if ($l->{TYPE} eq "POINTER") {
                        return if ($l->{POINTER_TYPE} eq "ref" and $l->{LEVEL} eq "top");
-                       pidl "\tuint32 ptr_$e->{NAME};";
+                       pidl "\tuint32 ptr$l->{POINTER_INDEX}_$e->{NAME};";
                } elsif ($l->{TYPE} eq "SWITCH") {
                        pidl "\tuint32 level_$e->{NAME};";
                } elsif ($l->{TYPE} eq "DATA") {
@@ -120,7 +120,7 @@ sub ParseUnion($$$)
                                        $extra->{"length"} = $extra->{"offset"} = 1;
                                }
                        } elsif ($l->{TYPE} eq "POINTER") {
-                               $extra->{"ptr"} = 1;
+                               $extra->{"ptr$l->{POINTER_INDEX}"} = 1;
                        } elsif ($l->{TYPE} eq "SWITCH") {
                                $extra->{"level"} = 1;
                        }
index ac7fde69a6803ee5fb627044184cbfd30828d102..7cd1255a40f94d5faf2a04d8612ee3119620d8df 100644 (file)
@@ -158,14 +158,16 @@ sub ParseElementLevelPtr($$$$$$$)
        my ($e,$l,$nl,$env,$varname,$what,$align) = @_;
 
        if ($what == PRIMITIVES) {
-               if ($l->{POINTER_TYPE} eq "ref" and 
-                       $l->{LEVEL} eq "TOP") {
-                       pidl "if (!" . ParseExpr("ptr_$e->{NAME}", $env) . ")";
+               if (($l->{POINTER_TYPE} eq "ref") and ($l->{LEVEL} eq "EMBEDDED")) {
+                       # Ref pointers always have to be non-NULL
+                       pidl "if (MARSHALLING(ps) && !" . ParseExpr("ptr$l->{POINTER_INDEX}_$e->{NAME}", $env) . ")";
                        pidl "\treturn False;";
                        pidl "";
-               } else {
+               } 
+               
+               unless ($l->{POINTER_TYPE} eq "ref" and $l->{LEVEL} eq "TOP") {
                        Align($align, 4);
-                       pidl "if (!prs_uint32(\"ptr_$e->{NAME}\", ps, depth, &" . ParseExpr("ptr_$e->{NAME}", $env) . "))";
+                       pidl "if (!prs_uint32(\"ptr$l->{POINTER_INDEX}_$e->{NAME}\", ps, depth, &" . ParseExpr("ptr$l->{POINTER_INDEX}_$e->{NAME}", $env) . "))";
                        pidl "\treturn False;";
                        pidl "";
                }
@@ -177,12 +179,16 @@ sub ParseElementLevelPtr($$$$$$$)
        }
        
        if ($what == DEFERRED) {
-               pidl "if (" . ParseExpr("ptr_$e->{NAME}", $env) . ") {";
-               indent;
+               if ($l->{POINTER_TYPE} ne "ref") {
+                       pidl "if (" . ParseExpr("ptr$l->{POINTER_INDEX}_$e->{NAME}", $env) . ") {";
+                       indent;
+               }
                ParseElementLevel($e,$nl,$env,$varname,PRIMITIVES,$align);
                ParseElementLevel($e,$nl,$env,$varname,DEFERRED,$align);
-               deindent;
-               pidl "}";
+               if ($l->{POINTER_TYPE} ne "ref") {
+                       deindent;
+                       pidl "}";
+               }
                $$align = 0;
        }
 }
@@ -221,14 +227,24 @@ sub InitLevel($$$$)
        my ($e,$l,$varname,$env) = @_;
 
        if ($l->{TYPE} eq "POINTER") {
-               pidl "if ($varname) {";
-               indent;
-               pidl ParseExpr("ptr_$e->{NAME}", $env) . " = 1;";
+               if ($l->{POINTER_TYPE} eq "ref") {
+                       pidl "if (!$varname)";
+                       pidl "\treturn False;";
+                       pidl "";
+               } else {
+                       pidl "if ($varname) {";
+                       indent;
+               }
+
+               pidl ParseExpr("ptr$l->{POINTER_INDEX}_$e->{NAME}", $env) . " = 1;";
                InitLevel($e, GetNextLevel($e,$l), "*$varname", $env);
-               deindent;
-               pidl "} else {";
-               pidl "\t" . ParseExpr("ptr_$e->{NAME}", $env) . " = 0;";
-               pidl "}";
+               
+               if ($l->{POINTER_TYPE} ne "ref") {
+                       deindent;
+                       pidl "} else {";
+                       pidl "\t" . ParseExpr("ptr$l->{POINTER_INDEX}_$e->{NAME}", $env) . " = 0;";
+                       pidl "}";
+               }
        } elsif ($l->{TYPE} eq "ARRAY") {
                pidl ParseExpr($e->{NAME}, $env) . " = $varname;";
        } elsif ($l->{TYPE} eq "DATA") {
@@ -245,7 +261,7 @@ sub GenerateEnvElement($$)
                if ($l->{TYPE} eq "DATA") {
                        $env->{$e->{NAME}} = "v->$e->{NAME}";
                } elsif ($l->{TYPE} eq "POINTER") {
-                       $env->{"ptr_$e->{NAME}"} = "v->ptr_$e->{NAME}";
+                       $env->{"ptr$l->{POINTER_INDEX}_$e->{NAME}"} = "v->ptr$l->{POINTER_INDEX}_$e->{NAME}";
                } elsif ($l->{TYPE} eq "SWITCH") {
                        $env->{"level_$e->{NAME}"} = "v->level_$e->{NAME}";
                } elsif ($l->{TYPE} eq "ARRAY") {
@@ -350,7 +366,7 @@ sub UnionGenerateEnvElement($)
                if ($l->{TYPE} eq "DATA") {
                        $env->{$e->{NAME}} = "v->u.$e->{NAME}";
                } elsif ($l->{TYPE} eq "POINTER") {
-                       $env->{"ptr_$e->{NAME}"} = "v->ptr";
+                       $env->{"ptr$l->{POINTER_INDEX}_$e->{NAME}"} = "v->ptr$l->{POINTER_INDEX}";
                } elsif ($l->{TYPE} eq "SWITCH") {
                        $env->{"level_$e->{NAME}"} = "v->level";
                } elsif ($l->{TYPE} eq "ARRAY") {
@@ -480,7 +496,7 @@ sub CreateFnDirection($$$$)
        pidl "prs_debug(ps, depth, desc, \"$fn\");";
        pidl "depth++;";
 
-       my $align = 0;
+       my $align = 8;
        foreach (@$es) {
                ParseElement($_, $env, PRIMITIVES, \$align); 
                ParseElement($_, $env, DEFERRED, \$align);