diff options
Diffstat (limited to 'tools/pidl/lib/Parse/Pidl/NDR.pm')
-rw-r--r-- | tools/pidl/lib/Parse/Pidl/NDR.pm | 185 |
1 files changed, 121 insertions, 64 deletions
diff --git a/tools/pidl/lib/Parse/Pidl/NDR.pm b/tools/pidl/lib/Parse/Pidl/NDR.pm index f624d2bdc0..8440f0183d 100644 --- a/tools/pidl/lib/Parse/Pidl/NDR.pm +++ b/tools/pidl/lib/Parse/Pidl/NDR.pm @@ -35,7 +35,7 @@ use vars qw($VERSION); $VERSION = '0.01'; @ISA = qw(Exporter); @EXPORT = qw(GetPrevLevel GetNextLevel ContainsDeferred ContainsString); -@EXPORT_OK = qw(GetElementLevelTable ParseElement ValidElement align_type mapToScalar ParseType can_contain_deferred); +@EXPORT_OK = qw(GetElementLevelTable ParseElement ValidElement align_type mapToScalar ParseType can_contain_deferred is_charset_array); use strict; use Parse::Pidl qw(warning fatal); @@ -53,6 +53,7 @@ my $scalar_alignment = { 'int32' => 4, 'uint32' => 4, 'hyper' => 8, + 'double' => 8, 'pointer' => 8, 'dlong' => 4, 'udlong' => 4, @@ -72,9 +73,9 @@ my $scalar_alignment = { 'ipv4address' => 4 }; -sub GetElementLevelTable($) +sub GetElementLevelTable($$) { - my $e = shift; + my ($e, $pointer_default) = @_; my $order = []; my $is_deferred = 0; @@ -141,6 +142,13 @@ sub GetElementLevelTable($) $is_fixed = 1 if (not $is_conformant and Parse::Pidl::Util::is_constant($size)); $is_inline = 1 if (not $is_conformant and not Parse::Pidl::Util::is_constant($size)); + if ($i == 0 and $is_fixed and has_property($e, "string")) { + $is_fixed = 0; + $is_varying = 1; + $is_string = 1; + delete($e->{PROPERTIES}->{string}); + } + push (@$order, { TYPE => "ARRAY", SIZE_IS => $size, @@ -157,32 +165,45 @@ sub GetElementLevelTable($) # Next, all the pointers foreach my $i (1..$e->{POINTERS}) { - my $pt = pointer_type($e); - my $level = "EMBEDDED"; # Top level "ref" pointers do not have a referrent identifier - $level = "TOP" if ( defined($pt) - and $i == 1 - and $e->{PARENT}->{TYPE} eq "FUNCTION"); + $level = "TOP" if ($i == 1 and $e->{PARENT}->{TYPE} eq "FUNCTION"); + + my $pt; + # + # Only the first level gets the pointer type from the + # pointer property, the others get them from + # the pointer_default() interface property + # + # see http://msdn2.microsoft.com/en-us/library/aa378984(VS.85).aspx + # (Here they talk about the rightmost pointer, but testing shows + # they mean the leftmost pointer.) + # + # --metze + # + $pt = pointer_type($e); + if ($i > 1) { + $is_deferred = 1 if ($pt ne "ref" and $e->{PARENT}->{TYPE} eq "FUNCTION"); + $pt = $pointer_default; + } push (@$order, { TYPE => "POINTER", - # for now, there can only be one pointer type per element - POINTER_TYPE => pointer_type($e), + POINTER_TYPE => $pt, POINTER_INDEX => $pointer_idx, IS_DEFERRED => "$is_deferred", LEVEL => $level }); warning($e, "top-level \[out\] pointer `$e->{NAME}' is not a \[ref\] pointer") - if ($i == 1 and pointer_type($e) ne "ref" and + if ($i == 1 and $pt ne "ref" and $e->{PARENT}->{TYPE} eq "FUNCTION" and not has_property($e, "in")); $pointer_idx++; # everything that follows will be deferred - $is_deferred = 1 if ($e->{PARENT}->{TYPE} ne "FUNCTION"); + $is_deferred = 1 if ($level ne "TOP"); my $array_size = shift @size_is; my $array_length; @@ -274,6 +295,22 @@ sub GetElementLevelTable($) return $order; } +sub GetTypedefLevelTable($$$) +{ + my ($e, $data, $pointer_default) = @_; + + my $order = []; + + push (@$order, { + TYPE => "TYPEDEF" + }); + + my $i = 0; + foreach (@$order) { $_->{LEVEL_INDEX} = $i; $i+=1; } + + return $order; +} + ##################################################################### # see if a type contains any deferred data sub can_contain_deferred($) @@ -287,8 +324,6 @@ sub can_contain_deferred($) return 0 if (Parse::Pidl::Typelist::is_scalar($type)); - return 1 if ($type->{TYPE} eq "DECLARE"); # assume the worst - return can_contain_deferred($type->{DATA}) if ($type->{TYPE} eq "TYPEDEF"); return 0 unless defined($type->{ELEMENTS}); @@ -354,21 +389,25 @@ sub align_type($) return $scalar_alignment->{$e->{NAME}}; } + return 0 if ($e eq "EMPTY"); + unless (hasType($e)) { # it must be an external type - all we can do is guess - # print "Warning: assuming alignment of unknown type '$e' is 4\n"; + # warning($e, "assuming alignment of unknown type '$e' is 4"); return 4; } my $dt = getType($e); - if ($dt->{TYPE} eq "TYPEDEF" or $dt->{TYPE} eq "DECLARE") { + if ($dt->{TYPE} eq "TYPEDEF") { return align_type($dt->{DATA}); } elsif ($dt->{TYPE} eq "ENUM") { return align_type(Parse::Pidl::Typelist::enum_type_fn($dt)); } elsif ($dt->{TYPE} eq "BITMAP") { return align_type(Parse::Pidl::Typelist::bitmap_type_fn($dt)); } elsif (($dt->{TYPE} eq "STRUCT") or ($dt->{TYPE} eq "UNION")) { + # Struct/union without body: assume 4 + return 4 unless (defined($dt->{ELEMENTS})); return find_largest_alignment($dt); } @@ -389,7 +428,7 @@ sub ParseElement($$) NAME => $e->{NAME}, TYPE => $e->{TYPE}, PROPERTIES => $e->{PROPERTIES}, - LEVELS => GetElementLevelTable($e), + LEVELS => GetElementLevelTable($e, $pointer_default), REPRESENTATION_TYPE => ($e->{PROPERTIES}->{represent_as} or $e->{TYPE}), ALIGN => align_type($e->{TYPE}), ORIGINAL => $e @@ -560,6 +599,7 @@ sub ParseTypedef($$) NAME => $d->{NAME}, TYPE => $d->{TYPE}, PROPERTIES => $d->{PROPERTIES}, + LEVELS => GetTypedefLevelTable($d, $data, $pointer_default), DATA => $data, ORIGINAL => $d }; @@ -579,7 +619,7 @@ sub ParseFunction($$$) my $rettype = undef; my $thisopnum = undef; - CheckPointerTypes($d, $ndr->{PROPERTIES}->{pointer_default_top}); + CheckPointerTypes($d, "ref"); if (not defined($d->{PROPERTIES}{noopnum})) { $thisopnum = ${$opnum}; @@ -621,7 +661,7 @@ sub CheckPointerTypes($$) foreach my $e (@{$s->{ELEMENTS}}) { if ($e->{POINTERS} and not defined(pointer_type($e))) { - $e->{PROPERTIES}->{$default} = 1; + $e->{PROPERTIES}->{$default} = '1'; } } } @@ -631,7 +671,7 @@ sub FindNestedTypes($$) sub FindNestedTypes($$); my ($l, $t) = @_; - return if not defined($t->{ELEMENTS}); + return unless defined($t->{ELEMENTS}); return if ($t->{TYPE} eq "ENUM"); return if ($t->{TYPE} eq "BITMAP"); @@ -650,7 +690,6 @@ sub ParseInterface($) my @consts = (); my @functions = (); my @endpoints; - my @declares = (); my $opnum = 0; my $version; @@ -660,16 +699,8 @@ sub ParseInterface($) $idl->{PROPERTIES}->{pointer_default} = "unique"; } - if (not has_property($idl, "pointer_default_top")) { - $idl->{PROPERTIES}->{pointer_default_top} = "ref"; - } else { - warning($idl, "pointer_default_top() is a pidl extension and should not be used"); - } - foreach my $d (@{$idl->{DATA}}) { - if ($d->{TYPE} eq "DECLARE") { - push (@declares, $d); - } elsif ($d->{TYPE} eq "FUNCTION") { + if ($d->{TYPE} eq "FUNCTION") { push (@functions, ParseFunction($idl, $d, \$opnum)); } elsif ($d->{TYPE} eq "CONST") { push (@consts, ParseConst($idl, $d)); @@ -682,14 +713,19 @@ sub ParseInterface($) $version = "0.0"; if(defined $idl->{PROPERTIES}->{version}) { - $version = $idl->{PROPERTIES}->{version}; + my @if_version = split(/\./, $idl->{PROPERTIES}->{version}); + if ($if_version[0] == $idl->{PROPERTIES}->{version}) { + $version = $idl->{PROPERTIES}->{version}; + } else { + $version = $if_version[1] << 16 | $if_version[0]; + } } # If no endpoint is set, default to the interface name as a named pipe if (!defined $idl->{PROPERTIES}->{endpoint}) { push @endpoints, "\"ncacn_np:[\\\\pipe\\\\" . $idl->{NAME} . "]\""; } else { - @endpoints = split / /, $idl->{PROPERTIES}->{endpoint}; + @endpoints = split /,/, $idl->{PROPERTIES}->{endpoint}; } return { @@ -701,7 +737,6 @@ sub ParseInterface($) FUNCTIONS => \@functions, CONSTS => \@consts, TYPES => \@types, - DECLARES => \@declares, ENDPOINTS => \@endpoints }; } @@ -785,20 +820,21 @@ sub ContainsDeferred($$) sub el_name($) { my $e = shift; + my $name = "<ANONYMOUS>"; - if ($e->{PARENT} && $e->{PARENT}->{NAME}) { - return "$e->{PARENT}->{NAME}.$e->{NAME}"; - } + $name = $e->{NAME} if defined($e->{NAME}); - if ($e->{PARENT} && $e->{PARENT}->{PARENT}->{NAME}) { - return "$e->{PARENT}->{PARENT}->{NAME}.$e->{NAME}"; + if (defined($e->{PARENT}) and defined($e->{PARENT}->{NAME})) { + return "$e->{PARENT}->{NAME}.$name"; } - if ($e->{PARENT}) { - return "$e->{PARENT}->{NAME}.$e->{NAME}"; + if (defined($e->{PARENT}) and + defined($e->{PARENT}->{PARENT}) and + defined($e->{PARENT}->{PARENT}->{NAME})) { + return "$e->{PARENT}->{PARENT}->{NAME}.$name"; } - return $e->{NAME}; + return $name; } ################################### @@ -826,9 +862,10 @@ my %property_list = ( "uuid" => ["INTERFACE"], "endpoint" => ["INTERFACE"], "pointer_default" => ["INTERFACE"], - "pointer_default_top" => ["INTERFACE"], "helper" => ["INTERFACE"], + "pyhelper" => ["INTERFACE"], "authservice" => ["INTERFACE"], + "restricted" => ["INTERFACE"], # dcom "object" => ["INTERFACE"], @@ -849,24 +886,25 @@ my %property_list = ( "unique" => ["ELEMENT"], "ignore" => ["ELEMENT"], "relative" => ["ELEMENT"], - "relative_base" => ["TYPEDEF"], + "null_is_ffffffff" => ["ELEMENT"], + "relative_base" => ["TYPEDEF", "STRUCT", "UNION"], - "gensize" => ["TYPEDEF"], + "gensize" => ["TYPEDEF", "STRUCT", "UNION"], "value" => ["ELEMENT"], - "flag" => ["ELEMENT", "TYPEDEF"], + "flag" => ["ELEMENT", "TYPEDEF", "STRUCT", "UNION", "ENUM", "BITMAP"], # generic - "public" => ["FUNCTION", "TYPEDEF"], - "nopush" => ["FUNCTION", "TYPEDEF"], - "nopull" => ["FUNCTION", "TYPEDEF"], - "nosize" => ["FUNCTION", "TYPEDEF"], - "noprint" => ["FUNCTION", "TYPEDEF"], - "noejs" => ["FUNCTION", "TYPEDEF"], + "public" => ["FUNCTION", "TYPEDEF", "STRUCT", "UNION", "ENUM", "BITMAP"], + "nopush" => ["FUNCTION", "TYPEDEF", "STRUCT", "UNION", "ENUM", "BITMAP"], + "nopull" => ["FUNCTION", "TYPEDEF", "STRUCT", "UNION", "ENUM", "BITMAP"], + "nosize" => ["FUNCTION", "TYPEDEF", "STRUCT", "UNION", "ENUM", "BITMAP"], + "noprint" => ["FUNCTION", "TYPEDEF", "STRUCT", "UNION", "ENUM", "BITMAP", "ELEMENT"], + "todo" => ["FUNCTION"], # union "switch_is" => ["ELEMENT"], - "switch_type" => ["ELEMENT", "TYPEDEF"], - "nodiscriminant" => ["TYPEDEF"], + "switch_type" => ["ELEMENT", "UNION"], + "nodiscriminant" => ["UNION"], "case" => ["ELEMENT"], "default" => ["ELEMENT"], @@ -879,15 +917,15 @@ my %property_list = ( "compression" => ["ELEMENT"], # enum - "enum8bit" => ["TYPEDEF"], - "enum16bit" => ["TYPEDEF"], - "v1_enum" => ["TYPEDEF"], + "enum8bit" => ["ENUM"], + "enum16bit" => ["ENUM"], + "v1_enum" => ["ENUM"], # bitmap - "bitmap8bit" => ["TYPEDEF"], - "bitmap16bit" => ["TYPEDEF"], - "bitmap32bit" => ["TYPEDEF"], - "bitmap64bit" => ["TYPEDEF"], + "bitmap8bit" => ["BITMAP"], + "bitmap16bit" => ["BITMAP"], + "bitmap32bit" => ["BITMAP"], + "bitmap64bit" => ["BITMAP"], # array "range" => ["ELEMENT"], @@ -911,7 +949,7 @@ sub ValidProperties($$) unless defined($property_list{$key}); fatal($e, el_name($e) . ": property '$key' not allowed on '$t'") - unless grep($t, @{$property_list{$key}}); + unless grep(/^$t$/, @{$property_list{$key}}); } } @@ -1052,8 +1090,9 @@ sub ValidUnion($) ValidProperties($union,"UNION"); - if (has_property($union->{PARENT}, "nodiscriminant") and has_property($union->{PARENT}, "switch_type")) { - fatal($union->{PARENT}, $union->{PARENT}->{NAME} . ": switch_type() on union without discriminant"); + if (has_property($union->{PARENT}, "nodiscriminant") and + has_property($union->{PARENT}, "switch_type")) { + fatal($union->{PARENT}, $union->{PARENT}->{NAME} . ": switch_type(" . $union->{PARENT}->{PROPERTIES}->{switch_type} . ") on union without discriminant"); } return unless defined($union->{ELEMENTS}); @@ -1072,7 +1111,7 @@ sub ValidUnion($) } if (has_property($e, "ref")) { - fatal($e, el_name($e) . " : embedded ref pointers are not supported yet\n"); + fatal($e, el_name($e) . ": embedded ref pointers are not supported yet\n"); } @@ -1091,6 +1130,9 @@ sub ValidTypedef($) $data->{PARENT} = $typedef; + $data->{FILE} = $typedef->{FILE} unless defined($data->{FILE}); + $data->{LINE} = $typedef->{LINE} unless defined($data->{LINE}); + ValidType($data) if (ref($data) eq "HASH"); } @@ -1183,4 +1225,19 @@ sub Validate($) } } +sub is_charset_array($$) +{ + my ($e,$l) = @_; + + return 0 if ($l->{TYPE} ne "ARRAY"); + + my $nl = GetNextLevel($e,$l); + + return 0 unless ($nl->{TYPE} eq "DATA"); + + return has_property($e, "charset"); +} + + + 1; |