Sync up to the latest PIDL with Mathieu's wireshark patches

svn path=/trunk/; revision=38470
This commit is contained in:
Ronnie Sahlberg 2011-08-11 06:12:39 +00:00
parent 37bab5e89d
commit 07213ad329
14 changed files with 911 additions and 273 deletions

View File

@ -387,7 +387,31 @@ pipe:
{{
"TYPE" => "PIPE",
"PROPERTIES" => $_[1],
"DATA" => $_[3],
"NAME" => undef,
"DATA" => {
"TYPE" => "STRUCT",
"PROPERTIES" => $_[1],
"NAME" => undef,
"ELEMENTS" => [{
"NAME" => "count",
"PROPERTIES" => $_[1],
"POINTERS" => 0,
"ARRAY_LEN" => [],
"TYPE" => "uint3264",
"FILE" => $_[0]->YYData->{FILE},
"LINE" => $_[0]->YYData->{LINE},
},{
"NAME" => "array",
"PROPERTIES" => $_[1],
"POINTERS" => 0,
"ARRAY_LEN" => [ "count" ],
"TYPE" => $_[3],
"FILE" => $_[0]->YYData->{FILE},
"LINE" => $_[0]->YYData->{LINE},
}],
"FILE" => $_[0]->YYData->{FILE},
"LINE" => $_[0]->YYData->{LINE},
},
"FILE" => $_[0]->YYData->{FILE},
"LINE" => $_[0]->YYData->{LINE},
}}
@ -653,11 +677,17 @@ sub parse_file($$)
my $saved_delim = $/;
undef $/;
my $cpp = $ENV{CPP};
my $options = "";
if (! defined $cpp) {
$cpp = "cpp";
if (defined $ENV{CC}) {
$cpp = "$ENV{CC}";
$options = "-E";
} else {
$cpp = "cpp";
}
}
my $includes = join('',map { " -I$_" } @$incdirs);
my $data = `$cpp -D__PIDL__$includes -xc "$filename"`;
my $data = `$cpp $options -D__PIDL__$includes -xc "$filename"`;
$/ = $saved_delim;
return parse_string($data, $filename);

View File

