summaryrefslogtreecommitdiff
path: root/source4/pidl/lib/Parse
diff options
context:
space:
mode:
authorJelmer Vernooij <jelmer@samba.org>2005-10-05 00:29:47 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 13:39:24 -0500
commitd220237b19f361a2c3c09b292e11f54c8d522fdf (patch)
tree786d6a19e83e305d9c44bcc73ede81afea4d84da /source4/pidl/lib/Parse
parent1e0823d0a580ec61ae5a4e4826586e24f64eee0b (diff)
downloadsamba-d220237b19f361a2c3c09b292e11f54c8d522fdf.tar.gz
samba-d220237b19f361a2c3c09b292e11f54c8d522fdf.tar.bz2
samba-d220237b19f361a2c3c09b292e11f54c8d522fdf.zip
r10721: Handle allocations and primitive / deferred data correctly. In theory,
the generated output for DFS should work now (it compiles cleanly, but I haven't tested it yet). Not supported: - subcontexts() - relative pointers - unions of pointers - DATA_BLOB - several other things Also still need to do: - Remove some spurious spaces in the output - Do range() checking Example output is still available at http://samba.org/~jelmer/pidl_samba3/ (This used to be commit e2d7e382bb645f1bddd2047669bed10f121b59d2)
Diffstat (limited to 'source4/pidl/lib/Parse')
-rw-r--r--source4/pidl/lib/Parse/Pidl/Samba3/Header.pm1
-rw-r--r--source4/pidl/lib/Parse/Pidl/Samba3/Parser.pm286
-rw-r--r--source4/pidl/lib/Parse/Pidl/Samba3/Types.pm69
3 files changed, 273 insertions, 83 deletions
diff --git a/source4/pidl/lib/Parse/Pidl/Samba3/Header.pm b/source4/pidl/lib/Parse/Pidl/Samba3/Header.pm
index 21a56e4c2d..5b7fddc14f 100644
--- a/source4/pidl/lib/Parse/Pidl/Samba3/Header.pm
+++ b/source4/pidl/lib/Parse/Pidl/Samba3/Header.pm
@@ -37,6 +37,7 @@ sub ParseElement($)
}
if ($l->{IS_VARYING}) {
pidl "\tuint32 length_$e->{NAME};";
+ pidl "\tuint32 offset_$e->{NAME};";
}
}
}
diff --git a/source4/pidl/lib/Parse/Pidl/Samba3/Parser.pm b/source4/pidl/lib/Parse/Pidl/Samba3/Parser.pm
index 166d98bfb1..702835c378 100644
--- a/source4/pidl/lib/Parse/Pidl/Samba3/Parser.pm
+++ b/source4/pidl/lib/Parse/Pidl/Samba3/Parser.pm
@@ -14,6 +14,9 @@ use Parse::Pidl::Samba3::Types qw(DeclShort DeclLong InitType DissectType);
use vars qw($VERSION);
$VERSION = '0.01';
+use constant PRIMITIVES => 1;
+use constant DEFERRED => 2;
+
my $res = "";
my $tabs = "";
sub indent() { $tabs.="\t"; }
@@ -22,17 +25,22 @@ sub pidl($) { $res .= $tabs.(shift)."\n"; }
sub fatal($$) { my ($e,$s) = @_; die("$e->{FILE}:$e->{LINE}: $s\n"); }
#TODO:
-# - Different scalars / buffers functions for arrays + unions
-# - Memory allocation for arrays
+# - Add some security checks (array sizes, memory alloc == NULL, etc)
+# - Don't add seperate _p and _d functions if there is no deferred data
-sub DeclareArrayVariables($)
+sub DeclareArrayVariables
{
my $es = shift;
+ my $what = shift;
my $output = 0;
foreach my $e (@$es) {
foreach my $l (@{$e->{LEVELS}}) {
+ if ($what) {
+ next if ($l->{IS_DEFERRED} and $what == PRIMITIVES);
+ next if (not $l->{IS_DEFERRED} and $what == DEFERRED);
+ }
if ($l->{TYPE} eq "ARRAY") {
pidl "uint32 i_$e->{NAME}_$l->{LEVEL_INDEX};";
$output = 1;
@@ -42,11 +50,11 @@ sub DeclareArrayVariables($)
pidl "" if $output;
}
-sub ParseElementLevelData($$$$$)
+sub ParseElementLevelData($$$$$$)
{
- my ($e,$l,$nl,$env,$varname) = @_;
+ my ($e,$l,$nl,$env,$varname,$what) = @_;
- my @args = ($e,$l,$varname);
+ my @args = ($e,$l,$varname,$what);
# See if we need to add a level argument because we're parsing a union
foreach (@{$e->{LEVELS}}) {
@@ -54,64 +62,107 @@ sub ParseElementLevelData($$$$$)
if ($_->{TYPE} eq "SWITCH");
}
- pidl "if (!".DissectType(@args).")";
+ my $c = DissectType(@args);
+ return if not $c;
+
+ pidl "if (!$c)";
pidl "\treturn False;";
}
-sub ParseElementLevelArray($$$$$)
+sub ParseElementLevelArray($$$$$$)
{
- my ($e,$l,$nl,$env,$varname) = @_;
+ my ($e,$l,$nl,$env,$varname,$what) = @_;
my $len = ParseExpr($l->{LENGTH_IS}, $env);
+ my $size = ParseExpr($l->{SIZE_IS}, $env);
+
+ if ($what == PRIMITIVES) {
+ # Fetch headers
+ if ($l->{IS_CONFORMANT} and not $l->{IS_SURROUNDING}) {
+ pidl "if (!prs_uint32(\"size_$e->{NAME}\", ps, depth, &" . ParseExpr("size_$e->{NAME}", $env) . "))";
+ pidl "\treturn False;";
+ pidl "";
+ }
+
+ if ($l->{IS_VARYING}) {
+ pidl "if (!prs_uint32(\"offset_$e->{NAME}\", ps, depth, &" . ParseExpr("offset_$e->{NAME}", $env) . "))";
+ pidl "\treturn False;";
+ pidl "";
+
+ pidl "if (!prs_uint32(\"length_$e->{NAME}\", ps, depth, &" . ParseExpr("length_$e->{NAME}", $env) . "))";
+ pidl "\treturn False;";
+ pidl "";
+ }
+ }
+
+ # Everything but fixed arrays have to be allocated
+ if (!$l->{IS_FIXED} and $what == PRIMITIVES) {
+ pidl "if (UNMARSHALLING(ps)) {";
+ indent;
+ pidl "$varname = (void *)PRS_ALLOC_MEM_VOID(ps,sizeof(*$varname)*$size);";
+ deindent;
+ pidl "}";
+ }
+
+ return if ($what == DEFERRED and not ContainsDeferred($e,$l));
my $i = "i_$e->{NAME}_$l->{LEVEL_INDEX}";
pidl "for ($i=0; $i<$len;$i++) {";
indent;
- ParseElementLevel($e,$nl,$env,$varname."[$i]");
+ ParseElementLevel($e,$nl,$env,$varname."[$i]",$what);
deindent;
pidl "}";
}
-sub ParseElementLevelSwitch($$$$$)
+sub ParseElementLevelSwitch($$$$$$)
{
- my ($e,$l,$nl,$env,$varname) = @_;
+ my ($e,$l,$nl,$env,$varname,$what) = @_;
- pidl "if (!prs_uint32(\"level\", ps, depth, &" . ParseExpr("level_$e->{NAME}", $env) . "))";
- pidl "\treturn False;";
- pidl "";
+ if ($what == PRIMITIVES) {
+ pidl "if (!prs_uint32(\"level\", ps, depth, &" . ParseExpr("level_$e->{NAME}", $env) . "))";
+ pidl "\treturn False;";
+ pidl "";
+ }
- ParseElementLevel($e,$nl,$env,$varname);
+ ParseElementLevel($e,$nl,$env,$varname,$what);
}
-sub ParseElementLevelPtr($$$$$)
+sub ParseElementLevelPtr($$$$$$)
{
- my ($e,$l,$nl,$env,$varname) = @_;
+ my ($e,$l,$nl,$env,$varname,$what) = @_;
+
+ if ($what == PRIMITIVES) {
+ pidl "if (!prs_uint32(\"ptr_$e->{NAME}\", ps, depth, &" . ParseExpr("ptr_$e->{NAME}", $env) . "))";
+ pidl "\treturn False;";
+ pidl "";
+ }
if ($l->{POINTER_TYPE} eq "relative") {
fatal($e, "relative pointers not supported for Samba 3");
+ #FIXME
}
-
- pidl "if (!prs_uint32(\"ptr_$e->{NAME}\", ps, depth, &" . ParseExpr("ptr_$e->{NAME}", $env) . "))";
- pidl "\treturn False;";
- pidl "";
- pidl "if (" . ParseExpr("ptr_$e->{NAME}", $env) . ") {";
- indent;
- ParseElementLevel($e,$nl,$env,$varname);
- deindent;
- pidl "}";
+ if ($what == DEFERRED) {
+ pidl "if (" . ParseExpr("ptr_$e->{NAME}", $env) . ") {";
+ indent;
+ ParseElementLevel($e,$nl,$env,$varname,PRIMITIVES);
+ ParseElementLevel($e,$nl,$env,$varname,DEFERRED);
+ deindent;
+ pidl "}";
+ }
}
-sub ParseElementLevelSubcontext($$$$$)
+sub ParseElementLevelSubcontext($$$$$$)
{
- my ($e,$l,$nl,$env,$varname) = @_;
+ my ($e,$l,$nl,$env,$varname,$what) = @_;
fatal($e, "subcontext() not supported for Samba 3");
+ #FIXME
}
-sub ParseElementLevel($$$$)
+sub ParseElementLevel($$$$$)
{
- my ($e,$l,$env,$varname) = @_;
+ my ($e,$l,$env,$varname,$what) = @_;
{
DATA => \&ParseElementLevelData,
@@ -119,14 +170,14 @@ sub ParseElementLevel($$$$)
POINTER => \&ParseElementLevelPtr,
SWITCH => \&ParseElementLevelSwitch,
ARRAY => \&ParseElementLevelArray
- }->{$l->{TYPE}}->($e,$l,GetNextLevel($e,$l),$env,$varname);
+ }->{$l->{TYPE}}->($e,$l,GetNextLevel($e,$l),$env,$varname,$what);
}
-sub ParseElement($$)
+sub ParseElement($$$)
{
- my ($e,$env) = @_;
+ my ($e,$env,$what) = @_;
- ParseElementLevel($e, $e->{LEVELS}[0], $env, ParseExpr($e->{NAME}, $env));
+ ParseElementLevel($e, $e->{LEVELS}[0], $env, ParseExpr($e->{NAME}, $env), $what);
}
sub InitLevel($$$$)
@@ -164,29 +215,35 @@ sub GenerateEnvElement($$)
$env->{"level_$e->{NAME}"} = "v->level_$e->{NAME}";
} elsif ($l->{TYPE} eq "ARRAY") {
$env->{"length_$e->{NAME}"} = "v->length_$e->{NAME}";
+ $env->{"size_$e->{NAME}"} = "v->size_$e->{NAME}";
+ $env->{"offset_$e->{NAME}"} = "v->offset_$e->{NAME}";
}
}
}
-sub CreateStruct($$$$$)
+sub ParseStruct($$$)
{
- my ($fn,$ifn, $s,$es,$a) = @_;
+ my ($if,$s,$n) = @_;
+
+ my $fn = "$if->{NAME}_io_$n";
+ my $sn = uc("$if->{NAME}_$n");
+ my $ifn = "init_$if->{NAME}_$n";
my $args = "";
- foreach (@$es) {
+ foreach (@{$s->{ELEMENTS}}) {
$args .= ", " . DeclLong($_);
}
my $env = { "this" => "v" };
- GenerateEnvElement($_, $env) foreach (@$es);
+ GenerateEnvElement($_, $env) foreach (@{$s->{ELEMENTS}});
- pidl "BOOL $ifn($s *v$args)";
+ pidl "BOOL $ifn($sn *v$args)";
pidl "{";
indent;
pidl "DEBUG(5,(\"$ifn\\n\"));";
pidl "";
# Call init for all arguments
- foreach (@$es) {
+ foreach (@{$s->{ELEMENTS}}) {
InitLevel($_, $_->{LEVELS}[0], $_->{NAME}, $env);
pidl "";
}
@@ -194,24 +251,31 @@ sub CreateStruct($$$$$)
deindent;
pidl "}";
pidl "";
+
+ my $pfn = "$fn\_p";
+ my $dfn = "$fn\_d";
- pidl "BOOL $fn(const char *desc, $s *v, prs_struct *ps, int depth)";
+ pidl "BOOL $pfn(const char *desc, $sn *v, prs_struct *ps, int depth)";
pidl "{";
indent;
- DeclareArrayVariables($es);
+ DeclareArrayVariables($s->{ELEMENTS}, PRIMITIVES);
pidl "if (v == NULL)";
pidl "\treturn False;";
pidl "";
- pidl "prs_debug(ps, depth, desc, \"$fn\");";
+ pidl "prs_debug(ps, depth, desc, \"$pfn\");";
pidl "depth++;";
- if ($a > 0) {
- pidl "if (!prs_align_custom(ps, $a))";
+ pidl "if (!prs_align_custom(ps, $s->{ALIGN}))";
+ pidl "\treturn False;";
+ pidl "";
+
+ if ($s->{SURROUNDING_ELEMENT}) {
+ pidl "if (!prs_uint32(\"size_$s->{SURROUNDING_ELEMENT}->{NAME}\", ps, depth, &" . ParseExpr("size_$s->{SURROUNDING_ELEMENT}->{NAME}", $env) . "))";
pidl "\treturn False;";
pidl "";
}
- foreach (@$es) {
- ParseElement($_, $env);
+ foreach (@{$s->{ELEMENTS}}) {
+ ParseElement($_, $env, PRIMITIVES);
pidl "";
}
@@ -219,16 +283,29 @@ sub CreateStruct($$$$$)
deindent;
pidl "}";
pidl "";
-}
-sub ParseStruct($$$)
-{
- my ($if,$s,$n) = @_;
+ pidl "BOOL $dfn(const char *desc, $sn *v, prs_struct *ps, int depth)";
+ pidl "{";
+ indent;
+ DeclareArrayVariables($s->{ELEMENTS}, DEFERRED);
+ pidl "if (v == NULL)";
+ pidl "\treturn False;";
+ pidl "";
+ pidl "prs_debug(ps, depth, desc, \"$dfn\");";
+ pidl "depth++;";
+ pidl "if (!prs_align_custom(ps, $s->{ALIGN}))";
+ pidl "\treturn False;";
+ pidl "";
- my $fn = "$if->{NAME}_io_$n";
- my $sn = uc("$if->{NAME}_$n");
+ foreach (@{$s->{ELEMENTS}}) {
+ ParseElement($_, $env, DEFERRED);
+ pidl "";
+ }
- CreateStruct($fn, "init_$if->{NAME}_$n", $sn, $s->{ELEMENTS}, $s->{ALIGN});
+ pidl "return True;";
+ deindent;
+ pidl "}";
+ pidl "";
}
sub ParseUnion($$$)
@@ -238,7 +315,44 @@ sub ParseUnion($$$)
my $fn = "$if->{NAME}_io_$n";
my $sn = uc("$if->{NAME}_$n");
- pidl "BOOL $fn(const char *desc, $sn* v, uint32 level, prs_struct *ps, int depth)";
+ my $pfn = "$fn\_p";
+ my $dfn = "$fn\_d";
+
+ pidl "BOOL $pfn(const char *desc, $sn* v, uint32 level, prs_struct *ps, int depth)";
+ pidl "{";
+ indent;
+ DeclareArrayVariables($u->{ELEMENTS});
+ pidl "if (!prs_align_custom(ps, $u->{ALIGN}))";
+ pidl "\treturn False;";
+ pidl "";
+
+ pidl "switch (level) {";
+ indent;
+
+ foreach (@{$u->{ELEMENTS}}) {
+ pidl "$_->{CASE}:";
+ indent;
+ if ($_->{TYPE} ne "EMPTY") {
+ pidl "depth++;";
+ my $env = {};
+ GenerateEnvElement($_, $env);
+ ParseElement($_, $env, PRIMITIVES);
+ ParseElement($_, $env, DEFERRED);
+ pidl "depth--;";
+ }
+ pidl "break;";
+ deindent;
+ pidl "";
+ }
+
+ deindent;
+ pidl "}";
+ pidl "";
+ pidl "return True;";
+ deindent;
+ pidl "}";
+
+ pidl "BOOL $dfn(const char *desc, $sn* v, uint32 level, prs_struct *ps, int depth)";
pidl "{";
indent;
DeclareArrayVariables($u->{ELEMENTS});
@@ -256,7 +370,7 @@ sub ParseUnion($$$)
pidl "depth++;";
my $env = {};
GenerateEnvElement($_, $env);
- ParseElement($_, $env);
+ ParseElement($_, $env, DEFERRED);
pidl "depth--;";
}
pidl "break;";
@@ -270,6 +384,56 @@ sub ParseUnion($$$)
pidl "return True;";
deindent;
pidl "}";
+
+}
+
+sub CreateFnDirection($$$$)
+{
+ my ($fn,$ifn, $s,$es) = @_;
+
+ my $args = "";
+ foreach (@$es) {
+ $args .= ", " . DeclLong($_);
+ }
+
+ my $env = { "this" => "v" };
+ GenerateEnvElement($_, $env) foreach (@$es);
+
+ pidl "BOOL $ifn($s *v$args)";
+ pidl "{";
+ indent;
+ pidl "DEBUG(5,(\"$ifn\\n\"));";
+ pidl "";
+ # Call init for all arguments
+ foreach (@$es) {
+ InitLevel($_, $_->{LEVELS}[0], $_->{NAME}, $env);
+ pidl "";
+ }
+ pidl "return True;";
+ deindent;
+ pidl "}";
+ pidl "";
+
+ pidl "BOOL $fn(const char *desc, $s *v, prs_struct *ps, int depth)";
+ pidl "{";
+ indent;
+ DeclareArrayVariables($es);
+ pidl "if (v == NULL)";
+ pidl "\treturn False;";
+ pidl "";
+ pidl "prs_debug(ps, depth, desc, \"$fn\");";
+ pidl "depth++;";
+
+ foreach (@$es) {
+ ParseElement($_, $env, PRIMITIVES);
+ ParseElement($_, $env, DEFERRED);
+ pidl "";
+ }
+
+ pidl "return True;";
+ deindent;
+ pidl "}";
+ pidl "";
}
sub ParseFunction($$)
@@ -297,14 +461,14 @@ sub ParseFunction($$)
} );
}
- CreateStruct("$if->{NAME}_io_q_$fn->{NAME}",
+ CreateFnDirection("$if->{NAME}_io_q_$fn->{NAME}",
"init_$if->{NAME}_q_$fn->{NAME}",
uc("$if->{NAME}_q_$fn->{NAME}"),
- \@in, 0);
- CreateStruct("$if->{NAME}_io_r_$fn->{NAME}",
+ \@in);
+ CreateFnDirection("$if->{NAME}_io_r_$fn->{NAME}",
"init_$if->{NAME}_r_$fn->{NAME}",
uc("$if->{NAME}_r_$fn->{NAME}"),
- \@out, 0);
+ \@out);
}
sub ParseInterface($)
diff --git a/source4/pidl/lib/Parse/Pidl/Samba3/Types.pm b/source4/pidl/lib/Parse/Pidl/Samba3/Types.pm
index a3bf91d54f..9a7a31a6bb 100644
--- a/source4/pidl/lib/Parse/Pidl/Samba3/Types.pm
+++ b/source4/pidl/lib/Parse/Pidl/Samba3/Types.pm
@@ -109,50 +109,50 @@ my $known_types =
{
DECL => "uint8",
INIT => \&init_scalar,
- DISSECT => \&dissect_scalar,
+ DISSECT_P => \&dissect_scalar,
},
uint16 =>
{
DECL => "uint16",
INIT => \&init_scalar,
- DISSECT => \&dissect_scalar,
+ DISSECT_P => \&dissect_scalar,
},
uint32 =>
{
DECL => "uint32",
INIT => \&init_scalar,
- DISSECT => \&dissect_scalar,
+ DISSECT_P => \&dissect_scalar,
},
uint64 =>
{
DECL => "uint64",
INIT => \&init_scalar,
- DISSECT => \&dissect_scalar,
+ DISSECT_P => \&dissect_scalar,
},
string =>
{
DECL => \&decl_string,
EXT_DECL => \&ext_decl_string,
INIT => \&init_string,
- DISSECT => \&dissect_string,
+ DISSECT_P => \&dissect_string,
},
NTSTATUS =>
{
DECL => "NTSTATUS",
INIT => \&init_scalar,
- DISSECT => \&dissect_scalar,
+ DISSECT_P => \&dissect_scalar,
},
WERROR =>
{
DECL => "WERROR",
INIT => \&init_scalar,
- DISSECT => \&dissect_scalar,
+ DISSECT_P => \&dissect_scalar,
},
GUID =>
{
DECL => "struct uuid",
INIT => "",
- DISSECT => sub {
+ DISSECT_P => sub {
my ($e,$l,$n) = @_;
return "smb_io_uuid(\"$e->{NAME}\", &$n, ps, depth)";
}
@@ -161,7 +161,7 @@ my $known_types =
{
DECL => "NTTIME",
INIT => "",
- DISSECT => sub {
+ DISSECT_P => sub {
my ($e,$l,$n) = @_;
return "smb_io_nttime(\"$e->{NAME}\", &n, ps, depth)";
}
@@ -170,7 +170,7 @@ my $known_types =
{
DECL => "DOM_SID",
INIT => "",
- DISSECT => sub {
+ DISSECT_P => sub {
my ($e,$l,$n) = @_;
return "smb_io_dom_sid(\"$e->{NAME}\", &n, ps, depth)";
}
@@ -179,7 +179,7 @@ my $known_types =
{
DECL => "POLICY_HND",
INIT => "",
- DISSECT => sub {
+ DISSECT_P => sub {
my ($e,$l,$n) = @_;
return "smb_io_pol_hnd(\"$e->{NAME}\", &n, ps, depth)";
}
@@ -301,6 +301,7 @@ sub DissectType
my $e = shift @_;
my $l = shift @_;
my $varname = shift @_;
+ my $what = shift @_;
my $t = $known_types->{$l->{DATA_TYPE}};
@@ -309,11 +310,20 @@ sub DissectType
return undef;
}
+ my $dissect;
+ if ($what == 1) { #primitives
+ $dissect = $t->{DISSECT_P};
+ } elsif ($what == 2) {
+ $dissect = $t->{DISSECT_D};
+ }
+
+ return "" if not defined($dissect);
+
# DISSECT can be a function
- if (ref($t->{DISSECT}) eq "CODE") {
- return $t->{DISSECT}->(@args);
+ if (ref($dissect) eq "CODE") {
+ return $dissect->(@args);
} else {
- return $t->{DISSECT};
+ return $dissect;
}
}
@@ -330,25 +340,40 @@ sub LoadTypes($)
return "$n = $v;";
};
- my $dissect;
+ my $dissect_d;
+ my $dissect_p;
if ($td->{DATA}->{TYPE} eq "UNION") {
- $dissect = sub {
- my ($e,$l,$n,$s) = @_;
+ $dissect_p = sub {
+ my ($e,$l,$n,$w,$s) = @_;
+
+ return "$if->{NAME}_io_$td->{NAME}_p(\"$e->{NAME}\", &$n, $s, ps, depth)";
+ };
- return "$if->{NAME}_io_$td->{NAME}(\"$e->{NAME}\", &$n, $s, ps, depth)";
+ $dissect_d = sub {
+ my ($e,$l,$n,$w,$s) = @_;
+
+ return "$if->{NAME}_io_$td->{NAME}_d(\"$e->{NAME}\", &$n, $s, ps, depth)";
};
+
} else {
- $dissect = sub {
- my ($e,$l,$n) = @_;
+ $dissect_p = sub {
+ my ($e,$l,$n,$w) = @_;
- return "$if->{NAME}_io_$td->{NAME}(\"$e->{NAME}\", &$n, ps, depth)";
+ return "$if->{NAME}_io_$td->{NAME}_p(\"$e->{NAME}\", &$n, ps, depth)";
};
+ $dissect_d = sub {
+ my ($e,$l,$n,$w) = @_;
+
+ return "$if->{NAME}_io_$td->{NAME}_d(\"$e->{NAME}\", &$n, ps, depth)";
+ };
+
}
AddType($td->{NAME}, {
DECL => $decl,
INIT => $init,
- DISSECT => $dissect
+ DISSECT_D => $dissect_d,
+ DISSECT_P => $dissect_p
});
}
}