1
0
mirror of https://github.com/samba-team/samba.git synced 2025-02-28 01:58:17 +03:00

r10742: Support multi-level pointers + ref pointer fixes

(This used to be commit 258b762dc62b257f99d1d859c5a3d850aba3e9fa)
This commit is contained in:
Jelmer Vernooij 2005-10-05 22:18:59 +00:00 committed by Gerald (Jerry) Carter
parent 765f69ce42
commit be9af1a4e8
4 changed files with 71 additions and 25 deletions

View 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");

View 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"";

View 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;
}

View 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);