@ -1127,7 +1127,7 @@ sub new {
[#Rule 2
'exp', 1,
sub
#line 24 "./../pidl/expr.yp"
#line 24 "expr.yp"
{ "\"$_[1]\"" }
],
[#Rule 3
@ -1139,199 +1139,199 @@ sub
[#Rule 5
'exp', 2,
sub
#line 30 "./../pidl/expr.yp"
#line 30 "expr.yp"
{ "~$_[2]" }
],
[#Rule 6
'exp', 3,
sub
#line 32 "./../pidl/expr.yp"
#line 32 "expr.yp"
{ "$_[1] + $_[3]" }
],
[#Rule 7
'exp', 3,
sub
#line 34 "./../pidl/expr.yp"
#line 34 "expr.yp"
{ "$_[1] - $_[3]" }
],
[#Rule 8
'exp', 3,
sub
#line 36 "./../pidl/expr.yp"
#line 36 "expr.yp"
{ "$_[1] * $_[3]" }
],
[#Rule 9
'exp', 3,
sub
#line 38 "./../pidl/expr.yp"
#line 38 "expr.yp"
{ "$_[1] % $_[3]" }
],
[#Rule 10
'exp', 3,
sub
#line 40 "./../pidl/expr.yp"
#line 40 "expr.yp"
{ "$_[1] < $_[3]" }
],
[#Rule 11
'exp', 3,
sub
#line 42 "./../pidl/expr.yp"
#line 42 "expr.yp"
{ "$_[1] > $_[3]" }
],
[#Rule 12
'exp', 3,
sub
#line 44 "./../pidl/expr.yp"
#line 44 "expr.yp"
{ "$_[1] | $_[3]" }
],
[#Rule 13
'exp', 3,
sub
#line 46 "./../pidl/expr.yp"
#line 46 "expr.yp"
{ "$_[1] == $_[3]" }
],
[#Rule 14
'exp', 3,
sub
#line 48 "./../pidl/expr.yp"
#line 48 "expr.yp"
{ "$_[1] <= $_[3]" }
],
[#Rule 15
'exp', 3,
sub
#line 50 "./../pidl/expr.yp"
#line 50 "expr.yp"
{ "$_[1] => $_[3]" }
],
[#Rule 16
'exp', 3,
sub
#line 52 "./../pidl/expr.yp"
#line 52 "expr.yp"
{ "$_[1] << $_[3]" }
],
[#Rule 17
'exp', 3,
sub
#line 54 "./../pidl/expr.yp"
#line 54 "expr.yp"
{ "$_[1] >> $_[3]" }
],
[#Rule 18
'exp', 3,
sub
#line 56 "./../pidl/expr.yp"
#line 56 "expr.yp"
{ "$_[1] != $_[3]" }
],
[#Rule 19
'exp', 3,
sub
#line 58 "./../pidl/expr.yp"
#line 58 "expr.yp"
{ "$_[1] || $_[3]" }
],
[#Rule 20
'exp', 3,
sub
#line 60 "./../pidl/expr.yp"
#line 60 "expr.yp"
{ "$_[1] && $_[3]" }
],
[#Rule 21
'exp', 3,
sub
#line 62 "./../pidl/expr.yp"
#line 62 "expr.yp"
{ "$_[1] & $_[3]" }
],
[#Rule 22
'exp', 5,
sub
#line 64 "./../pidl/expr.yp"
#line 64 "expr.yp"
{ "$_[1]?$_[3]:$_[5]" }
],
[#Rule 23
'exp', 2,
sub
#line 66 "./../pidl/expr.yp"
#line 66 "expr.yp"
{ "~$_[1]" }
],
[#Rule 24
'exp', 2,
sub
#line 68 "./../pidl/expr.yp"
#line 68 "expr.yp"
{ "not $_[1]" }
],
[#Rule 25
'exp', 3,
sub
#line 70 "./../pidl/expr.yp"
#line 70 "expr.yp"
{ "$_[1] / $_[3]" }
],
[#Rule 26
'exp', 2,
sub
#line 72 "./../pidl/expr.yp"
#line 72 "expr.yp"
{ "-$_[2]" }
],
[#Rule 27
'exp', 2,
sub
#line 74 "./../pidl/expr.yp"
#line 74 "expr.yp"
{ "&$_[2]" }
],
[#Rule 28
'exp', 3,
sub
#line 76 "./../pidl/expr.yp"
#line 76 "expr.yp"
{ "$_[1]^$_[3]" }
],
[#Rule 29
'exp', 3,
sub
#line 78 "./../pidl/expr.yp"
#line 78 "expr.yp"
{ "($_[2])" }
],
[#Rule 30
'possible_pointer', 1,
sub
#line 82 "./../pidl/expr.yp"
#line 82 "expr.yp"
{ $_[0]->_Lookup($_[1]) }
],
[#Rule 31
'possible_pointer', 2,
sub
#line 84 "./../pidl/expr.yp"
#line 84 "expr.yp"
{ $_[0]->_Dereference($_[2]); "*$_[2]" }
],
[#Rule 32
'var', 1,
sub
#line 88 "./../pidl/expr.yp"
#line 88 "expr.yp"
{ $_[0]->_Use($_[1]) }
],
[#Rule 33
'var', 3,
sub
#line 90 "./../pidl/expr.yp"
#line 90 "expr.yp"
{ $_[0]->_Use("$_[1].$_[3]") }
],
[#Rule 34
'var', 3,
sub
#line 92 "./../pidl/expr.yp"
#line 92 "expr.yp"
{ "($_[2])" }
],
[#Rule 35
'var', 3,
sub
#line 94 "./../pidl/expr.yp"
#line 94 "expr.yp"
{ $_[0]->_Use("*$_[1]"); $_[1]."->".$_[3] }
],
[#Rule 36
'func', 4,
sub
#line 99 "./../pidl/expr.yp"
#line 99 "expr.yp"
{ "$_[1]($_[3])" }
],
[#Rule 37
'opt_args', 0,
sub
#line 104 "./../pidl/expr.yp"
#line 104 "expr.yp"
{ "" }
],
[#Rule 38
@ -1349,7 +1349,7 @@ sub
[#Rule 42
'args', 3,
sub
#line 118 "./../pidl/expr.yp"
#line 118 "expr.yp"
{ "$_[1], $_[3]" }
]
],
@ -1357,7 +1357,7 @@ sub
bless($self,$class);
}
#line 121 "./../pidl/expr.yp"
#line 121 "expr.yp"
package Parse::Pidl::Expr;

View File

@ -2249,7 +2249,31 @@ sub
{{
"TYPE" => "PIPE",
"PROPERTIES" => $_[1],
"DATA" => $_[3],
"NAME" => undef,
"DATA" => {
"TYPE" => "STRUCT",
"PROPERTIES" => $_[1],
"NAME" => undef,
"ELEMENTS" => [{
"NAME" => "count",
"PROPERTIES" => $_[1],
"POINTERS" => 0,
"ARRAY_LEN" => [],
"TYPE" => "uint3264",
"FILE" => $_[0]->YYData->{FILE},
"LINE" => $_[0]->YYData->{LINE},
},{
"NAME" => "array",
"PROPERTIES" => $_[1],
"POINTERS" => 0,
"ARRAY_LEN" => [ "count" ],
"TYPE" => $_[3],
"FILE" => $_[0]->YYData->{FILE},
"LINE" => $_[0]->YYData->{LINE},
}],
"FILE" => $_[0]->YYData->{FILE},
"LINE" => $_[0]->YYData->{LINE},
},
"FILE" => $_[0]->YYData->{FILE},
"LINE" => $_[0]->YYData->{LINE},
}}
@ -2257,13 +2281,13 @@ sub
[#Rule 78
'element_list1', 0,
sub
#line 398 "idl.yp"
#line 422 "idl.yp"
{ [] }
],
[#Rule 79
'element_list1', 3,
sub
#line 400 "idl.yp"
#line 424 "idl.yp"
{ push(@{$_[1]}, $_[2]); $_[1] }
],
[#Rule 80
@ -2281,13 +2305,13 @@ sub
[#Rule 84
'element_list2', 2,
sub
#line 414 "idl.yp"
#line 438 "idl.yp"
{ [ $_[2] ] }
],
[#Rule 85
'element_list2', 4,
sub
#line 416 "idl.yp"
#line 440 "idl.yp"
{ push(@{$_[1]}, $_[4]); $_[1] }
],
[#Rule 86
@ -2296,13 +2320,13 @@ sub
[#Rule 87
'array_len', 3,
sub
#line 422 "idl.yp"
#line 446 "idl.yp"
{ push(@{$_[3]}, "*"); $_[3] }
],
[#Rule 88
'array_len', 4,
sub
#line 424 "idl.yp"
#line 448 "idl.yp"
{ push(@{$_[4]}, "$_[2]"); $_[4] }
],
[#Rule 89
@ -2311,31 +2335,31 @@ sub
[#Rule 90
'property_list', 4,
sub
#line 430 "idl.yp"
#line 454 "idl.yp"
{ FlattenHash([$_[1],$_[3]]); }
],
[#Rule 91
'properties', 1,
sub
#line 434 "idl.yp"
#line 458 "idl.yp"
{ $_[1] }
],
[#Rule 92
'properties', 3,
sub
#line 436 "idl.yp"
#line 460 "idl.yp"
{ FlattenHash([$_[1], $_[3]]); }
],
[#Rule 93
'property', 1,
sub
#line 440 "idl.yp"
#line 464 "idl.yp"
{{ "$_[1]" => "1" }}
],
[#Rule 94
'property', 4,
sub
#line 442 "idl.yp"
#line 466 "idl.yp"
{{ "$_[1]" => "$_[3]" }}
],
[#Rule 95
@ -2344,13 +2368,13 @@ sub
[#Rule 96
'commalisttext', 3,
sub
#line 448 "idl.yp"
#line 472 "idl.yp"
{ "$_[1],$_[3]" }
],
[#Rule 97
'anytext', 0,
sub
#line 453 "idl.yp"
#line 477 "idl.yp"
{ "" }
],
[#Rule 98
@ -2365,91 +2389,91 @@ sub
[#Rule 101
'anytext', 3,
sub
#line 461 "idl.yp"
#line 485 "idl.yp"
{ "$_[1]$_[2]$_[3]" }
],
[#Rule 102
'anytext', 3,
sub
#line 463 "idl.yp"
#line 487 "idl.yp"
{ "$_[1]$_[2]$_[3]" }
],
[#Rule 103
'anytext', 3,
sub
#line 465 "idl.yp"
#line 489 "idl.yp"
{ "$_[1]$_[2]$_[3]" }
],
[#Rule 104
'anytext', 3,
sub
#line 467 "idl.yp"
#line 491 "idl.yp"
{ "$_[1]$_[2]$_[3]" }
],
[#Rule 105
'anytext', 3,
sub
#line 469 "idl.yp"
#line 493 "idl.yp"
{ "$_[1]$_[2]$_[3]" }
],
[#Rule 106
'anytext', 3,
sub
#line 471 "idl.yp"
#line 495 "idl.yp"
{ "$_[1]$_[2]$_[3]" }
],
[#Rule 107
'anytext', 3,
sub
#line 473 "idl.yp"
#line 497 "idl.yp"
{ "$_[1]$_[2]$_[3]" }
],
[#Rule 108
'anytext', 3,
sub
#line 475 "idl.yp"
#line 499 "idl.yp"
{ "$_[1]$_[2]$_[3]" }
],
[#Rule 109
'anytext', 3,
sub
#line 477 "idl.yp"
#line 501 "idl.yp"
{ "$_[1]$_[2]$_[3]" }
],
[#Rule 110
'anytext', 3,
sub
#line 479 "idl.yp"
#line 503 "idl.yp"
{ "$_[1]$_[2]$_[3]" }
],
[#Rule 111
'anytext', 3,
sub
#line 481 "idl.yp"
#line 505 "idl.yp"
{ "$_[1]$_[2]$_[3]" }
],
[#Rule 112
'anytext', 3,
sub
#line 483 "idl.yp"
#line 507 "idl.yp"
{ "$_[1]$_[2]$_[3]" }
],
[#Rule 113
'anytext', 3,
sub
#line 485 "idl.yp"
#line 509 "idl.yp"
{ "$_[1]$_[2]$_[3]" }
],
[#Rule 114
'anytext', 5,
sub
#line 487 "idl.yp"
#line 511 "idl.yp"
{ "$_[1]$_[2]$_[3]$_[4]$_[5]" }
],
[#Rule 115
'anytext', 5,
sub
#line 489 "idl.yp"
#line 513 "idl.yp"
{ "$_[1]$_[2]$_[3]$_[4]$_[5]" }
],
[#Rule 116
@ -2467,7 +2491,7 @@ sub
[#Rule 120
'text', 1,
sub
#line 507 "idl.yp"
#line 531 "idl.yp"
{ "\"$_[1]\"" }
],
[#Rule 121
@ -2481,7 +2505,7 @@ sub
bless($self,$class);
}
#line 519 "idl.yp"
#line 543 "idl.yp"
use Parse::Pidl qw(error);
@ -2619,11 +2643,17 @@ sub parse_file($$)
my $saved_delim = $/;
undef $/;
my $cpp = $ENV{CPP};
my $options = "";
if (! defined $cpp) {
$cpp = "cpp";
if (defined $ENV{CC}) {
$cpp = "$ENV{CC}";
$options = "-E";
} else {
$cpp = "cpp";
}
}
my $includes = join('',map { " -I$_" } @$incdirs);
my $data = `$cpp -D__PIDL__$includes -xc "$filename"`;
my $data = `$cpp $options -D__PIDL__$includes -xc "$filename"`;
$/ = $saved_delim;
return parse_string($data, $filename);

View File

@ -34,12 +34,12 @@ require Exporter;
use vars qw($VERSION);
$VERSION = '0.01';
@ISA = qw(Exporter);
@EXPORT = qw(GetPrevLevel GetNextLevel ContainsDeferred ContainsString);
@EXPORT = qw(GetPrevLevel GetNextLevel ContainsDeferred ContainsPipe ContainsString);
@EXPORT_OK = qw(GetElementLevelTable ParseElement ValidElement align_type mapToScalar ParseType can_contain_deferred is_charset_array);
use strict;
use Parse::Pidl qw(warning fatal);
use Parse::Pidl::Typelist qw(hasType getType expandAlias mapScalarType);
use Parse::Pidl::Typelist qw(hasType getType typeIs expandAlias mapScalarType is_fixed_size_scalar);
use Parse::Pidl::Util qw(has_property property_matches);
# Alignment of the built-in scalar types
@ -66,6 +66,8 @@ my $scalar_alignment = {
'string' => 4,
'string_array' => 4, #???
'time_t' => 4,
'uid_t' => 8,
'gid_t' => 8,
'NTTIME' => 4,
'NTTIME_1sec' => 4,
'NTTIME_hyper' => 8,
@ -81,9 +83,9 @@ my $scalar_alignment = {
'dnsp_string' => 1
};
sub GetElementLevelTable($$)
sub GetElementLevelTable($$$)
{
my ($e, $pointer_default) = @_;
my ($e, $pointer_default, $ms_union) = @_;
my $order = [];
my $is_deferred = 0;
@ -113,6 +115,51 @@ sub GetElementLevelTable($$)
warning($e, "[out] argument `$e->{NAME}' not a pointer") if ($needptrs > $e->{POINTERS});
}
my $allow_pipe = ($e->{PARENT}->{TYPE} eq "FUNCTION");
my $is_pipe = typeIs($e->{TYPE}, "PIPE");
if ($is_pipe) {
if (not $allow_pipe) {
fatal($e, "argument `$e->{NAME}' is a pipe and not allowed on $e->{PARENT}->{TYPE}");
}
if ($e->{POINTERS} > 1) {
fatal($e, "$e->{POINTERS} are not allowed on pipe element $e->{NAME}");
}
if ($e->{POINTERS} < 0) {
fatal($e, "pipe element $e->{NAME} needs pointer");
}
if ($e->{POINTERS} == 1 and pointer_type($e) ne "ref") {
fatal($e, "pointer should be 'ref' on pipe element $e->{NAME}");
}
if (scalar(@size_is) > 0) {
fatal($e, "size_is() on pipe element");
}
if (scalar(@length_is) > 0) {
fatal($e, "length_is() on pipe element");
}
if (scalar(@bracket_array) > 0) {
fatal($e, "brackets on pipe element");
}
if (defined(has_property($e, "subcontext"))) {
fatal($e, "subcontext on pipe element");
}
if (has_property($e, "switch_is")) {
fatal($e, "switch_is on pipe element");
}
if (can_contain_deferred($e->{TYPE})) {
fatal($e, "$e->{TYPE} can_contain_deferred - not allowed on pipe element");
}
}
# Parse the [][][][] style array stuff
for my $i (0 .. $#bracket_array) {
my $d = $bracket_array[$#bracket_array - $i];
@ -257,6 +304,19 @@ sub GetElementLevelTable($$)
}
}
if ($is_pipe) {
push (@$order, {
TYPE => "PIPE",
IS_DEFERRED => 0,
CONTAINS_DEFERRED => 0,
});
my $i = 0;
foreach (@$order) { $_->{LEVEL_INDEX} = $i; $i+=1; }
return $order;
}
if (defined(has_property($e, "subcontext"))) {
my $hdr_size = has_property($e, "subcontext");
my $subsize = has_property($e, "subcontext_size");
@ -307,9 +367,9 @@ sub GetElementLevelTable($$)
return $order;
}
sub GetTypedefLevelTable($$$)
sub GetTypedefLevelTable($$$$)
{
my ($e, $data, $pointer_default) = @_;
my ($e, $data, $pointer_default, $ms_union) = @_;
my $order = [];
@ -427,35 +487,37 @@ sub align_type($)
# Struct/union without body: assume 4
return 4 unless (defined($dt->{ELEMENTS}));
return find_largest_alignment($dt);
} elsif (($dt->{TYPE} eq "PIPE")) {
return 5;
}
die("Unknown data type type $dt->{TYPE}");
}
sub ParseElement($$)
sub ParseElement($$$)
{
my ($e, $pointer_default) = @_;
my ($e, $pointer_default, $ms_union) = @_;
$e->{TYPE} = expandAlias($e->{TYPE});
if (ref($e->{TYPE}) eq "HASH") {
$e->{TYPE} = ParseType($e->{TYPE}, $pointer_default);
$e->{TYPE} = ParseType($e->{TYPE}, $pointer_default, $ms_union);
}
return {
NAME => $e->{NAME},
TYPE => $e->{TYPE},
PROPERTIES => $e->{PROPERTIES},
LEVELS => GetElementLevelTable($e, $pointer_default),
LEVELS => GetElementLevelTable($e, $pointer_default, $ms_union),
REPRESENTATION_TYPE => ($e->{PROPERTIES}->{represent_as} or $e->{TYPE}),
ALIGN => align_type($e->{TYPE}),
ORIGINAL => $e
};
}
sub ParseStruct($$)
sub ParseStruct($$$)
{
my ($struct, $pointer_default) = @_;
my ($struct, $pointer_default, $ms_union) = @_;
my @elements = ();
my $surrounding = undef;
@ -473,7 +535,7 @@ sub ParseStruct($$)
foreach my $x (@{$struct->{ELEMENTS}})
{
my $e = ParseElement($x, $pointer_default);
my $e = ParseElement($x, $pointer_default, $ms_union);
if ($x != $struct->{ELEMENTS}[-1] and
$e->{LEVELS}[0]->{IS_SURROUNDING}) {
fatal($x, "conformant member not at end of struct");
@ -510,8 +572,10 @@ sub ParseStruct($$)
sub ParseUnion($$)
{
my ($e, $pointer_default) = @_;
my ($e, $pointer_default, $ms_union) = @_;
my @elements = ();
my $is_ms_union = $ms_union;
$is_ms_union = 1 if has_property($e, "ms_union");
my $hasdefault = 0;
my $switch_type = has_property($e, "switch_type");
unless (defined($switch_type)) { $switch_type = "uint32"; }
@ -524,6 +588,7 @@ sub ParseUnion($$)
ELEMENTS => undef,
PROPERTIES => $e->{PROPERTIES},
HAS_DEFAULT => $hasdefault,
IS_MS_UNION => $is_ms_union,
ORIGINAL => $e,
ALIGN => undef
} unless defined($e->{ELEMENTS});
@ -536,7 +601,7 @@ sub ParseUnion($$)
if ($x->{TYPE} eq "EMPTY") {
$t = { TYPE => "EMPTY" };
} else {
$t = ParseElement($x, $pointer_default);
$t = ParseElement($x, $pointer_default, $ms_union);
}
if (has_property($x, "default")) {
$t->{CASE} = "default";
@ -561,6 +626,7 @@ sub ParseUnion($$)
ELEMENTS => \@elements,
PROPERTIES => $e->{PROPERTIES},
HAS_DEFAULT => $hasdefault,
IS_MS_UNION => $is_ms_union,
ORIGINAL => $e,
ALIGN => $align
};
@ -568,7 +634,7 @@ sub ParseUnion($$)
sub ParseEnum($$)
{
my ($e, $pointer_default) = @_;
my ($e, $pointer_default, $ms_union) = @_;
return {
TYPE => "ENUM",
@ -580,9 +646,9 @@ sub ParseEnum($$)
};
}
sub ParseBitmap($$)
sub ParseBitmap($$$)
{
my ($e, $pointer_default) = @_;
my ($e, $pointer_default, $ms_union) = @_;
return {
TYPE => "BITMAP",
@ -594,9 +660,60 @@ sub ParseBitmap($$)
};
}
sub ParseType($$)
sub ParsePipe($$$)
{
my ($d, $pointer_default) = @_;
my ($pipe, $pointer_default, $ms_union) = @_;
my $pname = $pipe->{NAME};
$pname = $pipe->{PARENT}->{NAME} unless defined $pname;
if (not defined($pipe->{PROPERTIES})
and defined($pipe->{PARENT}->{PROPERTIES})) {
$pipe->{PROPERTIES} = $pipe->{PARENT}->{PROPERTIES};
}
if (ref($pipe->{DATA}) eq "HASH") {
if (not defined($pipe->{DATA}->{PROPERTIES})
and defined($pipe->{PROPERTIES})) {
$pipe->{DATA}->{PROPERTIES} = $pipe->{PROPERTIES};
}
}
my $struct = ParseStruct($pipe->{DATA}, $pointer_default, $ms_union);
$struct->{ALIGN} = 5;
$struct->{NAME} = "$pname\_chunk";
# 'count' is element [0] and 'array' [1]
my $e = $struct->{ELEMENTS}[1];
# level [0] is of type "ARRAY"
my $l = $e->{LEVELS}[1];
# here we check that pipe elements have a fixed size type
while (defined($l)) {
my $cl = $l;
$l = GetNextLevel($e, $cl);
if ($cl->{TYPE} ne "DATA") {
fatal($pipe, el_name($pipe) . ": pipe contains non DATA level");
}
# for now we only support scalars
next if is_fixed_size_scalar($cl->{DATA_TYPE});
fatal($pipe, el_name($pipe) . ": pipe contains non fixed size type[$cl->{DATA_TYPE}]");
}
return {
TYPE => "PIPE",
NAME => $pipe->{NAME},
DATA => $struct,
PROPERTIES => $pipe->{PROPERTIES},
ORIGINAL => $pipe,
};
}
sub ParseType($$$)
{
my ($d, $pointer_default, $ms_union) = @_;
my $data = {
STRUCT => \&ParseStruct,
@ -604,14 +721,15 @@ sub ParseType($$)
ENUM => \&ParseEnum,
BITMAP => \&ParseBitmap,
TYPEDEF => \&ParseTypedef,
}->{$d->{TYPE}}->($d, $pointer_default);
PIPE => \&ParsePipe,
}->{$d->{TYPE}}->($d, $pointer_default, $ms_union);
return $data;
}
sub ParseTypedef($$)
{
my ($d, $pointer_default) = @_;
my ($d, $pointer_default, $ms_union) = @_;
my $data;
@ -621,7 +739,7 @@ sub ParseTypedef($$)
$d->{PROPERTIES} = $d->{DATA}->{PROPERTIES};
}
$data = ParseType($d->{DATA}, $pointer_default);
$data = ParseType($d->{DATA}, $pointer_default, $ms_union);
$data->{ALIGN} = align_type($d->{NAME});
} else {
$data = getType($d->{DATA});
@ -631,7 +749,7 @@ sub ParseTypedef($$)
NAME => $d->{NAME},
TYPE => $d->{TYPE},
PROPERTIES => $d->{PROPERTIES},
LEVELS => GetTypedefLevelTable($d, $data, $pointer_default),
LEVELS => GetTypedefLevelTable($d, $data, $pointer_default, $ms_union),
DATA => $data,
ORIGINAL => $d
};
@ -644,9 +762,9 @@ sub ParseConst($$)
return $d;
}
sub ParseFunction($$$)
sub ParseFunction($$$$)
{
my ($ndr,$d,$opnum) = @_;
my ($ndr,$d,$opnum,$ms_union) = @_;
my @elements = ();
my $rettype = undef;
my $thisopnum = undef;
@ -659,7 +777,7 @@ sub ParseFunction($$$)
}
foreach my $x (@{$d->{ELEMENTS}}) {
my $e = ParseElement($x, $ndr->{PROPERTIES}->{pointer_default});
my $e = ParseElement($x, $ndr->{PROPERTIES}->{pointer_default}, $ms_union);
push (@{$e->{DIRECTION}}, "in") if (has_property($x, "in"));
push (@{$e->{DIRECTION}}, "out") if (has_property($x, "out"));
@ -720,6 +838,8 @@ sub ParseInterface($)
my @endpoints;
my $opnum = 0;
my $version;
my $ms_union = 0;
$ms_union = 1 if has_property($idl, "ms_union");
if (not has_property($idl, "pointer_default")) {
# MIDL defaults to "ptr" in DCE compatible mode (/osf)
@ -729,11 +849,11 @@ sub ParseInterface($)
foreach my $d (@{$idl->{DATA}}) {
if ($d->{TYPE} eq "FUNCTION") {
push (@functions, ParseFunction($idl, $d, \$opnum));
push (@functions, ParseFunction($idl, $d, \$opnum, $ms_union));
} elsif ($d->{TYPE} eq "CONST") {
push (@consts, ParseConst($idl, $d));
} else {
push (@types, ParseType($d, $idl->{PROPERTIES}->{pointer_default}));
push (@types, ParseType($d, $idl->{PROPERTIES}->{pointer_default}, $ms_union));
FindNestedTypes(\@types, $d);
}
}
@ -823,6 +943,9 @@ sub ContainsString($)
{
my ($e) = @_;
if (property_matches($e, "flag", ".*STR_NULLTERM.*")) {
return 1;
}
foreach my $l (@{$e->{LEVELS}}) {
return 1 if ($l->{TYPE} eq "ARRAY" and $l->{IS_ZERO_TERMINATED});
}
@ -845,6 +968,20 @@ sub ContainsDeferred($$)
return 0;
}
sub ContainsPipe($$)
{
my ($e,$l) = @_;
return 1 if ($l->{TYPE} eq "PIPE");
while ($l = GetNextLevel($e,$l))
{
return 1 if ($l->{TYPE} eq "PIPE");
}
return 0;
}
sub el_name($)
{
my $e = shift;
@ -920,14 +1057,14 @@ my %property_list = (
"gensize" => ["TYPEDEF", "STRUCT", "UNION"],
"value" => ["ELEMENT"],
"flag" => ["ELEMENT", "TYPEDEF", "STRUCT", "UNION", "ENUM", "BITMAP"],
"flag" => ["ELEMENT", "TYPEDEF", "STRUCT", "UNION", "ENUM", "BITMAP", "PIPE"],
# generic
"public" => ["FUNCTION", "TYPEDEF", "STRUCT", "UNION", "ENUM", "BITMAP"],
"nopush" => ["FUNCTION", "TYPEDEF", "STRUCT", "UNION", "ENUM", "BITMAP"],
"nopull" => ["FUNCTION", "TYPEDEF", "STRUCT", "UNION", "ENUM", "BITMAP"],
"public" => ["FUNCTION", "TYPEDEF", "STRUCT", "UNION", "ENUM", "BITMAP", "PIPE"],
"nopush" => ["FUNCTION", "TYPEDEF", "STRUCT", "UNION", "ENUM", "BITMAP", "PIPE"],
"nopull" => ["FUNCTION", "TYPEDEF", "STRUCT", "UNION", "ENUM", "BITMAP", "PIPE"],
"nosize" => ["FUNCTION", "TYPEDEF", "STRUCT", "UNION", "ENUM", "BITMAP"],
"noprint" => ["FUNCTION", "TYPEDEF", "STRUCT", "UNION", "ENUM", "BITMAP", "ELEMENT"],
"noprint" => ["FUNCTION", "TYPEDEF", "STRUCT", "UNION", "ENUM", "BITMAP", "ELEMENT", "PIPE"],
"nopython" => ["FUNCTION", "TYPEDEF", "STRUCT", "UNION", "ENUM", "BITMAP"],
"todo" => ["FUNCTION"],
@ -935,6 +1072,7 @@ my %property_list = (
"switch_is" => ["ELEMENT"],
"switch_type" => ["ELEMENT", "UNION"],
"nodiscriminant" => ["UNION"],
"ms_union" => ["INTERFACE", "UNION"],
"case" => ["ELEMENT"],
"default" => ["ELEMENT"],
@ -1155,11 +1293,16 @@ sub ValidUnion($)
sub ValidPipe($)
{
my ($pipe) = @_;
my $data = $pipe->{DATA};
my $struct = $pipe->{DATA};
ValidProperties($pipe, "PIPE");
fatal($pipe, $pipe->{NAME} . ": 'pipe' is not yet supported by pidl");
$struct->{PARENT} = $pipe;
$struct->{FILE} = $pipe->{FILE} unless defined($struct->{FILE});
$struct->{LINE} = $pipe->{LINE} unless defined($struct->{LINE});
ValidType($struct);
}
#####################################################################

View File

@ -14,6 +14,7 @@ use Exporter;
use strict;
use Parse::Pidl qw(fatal warning error);
use Parse::Pidl::Util qw(has_property ParseExpr);
use Parse::Pidl::NDR qw(ContainsPipe);
use Parse::Pidl::Typelist qw(mapTypeName);
use Parse::Pidl::Samba4 qw(DeclLong);
use Parse::Pidl::Samba4::Header qw(GenerateFunctionInEnv GenerateFunctionOutEnv);
@ -378,6 +379,16 @@ sub ParseInterface($$)
foreach my $fn (@{$if->{FUNCTIONS}}) {
next if has_property($fn, "noopnum");
next if has_property($fn, "todo");
my $skip = 0;
foreach my $e (@{$fn->{ELEMENTS}}) {
if (ContainsPipe($e, $e->{LEVELS}[0])) {
$skip = 1;
last;
}
}
next if $skip;
$self->ParseFunction($if->{NAME}, $fn);
}
$self->pidl_hdr("#endif /* __CLI_$uif\__ */");

View File

@ -199,6 +199,12 @@ sub ParseFunction($$)
pidl "\treturn false;";
pidl "}";
pidl "";
pidl "/*";
pidl " * carry over the pointer count to the reply in case we are";
pidl " * using full pointer. See NDR specification for full pointers";
pidl " */";
pidl "push->ptr_count = pull->ptr_count;";
pidl "";
pidl "ndr_err = call->ndr_push(push, NDR_OUT, r);";
pidl "if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {";
pidl "\ttalloc_free(r);";
@ -288,6 +294,7 @@ sub Parse($$$)
pidl " */";
pidl "";
pidl "#include \"includes.h\"";
pidl "#include \"ntdomain.h\"";
pidl "#include \"$header\"";
pidl_hdr "#include \"$ndr_header\"";
pidl "";

View File

@ -18,12 +18,17 @@ use strict;
use vars qw($VERSION);
$VERSION = '0.01';
# return true if we are using pidl within the samba source tree. This changes
# the names of include files, as some include files (such as ntstatus.h) have
# different paths when installed to the patch in the source tree
sub is_intree()
{
my $srcdir = $ENV{srcdir};
$srcdir = $srcdir ? "$srcdir/" : "";
return 4 if (-f "${srcdir}kdc/kdc.c");
return 3 if (-f "${srcdir}include/smb.h");
return 1 if (-f "${srcdir}kdc/kdc.c");
return 1 if (-d "${srcdir}source4");
return 1 if (-f "${srcdir}include/smb.h");
return 0;
}

View File

@ -215,6 +215,30 @@ sub HeaderUnion($$;$)
pidl $tail if defined($tail);
}
#####################################################################
# parse a pipe
sub HeaderPipe($$;$)
{
my($pipe,$name,$tail) = @_;
my $struct = $pipe->{DATA};
my $e = $struct->{ELEMENTS}[1];
pidl "struct $name;\n";
pidl "struct $struct->{NAME} {\n";
$tab_depth++;
pidl tabs()."uint32_t count;\n";
pidl tabs().mapTypeName($e->{TYPE})." *array;\n";
$tab_depth--;
pidl "}";
if (defined $struct->{PROPERTIES}) {
HeaderProperties($struct->{PROPERTIES}, []);
}
pidl $tail if defined($tail);
}
#####################################################################
# parse a type
sub HeaderType($$$;$)
@ -225,6 +249,7 @@ sub HeaderType($$$;$)
($data->{TYPE} eq "BITMAP") && HeaderBitmap($data, $name);
($data->{TYPE} eq "STRUCT") && HeaderStruct($data, $name, $tail);
($data->{TYPE} eq "UNION") && HeaderUnion($data, $name, $tail);
($data->{TYPE} eq "PIPE") && HeaderPipe($data, $name, $tail);
return;
}
@ -385,6 +410,7 @@ sub HeaderInterface($)
HeaderUnion($t, $t->{NAME}, ";\n\n") if ($t->{TYPE} eq "UNION");
HeaderEnum($t, $t->{NAME}, ";\n\n") if ($t->{TYPE} eq "ENUM");
HeaderBitmap($t, $t->{NAME}) if ($t->{TYPE} eq "BITMAP");
HeaderPipe($t, $t->{NAME}, "\n\n") if ($t->{TYPE} eq "PIPE");
}
foreach my $fn (@{$interface->{FUNCTIONS}}) {

View File

@ -12,6 +12,7 @@ use Exporter;
use Parse::Pidl qw(fatal warning error);
use Parse::Pidl::Util qw(has_property ParseExpr);
use Parse::Pidl::NDR qw(ContainsPipe);
use Parse::Pidl::Typelist qw(mapTypeName);
use Parse::Pidl::Samba4 qw(choose_header is_intree DeclLong);
use Parse::Pidl::Samba4::Header qw(GenerateFunctionInEnv GenerateFunctionOutEnv);
@ -44,6 +45,17 @@ sub new($)
bless($self, $class);
}
sub ParseFunctionHasPipes($$)
{
my ($self, $fn) = @_;
foreach my $e (@{$fn->{ELEMENTS}}) {
return 1 if ContainsPipe($e, $e->{LEVELS}[0]);
}
return 0;
}
sub ParseFunction_r_State($$$$)
{
my ($self, $if, $fn, $name) = @_;
@ -89,10 +101,11 @@ sub ParseFunction_r_Send($$$$)
$self->pidl("");
my $out_params = 0;
foreach (@{$fn->{ELEMENTS}}) {
if (grep(/out/, @{$_->{DIRECTION}})) {
$out_params++;
}
foreach my $e (@{$fn->{ELEMENTS}}) {
next unless grep(/out/, @{$e->{DIRECTION}});
next if ContainsPipe($e, $e->{LEVELS}[0]);
$out_params++;
}
my $submem;
@ -200,6 +213,17 @@ sub ParseFunction_r_Sync($$$$)
my ($self, $if, $fn, $name) = @_;
my $uname = uc $name;
if ($self->ParseFunctionHasPipes($fn)) {
$self->pidl_both("/*");
$self->pidl_both(" * The following function is skipped because");
$self->pidl_both(" * it uses pipes:");
$self->pidl_both(" *");
$self->pidl_both(" * dcerpc_$name\_r()");
$self->pidl_both(" */");
$self->pidl_both("");
return;
}
my $proto = "NTSTATUS dcerpc_$name\_r(struct dcerpc_binding_handle *h, TALLOC_CTX *mem_ctx, struct $name *r)";
$self->fn_declare($proto);
@ -220,49 +244,6 @@ sub ParseFunction_r_Sync($$$$)
$self->pidl("");
}
sub ParseFunction_Compat_Sync($$$$)
{
my ($self, $if, $fn, $name) = @_;
my $uname = uc $name;
my $proto = "NTSTATUS dcerpc_$name\_compat(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, struct $name *r)";
$self->pidl_hdr("#ifdef DCERPC_CALL_$uname\_COMPAT");
$self->pidl_hdr("#define dcerpc_$name(p, m, r) dcerpc_$name\_compat(p, m, r)");
$self->pidl_hdr("#endif /* DCERPC_CALL_$uname\_COMPAT */");
$self->fn_declare($proto);
$self->pidl("{");
$self->indent;
$self->pidl("NTSTATUS status;");
$self->pidl("");
$self->pidl("status = dcerpc_$name\_r(p->binding_handle, mem_ctx, r);");
$self->pidl("");
$self->pidl("if (NT_STATUS_IS_RPC(status)) {");
$self->indent;
$self->pidl("status = NT_STATUS_NET_WRITE_FAULT;");
$self->deindent;
$self->pidl("}");
$self->pidl("");
if (defined($fn->{RETURN_TYPE}) and $fn->{RETURN_TYPE} eq "NTSTATUS") {
$self->pidl("if (NT_STATUS_IS_OK(status)) {");
$self->indent;
$self->pidl("status = r->out.result;");
$self->deindent;
$self->pidl("}");
$self->pidl("");
}
$self->pidl("return status;");
$self->deindent;
$self->pidl("}");
$self->pidl("");
}
sub ElementDirection($)
{
my ($e) = @_;
@ -510,6 +491,9 @@ sub ParseFunction_Send($$$$)
next unless grep(/out/, @{$e->{DIRECTION}});
$self->ParseCopyArgument($fn, $e, "state->orig.out.", "_");
next if ContainsPipe($e, $e->{LEVELS}[0]);
$out_params++;
}
$self->pidl("");
@ -589,6 +573,7 @@ sub ParseFunction_Done($$$$)
$self->pidl("/* Copy out parameters */");
foreach my $e (@{$fn->{ELEMENTS}}) {
next if ContainsPipe($e, $e->{LEVELS}[0]);
next unless (grep(/out/, @{$e->{DIRECTION}}));
$self->ParseOutputArgument($fn, $e,
@ -665,6 +650,17 @@ sub ParseFunction_Sync($$$$)
{
my ($self, $if, $fn, $name) = @_;
if ($self->ParseFunctionHasPipes($fn)) {
$self->pidl_both("/*");
$self->pidl_both(" * The following function is skipped because");
$self->pidl_both(" * it uses pipes:");
$self->pidl_both(" *");
$self->pidl_both(" * dcerpc_$name()");
$self->pidl_both(" */");
$self->pidl_both("");
return;
}
my $uname = uc $name;
my $fn_args = "";
my $fn_str = "NTSTATUS dcerpc_$name";
@ -682,9 +678,7 @@ sub ParseFunction_Sync($$$$)
$fn_args .= ",\n" . $pad . mapTypeName($fn->{RETURN_TYPE}). " *result";
}
$self->pidl_hdr("#ifndef DCERPC_CALL_$uname\_COMPAT");
$self->fn_declare("$fn_str($fn_args)");
$self->pidl_hdr("#endif /* DCERPC_CALL_$uname\_COMPAT */");
$self->pidl("{");
$self->indent;
$self->pidl("struct $name r;");
@ -709,6 +703,7 @@ sub ParseFunction_Sync($$$$)
$self->pidl("/* Return variables */");
foreach my $e (@{$fn->{ELEMENTS}}) {
next if ContainsPipe($e, $e->{LEVELS}[0]);
next unless (grep(/out/, @{$e->{DIRECTION}}));
$self->ParseOutputArgument($fn, $e, "r.", "_", "sync");
@ -734,14 +729,30 @@ sub ParseFunction($$$)
{
my ($self, $if, $fn) = @_;
if ($self->ParseFunctionHasPipes($fn)) {
$self->pidl_both("/*");
$self->pidl_both(" * The following function is skipped because");
$self->pidl_both(" * it uses pipes:");
$self->pidl_both(" *");
$self->pidl_both(" * dcerpc_$fn->{NAME}_r_send()");
$self->pidl_both(" * dcerpc_$fn->{NAME}_r_recv()");
$self->pidl_both(" * dcerpc_$fn->{NAME}_r()");
$self->pidl_both(" *");
$self->pidl_both(" * dcerpc_$fn->{NAME}_send()");
$self->pidl_both(" * dcerpc_$fn->{NAME}_recv()");
$self->pidl_both(" * dcerpc_$fn->{NAME}()");
$self->pidl_both(" */");
$self->pidl_both("");
warning($fn->{ORIGINAL}, "$fn->{NAME}: dcerpc client does not support pipe yet");
return;
}
$self->ParseFunction_r_State($if, $fn, $fn->{NAME});
$self->ParseFunction_r_Send($if, $fn, $fn->{NAME});
$self->ParseFunction_r_Done($if, $fn, $fn->{NAME});
$self->ParseFunction_r_Recv($if, $fn, $fn->{NAME});
$self->ParseFunction_r_Sync($if, $fn, $fn->{NAME});
$self->ParseFunction_Compat_Sync($if, $fn, $fn->{NAME});
foreach my $e (@{$fn->{ELEMENTS}}) {
next unless (grep(/out/, @{$e->{DIRECTION}}));
@ -811,16 +822,6 @@ sub ParseInterface($$)
$self->pidl_hdr("");
}
$self->pidl_hdr("#ifdef DCERPC_IFACE_$ifu\_COMPAT");
foreach my $fn (@{$if->{FUNCTIONS}}) {
next if has_property($fn, "noopnum");
next if has_property($fn, "todo");
my $fnu = uc($fn->{NAME});
$self->pidl_hdr("#define DCERPC_CALL_$fnu\_COMPAT 1");
}
$self->pidl_hdr("#endif /* DCERPC_IFACE_$ifu\_COMPAT */");
$self->pidl_hdr("");
$self->pidl("/* $if->{NAME} - client functions generated by pidl */");
$self->pidl("");

View File

@ -15,7 +15,7 @@ use strict;
use Parse::Pidl::Typelist qw(hasType getType mapTypeName typeHasBody);
use Parse::Pidl::Util qw(has_property ParseExpr ParseExprExt print_uuid unmake_str);
use Parse::Pidl::CUtil qw(get_pointer_to get_value_of get_array_element);
use Parse::Pidl::NDR qw(GetPrevLevel GetNextLevel ContainsDeferred is_charset_array);
use Parse::Pidl::NDR qw(GetPrevLevel GetNextLevel ContainsDeferred ContainsPipe is_charset_array);
use Parse::Pidl::Samba4 qw(is_intree choose_header ArrayDynamicallyAllocated);
use Parse::Pidl::Samba4::Header qw(GenerateFunctionInEnv GenerateFunctionOutEnv EnvSubstituteValue GenerateStructEnv);
use Parse::Pidl qw(warning);
@ -198,6 +198,12 @@ sub ParseArrayPushHeader($$$$$$)
} else {
$size = $length = "ndr_string_length($var_name, sizeof(*$var_name))";
}
if (defined($l->{SIZE_IS})) {
$size = ParseExpr($l->{SIZE_IS}, $env, $e);
}
if (defined($l->{LENGTH_IS})) {
$length = ParseExpr($l->{LENGTH_IS}, $env, $e);
}
} else {
$size = ParseExpr($l->{SIZE_IS}, $env, $e);
$length = ParseExpr($l->{LENGTH_IS}, $env, $e);
@ -206,11 +212,11 @@ sub ParseArrayPushHeader($$$$$$)
if ((!$l->{IS_SURROUNDING}) and $l->{IS_CONFORMANT}) {
$self->pidl("NDR_CHECK(ndr_push_uint3264($ndr, NDR_SCALARS, $size));");
}
if ($l->{IS_VARYING}) {
$self->pidl("NDR_CHECK(ndr_push_uint3264($ndr, NDR_SCALARS, 0));"); # array offset
$self->pidl("NDR_CHECK(ndr_push_uint3264($ndr, NDR_SCALARS, $length));");
}
}
return $length;
}
@ -352,7 +358,7 @@ sub ParseArrayPullHeader($$$$$$)
$self->pidl("}");
}
if ($l->{IS_CONFORMANT} and not $l->{IS_ZERO_TERMINATED}) {
if ($l->{IS_CONFORMANT} and (defined($l->{SIZE_IS}) or not $l->{IS_ZERO_TERMINATED})) {
$self->defer("if ($var_name) {");
$self->defer_indent;
my $size = ParseExprExt($l->{SIZE_IS}, $env, $e->{ORIGINAL},
@ -364,7 +370,7 @@ sub ParseArrayPullHeader($$$$$$)
$self->defer("}");
}
if ($l->{IS_VARYING} and not $l->{IS_ZERO_TERMINATED}) {
if ($l->{IS_VARYING} and (defined($l->{LENGTH_IS}) or not $l->{IS_ZERO_TERMINATED})) {
$self->defer("if ($var_name) {");
$self->defer_indent;
my $length = ParseExprExt($l->{LENGTH_IS}, $env, $e->{ORIGINAL},
@ -630,6 +636,8 @@ sub ParseElementPush($$$$$$)
my $var_name = $env->{$e->{NAME}};
return if ContainsPipe($e, $e->{LEVELS}[0]);
return unless $primitives or ($deferred and ContainsDeferred($e, $e->{LEVELS}[0]));
# Representation type is different from transmit_as
@ -683,6 +691,9 @@ sub ParsePtrPush($$$$$)
$self->pidl("NDR_CHECK(ndr_push_unique_ptr($ndr, $var_name));");
} elsif ($l->{POINTER_TYPE} eq "full") {
$self->pidl("NDR_CHECK(ndr_push_full_ptr($ndr, $var_name));");
} elsif ($l->{POINTER_TYPE} eq "ignore") {
# We don't want this pointer to appear on the wire at all
$self->pidl("NDR_CHECK(ndr_push_uint3264(ndr, NDR_SCALARS, 0));");
} else {
die("Unhandled pointer type $l->{POINTER_TYPE}");
}
@ -770,7 +781,7 @@ sub ParseElementPrint($$$$$)
$var_name = get_pointer_to($var_name);
}
if ($l->{IS_ZERO_TERMINATED}) {
if ($l->{IS_ZERO_TERMINATED} and not defined($l->{LENGTH_IS})) {
$length = "ndr_string_length($var_name, sizeof(*$var_name))";
} else {
$length = ParseExprExt($l->{LENGTH_IS}, $env, $e->{ORIGINAL},
@ -945,6 +956,7 @@ sub ParseMemCtxPullFlags($$$$)
if (($l->{TYPE} eq "POINTER") and ($l->{POINTER_TYPE} eq "ref")) {
my $nl = GetNextLevel($e, $l);
return undef if ($nl->{TYPE} eq "PIPE");
return undef if ($nl->{TYPE} eq "ARRAY");
return undef if (($nl->{TYPE} eq "DATA") and ($nl->{DATA_TYPE} eq "string"));
@ -1149,6 +1161,8 @@ sub ParseElementPull($$$$$$)
my $represent_name;
my $transmit_name;
return if ContainsPipe($e, $e->{LEVELS}[0]);
return unless $primitives or ($deferred and ContainsDeferred($e, $e->{LEVELS}[0]));
if ($e->{REPRESENTATION_TYPE} ne $e->{TYPE}) {
@ -1194,7 +1208,7 @@ sub ParsePtrPull($$$$$)
$self->pidl("\tNDR_PULL_ALLOC($ndr, $var_name);");
$self->pidl("}");
}
return;
} elsif ($l->{POINTER_TYPE} eq "ref" and $l->{LEVEL} eq "EMBEDDED") {
$self->pidl("NDR_CHECK(ndr_pull_ref_ptr($ndr, &_ptr_$e->{NAME}));");
@ -1204,6 +1218,10 @@ sub ParsePtrPull($$$$$)
$self->pidl("NDR_CHECK(ndr_pull_generic_ptr($ndr, &_ptr_$e->{NAME}));");
} elsif ($l->{POINTER_TYPE} eq "relative_short") {
$self->pidl("NDR_CHECK(ndr_pull_relative_ptr_short($ndr, &_ptr_$e->{NAME}));");
} elsif ($l->{POINTER_TYPE} eq "ignore") {
#We want to consume the pointer bytes, but ignore the pointer value
$self->pidl("NDR_CHECK(ndr_pull_uint3264(ndr, NDR_SCALARS, &_ptr_$e->{NAME}));");
$self->pidl("_ptr_$e->{NAME} = 0;");
} else {
die("Unhandled pointer type $l->{POINTER_TYPE}");
}
@ -1211,16 +1229,22 @@ sub ParsePtrPull($$$$$)
$self->pidl("if (_ptr_$e->{NAME}) {");
$self->indent;
# Don't do this for arrays, they're allocated at the actual level
# of the array
unless ($next_is_array or $next_is_string) {
$self->pidl("NDR_PULL_ALLOC($ndr, $var_name);");
if ($l->{POINTER_TYPE} eq "ignore") {
# Don't do anything, we don't want to do the
# allocation, as we forced it to NULL just above, and
# we may not know the declared type anyway.
} else {
# FIXME: Yes, this is nasty.
# We allocate an array twice
# - once just to indicate that it's there,
# - then the real allocation...
$self->pidl("NDR_PULL_ALLOC($ndr, $var_name);");
# Don't do this for arrays, they're allocated at the actual level
# of the array
unless ($next_is_array or $next_is_string) {
$self->pidl("NDR_PULL_ALLOC($ndr, $var_name);");
} else {
# FIXME: Yes, this is nasty.
# We allocate an array twice
# - once just to indicate that it's there,
# - then the real allocation...
$self->pidl("NDR_PULL_ALLOC($ndr, $var_name);");
}
}
#$self->pidl("memset($var_name, 0, sizeof($var_name));");
@ -1255,6 +1279,9 @@ sub ParseStructPushPrimitives($$$$$)
} else {
$size = "ndr_string_length($varname->$e->{NAME}, sizeof(*$varname->$e->{NAME}))";
}
if (defined($e->{LEVELS}[0]->{SIZE_IS})) {
$size = ParseExpr($e->{LEVELS}[0]->{SIZE_IS}, $env, $e->{ORIGINAL});
}
} else {
$size = ParseExpr($e->{LEVELS}[0]->{SIZE_IS}, $env, $e->{ORIGINAL});
}
@ -1688,16 +1715,21 @@ sub ParseUnionPushPrimitives($$$$)
$self->pidl("uint32_t level = ndr_push_get_switch_value($ndr, $varname);");
if (defined($e->{ALIGN})) {
$self->pidl("NDR_CHECK(ndr_push_union_align($ndr, $e->{ALIGN}));");
}
if (defined($e->{SWITCH_TYPE})) {
if (defined($e->{ALIGN})) {
$self->pidl("NDR_CHECK(ndr_push_union_align($ndr, $e->{ALIGN}));");
}
$self->pidl("NDR_CHECK(ndr_push_$e->{SWITCH_TYPE}($ndr, NDR_SCALARS, level));");
}
if (defined($e->{ALIGN})) {
$self->pidl("NDR_CHECK(ndr_push_union_align($ndr, $e->{ALIGN}));");
if ($e->{IS_MS_UNION}) {
$self->pidl("/* ms_union is always aligned to the largest union arm*/");
$self->pidl("NDR_CHECK(ndr_push_align($ndr, $e->{ALIGN}));");
} else {
$self->pidl("NDR_CHECK(ndr_push_union_align($ndr, $e->{ALIGN}));");
}
}
$self->pidl("switch (level) {");
@ -1837,11 +1869,12 @@ sub ParseUnionPullPrimitives($$$$$)
my ($self,$e,$ndr,$varname,$switch_type) = @_;
my $have_default = 0;
if (defined($e->{ALIGN})) {
$self->pidl("NDR_CHECK(ndr_pull_union_align($ndr, $e->{ALIGN}));");
}
if (defined($switch_type)) {
if (defined($e->{ALIGN})) {
$self->pidl("NDR_CHECK(ndr_pull_union_align($ndr, $e->{ALIGN}));");
}
$self->pidl("NDR_CHECK(ndr_pull_$switch_type($ndr, NDR_SCALARS, &_level));");
$self->pidl("if (_level != level) {");
$self->pidl("\treturn ndr_pull_error($ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value %u for $varname at \%s\", _level, __location__);");
@ -1849,7 +1882,12 @@ sub ParseUnionPullPrimitives($$$$$)
}
if (defined($e->{ALIGN})) {
$self->pidl("NDR_CHECK(ndr_pull_union_align($ndr, $e->{ALIGN}));");
if ($e->{IS_MS_UNION}) {
$self->pidl("/* ms_union is always aligned to the largest union arm*/");
$self->pidl("NDR_CHECK(ndr_pull_align($ndr, $e->{ALIGN}));");
} else {
$self->pidl("NDR_CHECK(ndr_pull_union_align($ndr, $e->{ALIGN}));");
}
}
$self->pidl("switch (level) {");
@ -2051,6 +2089,99 @@ $typefamily{TYPEDEF} = {
SIZE_FN_BODY => \&ParseTypedefNdrSize,
};
sub ParsePipePushChunk($$)
{
my ($self, $t) = @_;
my $pipe = $t;
$pipe = $t->{DATA} if ($t->{TYPE} eq "TYPEDEF");
my $struct = $pipe->{DATA};
my $name = "$struct->{NAME}";
my $ndr = "ndr";
my $varname = "r";
my $args = $typefamily{$struct->{TYPE}}->{DECL}->($struct, "push", $name, $varname);
$self->fn_declare("push", $struct, "enum ndr_err_code ndr_push_$name(struct ndr_push *$ndr, int ndr_flags, $args)") or return;
return if has_property($t, "nopush");
$self->pidl("{");
$self->indent;
$self->ParseStructPush($struct, $ndr, $varname);
$self->pidl("");
$self->pidl("NDR_CHECK(ndr_push_pipe_chunk_trailer(ndr, ndr_flags, $varname->count));");
$self->pidl("");
$self->pidl("return NDR_ERR_SUCCESS;");
$self->deindent;
$self->pidl("}");
$self->pidl("");
}
sub ParsePipePullChunk($$)
{
my ($self, $t) = @_;
my $pipe = $t;
$pipe = $t->{DATA} if ($t->{TYPE} eq "TYPEDEF");
my $struct = $pipe->{DATA};
my $name = "$struct->{NAME}";
my $ndr = "ndr";
my $varname = "r";
my $args = $typefamily{$struct->{TYPE}}->{DECL}->($struct, "pull", $name, $varname);
$self->fn_declare("pull", $struct, "enum ndr_err_code ndr_pull_$name(struct ndr_pull *$ndr, int ndr_flags, $args)") or return;
return if has_property($struct, "nopull");
$self->pidl("{");
$self->indent;
$self->ParseStructPull($struct, $ndr, $varname);
$self->pidl("");
$self->pidl("NDR_CHECK(ndr_check_pipe_chunk_trailer($ndr, ndr_flags, $varname->count));");
$self->pidl("");
$self->pidl("return NDR_ERR_SUCCESS;");
$self->deindent;
$self->pidl("}");
$self->pidl("");
}
sub ParsePipePrintChunk($$)
{
my ($self, $t) = @_;
my $pipe = $t;
$pipe = $t->{DATA} if ($t->{TYPE} eq "TYPEDEF");
my $struct = $pipe->{DATA};
my $name = "$struct->{NAME}";
my $ndr = "ndr";
my $varname = "r";
my $args = $typefamily{$struct->{TYPE}}->{DECL}->($struct, "print", $name, $varname);
$self->pidl_hdr("void ndr_print_$name(struct ndr_print *ndr, const char *name, $args);");
return if (has_property($t, "noprint"));
$self->pidl("_PUBLIC_ void ndr_print_$name(struct ndr_print *$ndr, const char *name, $args)");
$self->pidl("{");
$self->indent;
$self->ParseTypePrint($struct, $ndr, $varname);
$self->deindent;
$self->pidl("}");
$self->pidl("");
}
#####################################################################
# parse a function - print side
sub ParseFunctionPrint($$)
@ -2253,6 +2384,7 @@ sub ParseFunctionPull($$)
$e->{LEVELS}[0]->{POINTER_TYPE} eq "ref");
next if (($e->{LEVELS}[1]->{TYPE} eq "DATA") and
($e->{LEVELS}[1]->{DATA_TYPE} eq "string"));
next if ($e->{LEVELS}[1]->{TYPE} eq "PIPE");
next if (($e->{LEVELS}[1]->{TYPE} eq "ARRAY")
and $e->{LEVELS}[1]->{IS_ZERO_TERMINATED});
@ -2268,6 +2400,12 @@ sub ParseFunctionPull($$)
} else {
$self->pidl("memset(r->out.$e->{NAME}, 0, ($size) * sizeof(*r->out.$e->{NAME}));");
}
} elsif ($e->{LEVELS}[1]->{TYPE} eq "ARRAY") {
if (grep(/in/, @{$e->{DIRECTION}})) {
$self->pidl("r->out.$e->{NAME} = r->in.$e->{NAME};");
} else {
$self->pidl("r->out.$e->{NAME} = NULL;");
}
} else {
$self->pidl("NDR_PULL_ALLOC($ndr, r->out.$e->{NAME});");
@ -2326,16 +2464,102 @@ sub AuthServiceStruct($$$)
$self->pidl("");
}
sub ParseGeneratePipeArray($$$)
{
my ($self, $fn, $direction) = @_;
$self->pidl("static const struct ndr_interface_call_pipe $fn->{NAME}\_$direction\_pipes[] = {");
$self->indent;
foreach my $e (@{$fn->{ELEMENTS}}) {
next unless ContainsPipe($e, $e->{LEVELS}[0]);
next unless (grep(/$direction/, @{$e->{DIRECTION}}));
my $cname = "$e->{TYPE}_chunk";
$self->pidl("{");
$self->indent;
$self->pidl("\"$direction.$e->{NAME}\",");
$self->pidl("\"$cname\",");
$self->pidl("sizeof(struct $cname),");
$self->pidl("(ndr_push_flags_fn_t) ndr_push_$cname,");
$self->pidl("(ndr_pull_flags_fn_t) ndr_pull_$cname,");
$self->pidl("(ndr_print_fn_t) ndr_print_$cname,");
$self->deindent;
$self->pidl("},");
}
$self->pidl("{ NULL, NULL, 0, NULL, NULL, NULL }");
$self->deindent;
$self->pidl("};");
$self->pidl("");
}
sub FunctionCallPipes($$)
{
my ($self, $d) = @_;
return if not defined($d->{OPNUM});
my $in_pipes = 0;
my $out_pipes = 0;
foreach my $e (@{$d->{ELEMENTS}}) {
next unless ContainsPipe($e, $e->{LEVELS}[0]);
if (grep(/in/, @{$e->{DIRECTION}})) {
$in_pipes++;
}
if (grep(/out/, @{$e->{DIRECTION}})) {
$out_pipes++;
}
}
if ($in_pipes) {
$self->ParseGeneratePipeArray($d, "in");
}
if ($out_pipes) {
$self->ParseGeneratePipeArray($d, "out");
}
}
sub FunctionCallEntry($$)
{
my ($self, $d) = @_;
return 0 if not defined($d->{OPNUM});
my $in_pipes = 0;
my $out_pipes = 0;
foreach my $e (@{$d->{ELEMENTS}}) {
next unless ContainsPipe($e, $e->{LEVELS}[0]);
if (grep(/in/, @{$e->{DIRECTION}})) {
$in_pipes++;
}
if (grep(/out/, @{$e->{DIRECTION}})) {
$out_pipes++;
}
}
my $in_pipes_ptr = "NULL";
my $out_pipes_ptr = "NULL";
if ($in_pipes) {
$in_pipes_ptr = "$d->{NAME}_in_pipes";
}
if ($out_pipes) {
$out_pipes_ptr = "$d->{NAME}_out_pipes";
}
$self->pidl("\t{");
$self->pidl("\t\t\"$d->{NAME}\",");
$self->pidl("\t\tsizeof(struct $d->{NAME}),");
$self->pidl("\t\t(ndr_push_flags_fn_t) ndr_push_$d->{NAME},");
$self->pidl("\t\t(ndr_pull_flags_fn_t) ndr_pull_$d->{NAME},");
$self->pidl("\t\t(ndr_print_function_t) ndr_print_$d->{NAME},");
$self->pidl("\t\t{ $in_pipes, $in_pipes_ptr },");
$self->pidl("\t\t{ $out_pipes, $out_pipes_ptr },");
$self->pidl("\t},");
return 1;
}
@ -2351,6 +2575,10 @@ sub FunctionTable($$)
return if ($#{$interface->{FUNCTIONS}}+1 == 0);
return unless defined ($interface->{PROPERTIES}->{uuid});
foreach my $d (@{$interface->{INHERITED_FUNCTIONS}},@{$interface->{FUNCTIONS}}) {
$self->FunctionCallPipes($d);
}
$self->pidl("static const struct ndr_interface_call $interface->{NAME}\_calls[] = {");
foreach my $d (@{$interface->{INHERITED_FUNCTIONS}},@{$interface->{FUNCTIONS}}) {
@ -2447,10 +2675,9 @@ sub HeaderInterface($$$)
if (defined $interface->{PROPERTIES}->{uuid}) {
my $name = uc $interface->{NAME};
$self->pidl_hdr("#define NDR_$name\_UUID " .
Parse::Pidl::Util::make_str(lc($interface->{PROPERTIES}->{uuid})));
Parse::Pidl::Util::make_str(lc($interface->{UUID})));
if(!defined $interface->{PROPERTIES}->{version}) { $interface->{PROPERTIES}->{version} = "0.0"; }
$self->pidl_hdr("#define NDR_$name\_VERSION $interface->{PROPERTIES}->{version}");
$self->pidl_hdr("#define NDR_$name\_VERSION $interface->{VERSION}");
$self->pidl_hdr("#define NDR_$name\_NAME \"$interface->{NAME}\"");
@ -2604,6 +2831,20 @@ sub ParseInterface($$$)
# Typedefs
foreach my $d (@{$interface->{TYPES}}) {
if (Parse::Pidl::Typelist::typeIs($d, "PIPE")) {
($needed->{TypeFunctionName("ndr_push", $d)}) &&
$self->ParsePipePushChunk($d);
($needed->{TypeFunctionName("ndr_pull", $d)}) &&
$self->ParsePipePullChunk($d);
($needed->{TypeFunctionName("ndr_print", $d)}) &&
$self->ParsePipePrintChunk($d);
$needed->{TypeFunctionName("ndr_pull", $d)} = 0;
$needed->{TypeFunctionName("ndr_push", $d)} = 0;
$needed->{TypeFunctionName("ndr_print", $d)} = 0;
next;
}
next unless(typeHasBody($d));
($needed->{TypeFunctionName("ndr_push", $d)}) && $self->ParseTypePushFunction($d, "r");
@ -2623,10 +2864,6 @@ sub ParseInterface($$$)
($needed->{"ndr_push_$d->{NAME}"}) && $self->ParseFunctionPush($d);
($needed->{"ndr_pull_$d->{NAME}"}) && $self->ParseFunctionPull($d);
($needed->{"ndr_print_$d->{NAME}"}) && $self->ParseFunctionPrint($d);
# Make sure we don't generate a function twice...
$needed->{"ndr_push_$d->{NAME}"} = $needed->{"ndr_pull_$d->{NAME}"} =
$needed->{"ndr_print_$d->{NAME}"} = 0;
}
$self->FunctionTable($interface);
@ -2749,6 +2986,7 @@ sub NeededType($$$)
my ($t,$needed,$req) = @_;
NeededType($t->{DATA}, $needed, $req) if ($t->{TYPE} eq "TYPEDEF");
NeededType($t->{DATA}, $needed, $req) if ($t->{TYPE} eq "PIPE");
if ($t->{TYPE} eq "STRUCT" or $t->{TYPE} eq "UNION") {
return unless defined($t->{ELEMENTS});
@ -2770,6 +3008,7 @@ sub NeededInterface($$)
my ($interface,$needed) = @_;
NeededFunction($_, $needed) foreach (@{$interface->{FUNCTIONS}});
foreach (reverse @{$interface->{TYPES}}) {
if (has_property($_, "public")) {
$needed->{TypeFunctionName("ndr_pull", $_)} = $needed->{TypeFunctionName("ndr_push", $_)} =
$needed->{TypeFunctionName("ndr_print", $_)} = 1;

View File

@ -77,8 +77,8 @@ sub Boilerplate_Iface($)
my($interface) = shift;
my $name = $interface->{NAME};
my $uname = uc $name;
my $uuid = lc($interface->{PROPERTIES}->{uuid});
my $if_version = $interface->{PROPERTIES}->{version};
my $uuid = lc($interface->{UUID});
my $if_version = $interface->{VERSION};
pidl "
static NTSTATUS $name\__op_bind(struct dcesrv_call_state *dce_call, const struct dcesrv_interface *iface, uint32_t if_version)
@ -251,9 +251,9 @@ static bool $name\__op_interface_by_name(struct dcesrv_interface *iface, const c
return true;
}
return false;
return false;
}
NTSTATUS dcerpc_server_$name\_init(void)
{
NTSTATUS ret;
@ -289,6 +289,9 @@ sub ParseInterface($)
my($interface) = shift;
my $count = 0;
$res .= "NTSTATUS dcerpc_server_$interface->{NAME}\_init(void);\n";
$res .= "\n";
if (!defined $interface->{PROPERTIES}->{uuid}) {
return $res;
}

View File

@ -12,7 +12,7 @@ use strict;
use Parse::Pidl qw(warning fatal error);
use Parse::Pidl::Typelist qw(hasType resolveType getType mapTypeName expandAlias);
use Parse::Pidl::Util qw(has_property ParseExpr unmake_str);
use Parse::Pidl::NDR qw(GetPrevLevel GetNextLevel ContainsDeferred is_charset_array);
use Parse::Pidl::NDR qw(GetPrevLevel GetNextLevel ContainsDeferred ContainsPipe is_charset_array);
use Parse::Pidl::CUtil qw(get_value_of get_pointer_to);
use Parse::Pidl::Samba4 qw(ArrayDynamicallyAllocated);
use Parse::Pidl::Samba4::Header qw(GenerateFunctionInEnv GenerateFunctionOutEnv EnvSubstituteValue GenerateStructEnv);
@ -297,9 +297,14 @@ sub PythonStruct($$$$$$)
$self->pidl("{");
$self->indent;
$self->pidl("$cname *object = ($cname *)py_talloc_get_ptr(py_obj);");
$self->pidl("PyObject *ret;");
$self->pidl("char *retstr;");
$self->pidl("");
$self->pidl("retstr = ndr_print_struct_string(py_talloc_get_mem_ctx(py_obj), (ndr_print_fn_t)ndr_print_$name, \"$name\", object);");
$self->pidl("return PyString_FromString(retstr);");
$self->pidl("ret = PyString_FromString(retstr);");
$self->pidl("talloc_free(retstr);");
$self->pidl("");
$self->pidl("return ret;");
$self->deindent;
$self->pidl("}");
$self->pidl("");
@ -662,6 +667,15 @@ sub Interface($$$)
next if has_property($d, "nopython");
next if has_property($d, "todo");
my $skip = 0;
foreach my $e (@{$d->{ELEMENTS}}) {
if (ContainsPipe($e, $e->{LEVELS}[0])) {
$skip = 1;
last;
}
}
next if $skip;
my $prettyname = $d->{NAME};
$prettyname =~ s/^$interface->{NAME}_//;
@ -890,7 +904,7 @@ sub ConvertObjectFromPythonData($$$$$$;$)
$self->pidl("}");
return;
}
if (expandAlias($actual_ctype->{NAME}) =~ /^(char|u?int[0-9]*|time_t)$/) {
if (expandAlias($actual_ctype->{NAME}) =~ /^(char|u?int[0-9]*|time_t|uid_t|gid_t)$/) {
$self->pidl("PY_CHECK_TYPE(&PyInt_Type, $cvar, $fail);");
$self->pidl("$target = PyInt_AsLong($cvar);");
return;
@ -979,12 +993,15 @@ sub ConvertObjectFromPythonLevel($$$$$$$$)
{
my ($self, $env, $mem_ctx, $py_var, $e, $l, $var_name, $fail) = @_;
my $nl = GetNextLevel($e, $l);
if ($nl and $nl->{TYPE} eq "SUBCONTEXT") {
$nl = GetNextLevel($e, $nl);
}
my $pl = GetPrevLevel($e, $l);
if ($pl and $pl->{TYPE} eq "SUBCONTEXT") {
$pl = GetPrevLevel($e, $pl);
}
if ($l->{TYPE} eq "POINTER") {
if ($nl->{TYPE} eq "DATA" and Parse::Pidl::Typelist::scalar_is_reference($nl->{DATA_TYPE})) {
$self->ConvertObjectFromPythonLevel($env, $mem_ctx, $py_var, $e, $nl, $var_name, $fail);
return;
}
if ($l->{POINTER_TYPE} ne "ref") {
$self->pidl("if ($py_var == Py_None) {");
$self->indent;
@ -997,16 +1014,21 @@ sub ConvertObjectFromPythonLevel($$$$$$$$)
# then this is where we would need to allocate it
if ($l->{POINTER_TYPE} eq "ref") {
$self->pidl("$var_name = talloc_ptrtype($mem_ctx, $var_name);");
} elsif ($nl->{TYPE} eq "DATA" and Parse::Pidl::Typelist::is_scalar($nl->{DATA_TYPE})
and not Parse::Pidl::Typelist::scalar_is_reference($nl->{DATA_TYPE})) {
$self->pidl("$var_name = talloc_ptrtype($mem_ctx, $var_name);");
} else {
$self->pidl("$var_name = NULL;");
}
$self->ConvertObjectFromPythonLevel($env, $mem_ctx, $py_var, $e, $nl, get_value_of($var_name), $fail);
unless ($nl->{TYPE} eq "DATA" and Parse::Pidl::Typelist::scalar_is_reference($nl->{DATA_TYPE})) {
$var_name = get_value_of($var_name);
}
$self->ConvertObjectFromPythonLevel($env, $mem_ctx, $py_var, $e, $nl, $var_name, $fail);
if ($l->{POINTER_TYPE} ne "ref") {
$self->deindent;
$self->pidl("}");
}
} elsif ($l->{TYPE} eq "ARRAY") {
my $pl = GetPrevLevel($e, $l);
if ($pl && $pl->{TYPE} eq "POINTER") {
$var_name = get_pointer_to($var_name);
}
@ -1024,7 +1046,7 @@ sub ConvertObjectFromPythonLevel($$$$$$$$)
$self->pidl("} else {");
$self->indent;
$self->pidl("PyErr_Format(PyExc_TypeError, \"Expected string or unicode object, got %s\", Py_TYPE($py_var)->tp_name);");
$self->pidl("$fail;");
$self->pidl("$fail");
$self->deindent;
$self->pidl("}");
} else {
@ -1040,7 +1062,7 @@ sub ConvertObjectFromPythonLevel($$$$$$$$)
}
$self->pidl("for ($counter = 0; $counter < PyList_GET_SIZE($py_var); $counter++) {");
$self->indent;
$self->ConvertObjectFromPythonLevel($env, $var_name, "PyList_GET_ITEM($py_var, $counter)", $e, GetNextLevel($e, $l), $var_name."[$counter]", $fail);
$self->ConvertObjectFromPythonLevel($env, $var_name, "PyList_GET_ITEM($py_var, $counter)", $e, $nl, $var_name."[$counter]", $fail);
$self->deindent;
$self->pidl("}");
$self->deindent;
@ -1057,15 +1079,15 @@ sub ConvertObjectFromPythonLevel($$$$$$$$)
my $switch_ptr = "$e->{NAME}_switch_$l->{LEVEL_INDEX}";
$self->pidl("{");
$self->indent;
my $union_type = mapTypeName(GetNextLevel($e, $l)->{DATA_TYPE});
my $union_type = mapTypeName($nl->{DATA_TYPE});
$self->pidl("$union_type *$switch_ptr;");
$self->pidl("$switch_ptr = py_export_" . GetNextLevel($e, $l)->{DATA_TYPE} . "($mem_ctx, $switch, $py_var);");
$self->pidl("if ($switch_ptr == NULL) { $fail }");
$self->pidl("$switch_ptr = py_export_" . $nl->{DATA_TYPE} . "($mem_ctx, $switch, $py_var);");
$self->fail_on_null($switch_ptr, $fail);
$self->assign($var_name, "$switch_ptr");
$self->deindent;
$self->pidl("}");
} elsif ($l->{TYPE} eq "SUBCONTEXT") {
$self->ConvertObjectFromPythonLevel($env, $mem_ctx, $py_var, $e, GetNextLevel($e, $l), $var_name, $fail);
$self->ConvertObjectFromPythonLevel($env, $mem_ctx, $py_var, $e, $nl, $var_name, $fail);
} else {
fatal($e->{ORIGINAL}, "unknown level type $l->{TYPE}");
}
@ -1090,7 +1112,7 @@ sub ConvertScalarToPython($$$)
return "PyLong_FromLongLong($cvar)";
}
if ($ctypename =~ /^(char|u?int[0-9]*|time_t)$/) {
if ($ctypename =~ /^(char|u?int[0-9]*|time_t|uid_t|gid_t)$/) {
return "PyInt_FromLong($cvar)";
}
@ -1107,19 +1129,19 @@ sub ConvertScalarToPython($$$)
}
if (($ctypename eq "string" or $ctypename eq "nbt_string" or $ctypename eq "nbt_name" or $ctypename eq "wrepl_nbt_name")) {
return "PyString_FromString_check_null($cvar)";
return "PyString_FromStringOrNULL($cvar)";
}
if (($ctypename eq "dns_string" or $ctypename eq "dns_name")) {
return "PyString_FromString_check_null($cvar)";
return "PyString_FromStringOrNULL($cvar)";
}
# Not yet supported
if ($ctypename eq "string_array") { return "PyCObject_FromTallocPtr($cvar)"; }
if ($ctypename eq "ipv4address") { return "PyString_FromString_check_null($cvar)"; }
if ($ctypename eq "ipv6address") { return "PyString_FromString_check_null($cvar)"; }
if ($ctypename eq "dnsp_name") { return "PyString_FromString_check_null($cvar)"; }
if ($ctypename eq "dnsp_string") { return "PyString_FromString_check_null($cvar)"; }
if ($ctypename eq "ipv4address") { return "PyString_FromStringOrNULL($cvar)"; }
if ($ctypename eq "ipv6address") { return "PyString_FromStringOrNULL($cvar)"; }
if ($ctypename eq "dnsp_name") { return "PyString_FromStringOrNULL($cvar)"; }
if ($ctypename eq "dnsp_string") { return "PyString_FromStringOrNULL($cvar)"; }
if ($ctypename eq "pointer") {
return "PyCObject_FromTallocPtr($cvar)";
}
@ -1174,12 +1196,15 @@ sub ConvertObjectToPythonLevel($$$$$$)
{
my ($self, $mem_ctx, $env, $e, $l, $var_name, $py_var, $fail) = @_;
my $nl = GetNextLevel($e, $l);
if ($nl and $nl->{TYPE} eq "SUBCONTEXT") {
$nl = GetNextLevel($e, $nl);
}
my $pl = GetPrevLevel($e, $l);
if ($pl and $pl->{TYPE} eq "SUBCONTEXT") {
$pl = GetPrevLevel($e, $pl);
}
if ($l->{TYPE} eq "POINTER") {
if ($nl->{TYPE} eq "DATA" and Parse::Pidl::Typelist::scalar_is_reference($nl->{DATA_TYPE})) {
$self->ConvertObjectToPythonLevel($var_name, $env, $e, $nl, $var_name, $py_var, $fail);
return;
}
if ($l->{POINTER_TYPE} ne "ref") {
$self->pidl("if ($var_name == NULL) {");
$self->indent;
@ -1189,13 +1214,16 @@ sub ConvertObjectToPythonLevel($$$$$$)
$self->pidl("} else {");
$self->indent;
}
$self->ConvertObjectToPythonLevel($var_name, $env, $e, $nl, get_value_of($var_name), $py_var, $fail);
my $var_name2 = $var_name;
unless ($nl->{TYPE} eq "DATA" and Parse::Pidl::Typelist::scalar_is_reference($nl->{DATA_TYPE})) {
$var_name2 = get_value_of($var_name);
}
$self->ConvertObjectToPythonLevel($var_name, $env, $e, $nl, $var_name2, $py_var, $fail);
if ($l->{POINTER_TYPE} ne "ref") {
$self->deindent;
$self->pidl("}");
}
} elsif ($l->{TYPE} eq "ARRAY") {
my $pl = GetPrevLevel($e, $l);
if ($pl && $pl->{TYPE} eq "POINTER") {
$var_name = get_pointer_to($var_name);
}
@ -1230,7 +1258,7 @@ sub ConvertObjectToPythonLevel($$$$$$)
$self->indent;
my $member_var = "py_$e->{NAME}_$l->{LEVEL_INDEX}";
$self->pidl("PyObject *$member_var;");
$self->ConvertObjectToPythonLevel($var_name, $env, $e, GetNextLevel($e, $l), $var_name."[$counter]", $member_var, $fail);
$self->ConvertObjectToPythonLevel($var_name, $env, $e, $nl, $var_name."[$counter]", $member_var, $fail);
$self->pidl("PyList_SetItem($py_var, $counter, $member_var);");
$self->deindent;
$self->pidl("}");
@ -1240,7 +1268,7 @@ sub ConvertObjectToPythonLevel($$$$$$)
} elsif ($l->{TYPE} eq "SWITCH") {
$var_name = get_pointer_to($var_name);
my $switch = ParseExpr($l->{SWITCH_IS}, $env, $e);
$self->pidl("$py_var = py_import_" . GetNextLevel($e, $l)->{DATA_TYPE} . "($mem_ctx, $switch, $var_name);");
$self->pidl("$py_var = py_import_" . $nl->{DATA_TYPE} . "($mem_ctx, $switch, $var_name);");
$self->fail_on_null($py_var, $fail);
} elsif ($l->{TYPE} eq "DATA") {
@ -1250,7 +1278,7 @@ sub ConvertObjectToPythonLevel($$$$$$)
my $conv = $self->ConvertObjectToPythonData($mem_ctx, $l->{DATA_TYPE}, $var_name, $e->{ORIGINAL});
$self->pidl("$py_var = $conv;");
} elsif ($l->{TYPE} eq "SUBCONTEXT") {
$self->ConvertObjectToPythonLevel($mem_ctx, $env, $e, GetNextLevel($e, $l), $var_name, $py_var, $fail);
$self->ConvertObjectToPythonLevel($mem_ctx, $env, $e, $nl, $var_name, $py_var, $fail);
} else {
fatal($e->{ORIGINAL}, "Unknown level type $l->{TYPE} $var_name");
}
@ -1273,7 +1301,7 @@ sub Parse($$$$$)
/* Python wrapper functions auto-generated by pidl */
#include <Python.h>
#include \"includes.h\"
#include \"lib/talloc/pytalloc.h\"
#include <pytalloc.h>
#include \"librpc/rpc/pyrpc.h\"
#include \"librpc/rpc/pyrpc_util.h\"
#include \"$hdr\"
@ -1299,6 +1327,7 @@ sub Parse($$$$$)
$self->pidl("");
$self->pidl_hdr("void init$basename(void);");
$self->pidl("void init$basename(void)");
$self->pidl("{");
$self->indent;

View File

@ -8,8 +8,8 @@ package Parse::Pidl::Typelist;
require Exporter;
@ISA = qw(Exporter);
@EXPORT_OK = qw(hasType getType resolveType mapTypeName scalar_is_reference expandAlias
mapScalarType addType typeIs is_signed is_scalar enum_type_fn
bitmap_type_fn mapType typeHasBody
mapScalarType addType typeIs is_signed is_scalar enum_type_fn
bitmap_type_fn mapType typeHasBody is_fixed_size_scalar
);
use vars qw($VERSION);
$VERSION = '0.01';
@ -21,7 +21,13 @@ my %types = ();
my @reference_scalars = (
"string", "string_array", "nbt_string", "dns_string",
"wrepl_nbt_name", "ipv4address", "ipv6address"
"wrepl_nbt_name", "dnsp_name", "dnsp_string",
"ipv4address", "ipv6address"
);
my @non_fixed_size_scalars = (
"string", "string_array", "nbt_string", "dns_string",
"wrepl_nbt_name", "dnsp_name", "dnsp_string"
);
# a list of known scalar types
@ -48,6 +54,8 @@ my %scalars = (
"string" => "const char *",
"string_array" => "const char **",
"time_t" => "time_t",
"uid_t" => "uid_t",
"gid_t" => "gid_t",
"NTTIME" => "NTTIME",
"NTTIME_1sec" => "NTTIME",
"NTTIME_hyper" => "NTTIME",
@ -128,6 +136,7 @@ sub getType($)
return $types{$t};
}
sub typeIs($$);
sub typeIs($$)
{
my ($t,$tt) = @_;
@ -187,6 +196,15 @@ sub is_scalar($)
return 0;
}
sub is_fixed_size_scalar($)
{
my $name = shift;
return 0 unless is_scalar($name);
return 0 if (grep(/^$name$/, @non_fixed_size_scalars));
return 1;
}
sub scalar_is_reference($)
{
my $name = shift;
@ -273,6 +291,7 @@ sub mapType($$)
return "struct $n" if ($t->{TYPE} eq "STRUCT" or $t->{TYPE} eq "INTERFACE");
return "union $n" if ($t->{TYPE} eq "UNION");
return mapScalarType(bitmap_type_fn($t)) if ($t->{TYPE} eq "BITMAP");
return "struct $n" if ($t->{TYPE} eq "PIPE");
die("Unknown type $t->{TYPE}");
}
@ -311,11 +330,12 @@ sub LoadIdl($;$)
}) if (has_property($x, "object"));
foreach my $y (@{$x->{DATA}}) {
if ($y->{TYPE} eq "TYPEDEF"
or $y->{TYPE} eq "UNION"
or $y->{TYPE} eq "STRUCT"
or $y->{TYPE} eq "ENUM"
or $y->{TYPE} eq "BITMAP") {
if ($y->{TYPE} eq "TYPEDEF"
or $y->{TYPE} eq "UNION"
or $y->{TYPE} eq "STRUCT"
or $y->{TYPE} eq "ENUM"
or $y->{TYPE} eq "BITMAP"
or $y->{TYPE} eq "PIPE") {
$y->{BASEFILE} = $basename;
addType($y);
}

View File

@ -270,11 +270,9 @@ sub Bitmap($$$$)
$self->register_type($name, "offset = $dissectorname(tvb, offset, pinfo, tree, drep, \@HF\@, \@PARAM\@);", "FT_UINT$size", "BASE_HEX", "0", "NULL", $size/8);
}
sub ElementLevel($$$$$$$)
sub ElementLevel($$$$$$$$)
{
my ($self,$e,$l,$hf,$myname,$pn,$ifname) = @_;
my $param = 0;
my ($self,$e,$l,$hf,$myname,$pn,$ifname,$param) = @_;
if (defined($self->{conformance}->{dissectorparams}->{$myname})) {
$param = $self->{conformance}->{dissectorparams}->{$myname}->{PARAM};
@ -323,9 +321,19 @@ sub ElementLevel($$$$$$$)
$self->pidl_code("proto_item_append_text(tree, \": %s\", data);");
} elsif (property_matches($e, "flag", ".*LIBNDR_FLAG_STR_SIZE4.*")) {
$self->pidl_code("offset = dissect_ndr_vstring(tvb, offset, pinfo, tree, drep, $bs, $hf, FALSE, NULL);");
} elsif (property_matches($e, "flag", ".*STR_NULLTERM.*")) {
if ($bs == 2) {
$self->pidl_code("offset = dissect_null_term_wstring(tvb, offset, pinfo, tree, drep, $hf , 0);")
} else {
$self->pidl_code("offset = dissect_null_term_string(tvb, offset, pinfo, tree, drep, $hf , 0);")
}
} else {
warn("Unable to handle string with flags $e->{PROPERTIES}->{flag}");
}
} elsif ($l->{DATA_TYPE} eq "DATA_BLOB") {
my $remain = 0;
$remain = 1 if (property_matches($e->{ORIGINAL}, "flag", ".*LIBNDR_FLAG_REMAINING.*"));
$self->pidl_code("offset = dissect_ndr_datablob(tvb, offset, pinfo, tree, drep, $hf, $remain);");
} else {
my $call;
@ -350,27 +358,65 @@ sub ElementLevel($$$$$$$)
$self->pidl_code($call);
}
} elsif ($_->{TYPE} eq "SUBCONTEXT") {
my $varswitch;
if (has_property($e, "switch_is")) {
$varswitch = $e->{PROPERTIES}->{switch_is};
}
my $num_bits = ($l->{HEADER_SIZE}*8);
my $hf2 = $self->register_hf_field($hf."_", "Subcontext length", "$ifname.$pn.$_->{NAME}subcontext", "FT_UINT$num_bits", "BASE_HEX", "NULL", 0, "");
$self->{hf_used}->{$hf2} = 1;
$self->pidl_code("dcerpc_info *di = pinfo->private_data;");
$self->pidl_code("guint$num_bits size;");
$self->pidl_code("int start_offset = offset;");
$self->pidl_code("int conformant = di->conformant_run;");
$self->pidl_code("tvbuff_t *subtvb;");
$self->pidl_code("offset = dissect_ndr_uint$num_bits(tvb, offset, pinfo, tree, drep, $hf, &size);");
$self->pidl_code("proto_tree_add_text(tree, tvb, start_offset, offset - start_offset + size, \"Subcontext size\");");
$self->pidl_code("");
# We need to be able to dissect the length of the context in every case
# and conformant run skips the dissections of scalars ...
$self->pidl_code("if (!conformant) {");
$self->indent;
$self->pidl_code("offset = dissect_ndr_uint$num_bits(tvb, offset, pinfo, tree, drep, $hf2, &size);");
$self->pidl_code("subtvb = tvb_new_subset(tvb, offset, size, -1);");
$self->pidl_code("$myname\_(subtvb, 0, pinfo, tree, drep);");
if ($param ne 0) {
$self->pidl_code("$myname\_(subtvb, 0, pinfo, tree, drep, $param);");
} else {
$self->pidl_code("$myname\_(subtvb, 0, pinfo, tree, drep);");
}
$self->pidl_code("offset += size;");
$self->deindent;
$self->pidl_code("}");
} else {
die("Unknown type `$_->{TYPE}'");
}
}
sub Element($$$)
sub Element($$$$$)
{
my ($self,$e,$pn,$ifname) = @_;
my ($self,$e,$pn,$ifname,$isoruseswitch) = @_;
my $dissectorname = "$ifname\_dissect\_element\_".StripPrefixes($pn, $self->{conformance}->{strip_prefixes})."\_".StripPrefixes($e->{NAME}, $self->{conformance}->{strip_prefixes});
my $call_code = "offset = $dissectorname(tvb, offset, pinfo, tree, drep);";
my ($call_code, $moreparam);
my $param = 0;
if (defined $isoruseswitch) {
my $type = $isoruseswitch->[0];
my $name = $isoruseswitch->[1];
my $switch_dt = getType($type);
my $switch_type;
if ($switch_dt->{DATA}->{TYPE} eq "ENUM") {
$switch_type = "g".Parse::Pidl::Typelist::enum_type_fn($switch_dt->{DATA});
} elsif ($switch_dt->{DATA}->{TYPE} eq "SCALAR") {
$switch_type = "g$e->{SWITCH_TYPE}";
}
$moreparam = ", $switch_type *".$name;
$param = $name;
$call_code = "offset = $dissectorname(tvb, offset, pinfo, tree, drep, &$name);";
} else {
$moreparam = "";
$call_code = "offset = $dissectorname(tvb, offset, pinfo, tree, drep);";
}
my $type = $self->find_type($e->{TYPE});
@ -403,16 +449,24 @@ sub Element($$$)
my $add = "";
my $oldparam = undef;
foreach (@{$e->{LEVELS}}) {
if (defined $_->{SWITCH_IS}) {
$oldparam = $param;
$param = "*$param";
}
next if ($_->{TYPE} eq "SWITCH");
$self->pidl_def("static int $dissectorname$add(tvbuff_t *tvb _U_, int offset _U_, packet_info *pinfo _U_, proto_tree *tree _U_, guint8 *drep _U_);");
$self->pidl_def("static int $dissectorname$add(tvbuff_t *tvb _U_, int offset _U_, packet_info *pinfo _U_, proto_tree *tree _U_, guint8 *drep _U_$moreparam);");
$self->pidl_fn_start("$dissectorname$add");
$self->pidl_code("static int");
$self->pidl_code("$dissectorname$add(tvbuff_t *tvb _U_, int offset _U_, packet_info *pinfo _U_, proto_tree *tree _U_, guint8 *drep _U_)");
$self->pidl_code("$dissectorname$add(tvbuff_t *tvb _U_, int offset _U_, packet_info *pinfo _U_, proto_tree *tree _U_, guint8 *drep _U_$moreparam)");
$self->pidl_code("{");
$self->indent;
$self->ElementLevel($e,$_,$hf,$dissectorname.$add,$pn,$ifname);
$self->ElementLevel($e,$_,$hf,$dissectorname.$add,$pn,$ifname,$param);
if (defined $oldparam) {
$param = $oldparam;
}
$self->pidl_code("");
$self->pidl_code("return offset;");
@ -433,7 +487,7 @@ sub Function($$$)
my %dissectornames;
foreach (@{$fn->{ELEMENTS}}) {
$dissectornames{$_->{NAME}} = $self->Element($_, $fn->{NAME}, $ifname) if not defined($dissectornames{$_->{NAME}});
$dissectornames{$_->{NAME}} = $self->Element($_, $fn->{NAME}, $ifname, undef) if not defined($dissectornames{$_->{NAME}});
}
my $fn_name = $_->{NAME};
@ -534,7 +588,40 @@ sub Struct($$$$)
$self->register_ett("ett_$ifname\_$name");
my $res = "";
($res.="\t".$self->Element($_, $name, $ifname)."\n\n") foreach (@{$e->{ELEMENTS}});
my $varswitchs = {};
# will contain the switch var declaration;
my $vars = [];
foreach (@{$e->{ELEMENTS}}) {
if (has_property($_, "switch_is")) {
$varswitchs->{$_->{PROPERTIES}->{switch_is}} = [];
}
}
foreach (@{$e->{ELEMENTS}}) {
my $switch_info = undef;
my $v = $_->{NAME};
if (scalar(grep {/$v/} keys(%$varswitchs)) == 1) {
# This element is one of the switch attribute
my $switch_dt = getType($_->{TYPE});
my $switch_type;
if ($switch_dt->{DATA}->{TYPE} eq "ENUM") {
$switch_type = "g".Parse::Pidl::Typelist::enum_type_fn($switch_dt->{DATA});
} elsif ($switch_dt->{DATA}->{TYPE} eq "SCALAR") {
$switch_type = "g$e->{SWITCH_TYPE}";
}
push @$vars, "$switch_type $v;";
$switch_info = [ $_->{TYPE}, $v ];
$varswitchs->{$v} = $switch_info;
}
if (has_property($_, "switch_is")) {
my $varswitch = $_->{PROPERTIES}->{switch_is};
$switch_info = $varswitchs->{$varswitch};
}
$res.="\t".$self->Element($_, $name, $ifname, $switch_info)."\n\n";
}
$self->pidl_hdr("int $dissectorname(tvbuff_t *tvb _U_, int offset _U_, packet_info *pinfo _U_, proto_tree *parent_tree _U_, guint8 *drep _U_, int hf_index _U_, guint32 param _U_);");
@ -543,6 +630,7 @@ sub Struct($$$$)
$self->pidl_code("$dissectorname(tvbuff_t *tvb _U_, int offset _U_, packet_info *pinfo _U_, proto_tree *parent_tree _U_, guint8 *drep _U_, int hf_index _U_, guint32 param _U_)");
$self->pidl_code("{");
$self->indent;
$self->pidl_code($_) foreach (@$vars);
$self->pidl_code("proto_item *item = NULL;");
$self->pidl_code("proto_tree *tree = NULL;");
if ($e->{ALIGN} > 1) {
@ -551,7 +639,7 @@ sub Struct($$$$)
$self->pidl_code("int old_offset;");
$self->pidl_code("");
if ($e->{ALIGN} > 1) {
if ($e->{ALIGN} > 1 and not property_matches($e, "flag", ".*LIBNDR_FLAG_NOALIGN.*")) {
$self->pidl_code("ALIGN_TO_$e->{ALIGN}_BYTES;");
}
$self->pidl_code("");
@ -599,7 +687,7 @@ sub Union($$$$)
foreach (@{$e->{ELEMENTS}}) {
$res.="\n\t\t$_->{CASE}:\n";
if ($_->{TYPE} ne "EMPTY") {
$res.="\t\t\t".$self->Element($_, $name, $ifname)."\n";
$res.="\t\t\t".$self->Element($_, $name, $ifname, undef)."\n";
}
$res.="\t\tbreak;\n";
}
@ -623,7 +711,11 @@ sub Union($$$$)
$self->pidl_code("proto_item *item = NULL;");
$self->pidl_code("proto_tree *tree = NULL;");
$self->pidl_code("int old_offset;");
$self->pidl_code("$switch_type level;");
if (!defined $switch_type) {
$self->pidl_code("guint32 level = param;");
} else {
$self->pidl_code("$switch_type level;");
}
$self->pidl_code("");
$self->pidl_code("old_offset = offset;");
@ -636,11 +728,13 @@ sub Union($$$$)
$self->pidl_code("");
$self->pidl_code("offset = $switch_dissect(tvb, offset, pinfo, tree, drep, hf_index, &level);");
if (defined $switch_type) {
$self->pidl_code("offset = $switch_dissect(tvb, offset, pinfo, tree, drep, hf_index, &level);");
if ($e->{ALIGN} > 1) {
$self->pidl_code("ALIGN_TO_$e->{ALIGN}_BYTES;");
$self->pidl_code("");
if ($e->{ALIGN} > 1) {
$self->pidl_code("ALIGN_TO_$e->{ALIGN}_BYTES;");
$self->pidl_code("");
}
}
@ -770,8 +864,8 @@ sub ProcessImport
my @imports = @_;
foreach (@imports) {
next if($_ eq "security");
s/\.idl\"$//;
s/^\"//;
s/\.idl"?$//;
$self->pidl_hdr("#include \"packet-dcerpc-$_\.h\"");
}
$self->pidl_hdr("");
@ -811,7 +905,7 @@ sub ProcessInterface($$)
. ", 0x" . substr($if_uuid, 35, 2) . " }");
$self->pidl_def("};");
my $maj = $x->{VERSION};
my $maj = 0x0000FFFF & $x->{VERSION};
$maj =~ s/\.(.*)$//g;
$self->pidl_def("static guint16 ver_dcerpc_$x->{NAME} = $maj;");
$self->pidl_def("");
@ -820,7 +914,6 @@ sub ProcessInterface($$)
$return_types{$x->{NAME}} = {};
$self->Interface($x);
$self->pidl_code("\n".DumpFunctionTable($x));
foreach (keys %{$return_types{$x->{NAME}}}) {
@ -879,6 +972,7 @@ sub Initialize($$)
$self->register_type("int$bits", "offset = PIDL_dissect_uint$bits(tvb, offset, pinfo, tree, drep, \@HF\@, \@PARAM\@);", "FT_INT$bits", "BASE_DEC", 0, "NULL", $bytes);
}
$self->register_type("hyper", "offset = dissect_ndr_uint64(tvb, offset, pinfo, tree, drep, \@HF\@, NULL);", "FT_UINT64", "BASE_DEC", 0, "NULL", 8);
$self->register_type("udlong", "offset = dissect_ndr_duint32(tvb, offset, pinfo, tree, drep, \@HF\@, NULL);", "FT_UINT64", "BASE_DEC", 0, "NULL", 4);
$self->register_type("bool8", "offset = PIDL_dissect_uint8(tvb, offset, pinfo, tree, drep, \@HF\@, \@PARAM\@);","FT_INT8", "BASE_DEC", 0, "NULL", 1);
$self->register_type("char", "offset = PIDL_dissect_uint8(tvb, offset, pinfo, tree, drep, \@HF\@, \@PARAM\@);","FT_INT8", "BASE_DEC", 0, "NULL", 1);