LOOKS OK... pidl: get the pointer types correct when an element has multiple pointers
authorStefan Metzmacher <metze@samba.org>
Fri, 1 Feb 2008 09:30:47 +0000 (10:30 +0100)
committerStefan Metzmacher <metze@samba.org>
Fri, 1 Feb 2008 21:36:05 +0000 (22:36 +0100)
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

source/pidl/lib/Parse/Pidl/NDR.pm
source/pidl/tests/ndr.pl

index 98e8f183a2bd11ac5c2a5094ff7fcdf8f4aad653..7d8907c6b58bb9fa757fda60f3a92e7cb2618414 100644 (file)
@@ -72,9 +72,9 @@ my $scalar_alignment = {
        'ipv4address' => 4
 };
 
-sub GetElementLevelTable($)
+sub GetElementLevelTable($$)
 {
-       my $e = shift;
+       my ($e, $pointer_default) = @_;
 
        my $order = [];
        my $is_deferred = 0;
@@ -157,25 +157,38 @@ 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
+               #
+               if ($i == 1) {
+                       $pt = pointer_type($e);
+               } else {
+                       $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"));
 
@@ -391,7 +404,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
index 7fcc7ef40e66e536005aab8e8af0cc0a6178bbe4..758c3dddb7b536335f3704c1eb3b83831c130bfc 100755 (executable)
@@ -4,7 +4,7 @@
 use strict;
 use warnings;
 
-use Test::More tests => 40;
+use Test::More tests => 46;
 use FindBin qw($RealBin);
 use lib "$RealBin";
 use Util;
@@ -22,7 +22,7 @@ my $e = {
        'PARENT' => { TYPE => 'STRUCT' },
        'LINE' => 42 };
 
-is_deeply(GetElementLevelTable($e), [
+is_deeply(GetElementLevelTable($e, "unique"), [
        {
                'IS_DEFERRED' => 0,
                'LEVEL_INDEX' => 0,
@@ -33,7 +33,7 @@ is_deeply(GetElementLevelTable($e), [
        }
 ]);
 
-my $ne = ParseElement($e, undef);
+my $ne = ParseElement($e, "unique");
 is($ne->{ORIGINAL}, $e);
 is($ne->{NAME}, "v");
 is($ne->{ALIGN}, 1);
@@ -60,7 +60,7 @@ $e = {
        'TYPE' => 'uint8',
        'LINE' => 42 };
 
-is_deeply(GetElementLevelTable($e), [
+is_deeply(GetElementLevelTable($e, "unique"), [
        {
                LEVEL_INDEX => 0,
                IS_DEFERRED => 0,
@@ -90,7 +90,7 @@ $e = {
        'PARENT' => { TYPE => 'STRUCT' },
        'LINE' => 42 };
 
-is_deeply(GetElementLevelTable($e), [
+is_deeply(GetElementLevelTable($e, "unique"), [
        {
                LEVEL_INDEX => 0,
                IS_DEFERRED => 0,
@@ -128,7 +128,7 @@ $e = {
        'PARENT' => { TYPE => 'STRUCT' },
        'LINE' => 42 };
 
-is_deeply(GetElementLevelTable($e), [
+is_deeply(GetElementLevelTable($e, "unique"), [
        {
                LEVEL_INDEX => 0,
                IS_DEFERRED => 0,
@@ -147,6 +147,97 @@ is_deeply(GetElementLevelTable($e), [
        }
 ]);
 
+# Case 3 : ref pointers
+#
+$e = {
+       'FILE' => 'foo.idl',
+       'NAME' => 'v',
+       'PROPERTIES' => {"ref" => 1},
+       'POINTERS' => 3,
+       'TYPE' => 'uint8',
+       'PARENT' => { TYPE => 'STRUCT' },
+       'LINE' => 42 };
+
+is_deeply(GetElementLevelTable($e, "unique"), [
+       {
+               LEVEL_INDEX => 0,
+               IS_DEFERRED => 0,
+               TYPE => 'POINTER',
+               POINTER_TYPE => "ref",
+               POINTER_INDEX => 0,
+               LEVEL => 'EMBEDDED'
+       },
+       {
+               LEVEL_INDEX => 1,
+               IS_DEFERRED => 1,
+               TYPE => 'POINTER',
+               POINTER_TYPE => "unique",
+               POINTER_INDEX => 1,
+               LEVEL => 'EMBEDDED'
+       },
+       {
+               LEVEL_INDEX => 2,
+               IS_DEFERRED => 1,
+               TYPE => 'POINTER',
+               POINTER_TYPE => "unique",
+               POINTER_INDEX => 2,
+               LEVEL => 'EMBEDDED'
+       },
+       {
+               'IS_DEFERRED' => 1,
+               'LEVEL_INDEX' => 3,
+               'DATA_TYPE' => 'uint8',
+               'CONTAINS_DEFERRED' => 0,
+               'TYPE' => 'DATA',
+               'IS_SURROUNDING' => 0,
+       }
+]);
+
+# Case 3 : ref pointers
+#
+$e = {
+       'FILE' => 'foo.idl',
+       'NAME' => 'v',
+       'PROPERTIES' => {"ref" => 1},
+       'POINTERS' => 3,
+       'TYPE' => 'uint8',
+       'PARENT' => { TYPE => 'STRUCT' },
+       'LINE' => 42 };
+
+is_deeply(GetElementLevelTable($e, "ref"), [
+       {
+               LEVEL_INDEX => 0,
+               IS_DEFERRED => 0,
+               TYPE => 'POINTER',
+               POINTER_TYPE => "ref",
+               POINTER_INDEX => 0,
+               LEVEL => 'EMBEDDED'
+       },
+       {
+               LEVEL_INDEX => 1,
+               IS_DEFERRED => 1,
+               TYPE => 'POINTER',
+               POINTER_TYPE => "ref",
+               POINTER_INDEX => 1,
+               LEVEL => 'EMBEDDED'
+       },
+       {
+               LEVEL_INDEX => 2,
+               IS_DEFERRED => 1,
+               TYPE => 'POINTER',
+               POINTER_TYPE => "ref",
+               POINTER_INDEX => 2,
+               LEVEL => 'EMBEDDED'
+       },
+       {
+               'IS_DEFERRED' => 1,
+               'LEVEL_INDEX' => 3,
+               'DATA_TYPE' => 'uint8',
+               'CONTAINS_DEFERRED' => 0,
+               'TYPE' => 'DATA',
+               'IS_SURROUNDING' => 0,
+       }
+]);
 
 # Case 4 : top-level ref pointers
 #
@@ -159,7 +250,7 @@ $e = {
        'PARENT' => { TYPE => 'FUNCTION' },
        'LINE' => 42 };
 
-is_deeply(GetElementLevelTable($e), [
+is_deeply(GetElementLevelTable($e, "unique"), [
        {
                LEVEL_INDEX => 0,
                IS_DEFERRED => 0,
@@ -178,6 +269,190 @@ is_deeply(GetElementLevelTable($e), [
        }
 ]);
 
+# Case 4 : top-level ref pointers, triple with pointer_default("unique")
+#
+$e = {
+       'FILE' => 'foo.idl',
+       'NAME' => 'v',
+       'PROPERTIES' => {"ref" => 1},
+       'POINTERS' => 3,
+       'TYPE' => 'uint8',
+       'PARENT' => { TYPE => 'FUNCTION' },
+       'LINE' => 42 };
+
+is_deeply(GetElementLevelTable($e, "unique"), [
+       {
+               LEVEL_INDEX => 0,
+               IS_DEFERRED => 0,
+               TYPE => 'POINTER',
+               POINTER_TYPE => "ref",
+               POINTER_INDEX => 0,
+               LEVEL => 'TOP'
+       },
+       {
+               LEVEL_INDEX => 1,
+               IS_DEFERRED => 0,
+               TYPE => 'POINTER',
+               POINTER_TYPE => "unique",
+               POINTER_INDEX => 1,
+               LEVEL => 'EMBEDDED'
+       },
+       {
+               LEVEL_INDEX => 2,
+               IS_DEFERRED => 0,
+               TYPE => 'POINTER',
+               POINTER_TYPE => "unique",
+               POINTER_INDEX => 2,
+               LEVEL => 'EMBEDDED'
+       },
+       {
+               'IS_DEFERRED' => 0,
+               'LEVEL_INDEX' => 3,
+               'DATA_TYPE' => 'uint8',
+               'CONTAINS_DEFERRED' => 0,
+               'TYPE' => 'DATA',
+               'IS_SURROUNDING' => 0,
+       }
+]);
+
+# Case 4 : top-level unique pointers, triple with pointer_default("unique")
+#
+$e = {
+       'FILE' => 'foo.idl',
+       'NAME' => 'v',
+       'PROPERTIES' => {"unique" => 1, "in" => 1},
+       'POINTERS' => 3,
+       'TYPE' => 'uint8',
+       'PARENT' => { TYPE => 'FUNCTION' },
+       'LINE' => 42 };
+
+is_deeply(GetElementLevelTable($e, "unique"), [
+       {
+               LEVEL_INDEX => 0,
+               IS_DEFERRED => 0,
+               TYPE => 'POINTER',
+               POINTER_TYPE => "unique",
+               POINTER_INDEX => 0,
+               LEVEL => 'TOP'
+       },
+       {
+               LEVEL_INDEX => 1,
+               IS_DEFERRED => 0,
+               TYPE => 'POINTER',
+               POINTER_TYPE => "unique",
+               POINTER_INDEX => 1,
+               LEVEL => 'EMBEDDED'
+       },
+       {
+               LEVEL_INDEX => 2,
+               IS_DEFERRED => 0,
+               TYPE => 'POINTER',
+               POINTER_TYPE => "unique",
+               POINTER_INDEX => 2,
+               LEVEL => 'EMBEDDED'
+       },
+       {
+               'IS_DEFERRED' => 0,
+               'LEVEL_INDEX' => 3,
+               'DATA_TYPE' => 'uint8',
+               'CONTAINS_DEFERRED' => 0,
+               'TYPE' => 'DATA',
+               'IS_SURROUNDING' => 0,
+       }
+]);
+
+# Case 4 : top-level unique pointers, triple with pointer_default("ref")
+#
+$e = {
+       'FILE' => 'foo.idl',
+       'NAME' => 'v',
+       'PROPERTIES' => {"unique" => 1, "in" => 1},
+       'POINTERS' => 3,
+       'TYPE' => 'uint8',
+       'PARENT' => { TYPE => 'FUNCTION' },
+       'LINE' => 42 };
+
+is_deeply(GetElementLevelTable($e, "ref"), [
+       {
+               LEVEL_INDEX => 0,
+               IS_DEFERRED => 0,
+               TYPE => 'POINTER',
+               POINTER_TYPE => "unique",
+               POINTER_INDEX => 0,
+               LEVEL => 'TOP'
+       },
+       {
+               LEVEL_INDEX => 1,
+               IS_DEFERRED => 0,
+               TYPE => 'POINTER',
+               POINTER_TYPE => "ref",
+               POINTER_INDEX => 1,
+               LEVEL => 'EMBEDDED'
+       },
+       {
+               LEVEL_INDEX => 2,
+               IS_DEFERRED => 0,
+               TYPE => 'POINTER',
+               POINTER_TYPE => "ref",
+               POINTER_INDEX => 2,
+               LEVEL => 'EMBEDDED'
+       },
+       {
+               'IS_DEFERRED' => 0,
+               'LEVEL_INDEX' => 3,
+               'DATA_TYPE' => 'uint8',
+               'CONTAINS_DEFERRED' => 0,
+               'TYPE' => 'DATA',
+               'IS_SURROUNDING' => 0,
+       }
+]);
+
+# Case 4 : top-level ref pointers, triple with pointer_default("ref")
+#
+$e = {
+       'FILE' => 'foo.idl',
+       'NAME' => 'v',
+       'PROPERTIES' => {"ref" => 1},
+       'POINTERS' => 3,
+       'TYPE' => 'uint8',
+       'PARENT' => { TYPE => 'FUNCTION' },
+       'LINE' => 42 };
+
+is_deeply(GetElementLevelTable($e, "ref"), [
+       {
+               LEVEL_INDEX => 0,
+               IS_DEFERRED => 0,
+               TYPE => 'POINTER',
+               POINTER_TYPE => "ref",
+               POINTER_INDEX => 0,
+               LEVEL => 'TOP'
+       },
+       {
+               LEVEL_INDEX => 1,
+               IS_DEFERRED => 0,
+               TYPE => 'POINTER',
+               POINTER_TYPE => "ref",
+               POINTER_INDEX => 1,
+               LEVEL => 'EMBEDDED'
+       },
+       {
+               LEVEL_INDEX => 2,
+               IS_DEFERRED => 0,
+               TYPE => 'POINTER',
+               POINTER_TYPE => "ref",
+               POINTER_INDEX => 2,
+               LEVEL => 'EMBEDDED'
+       },
+       {
+               'IS_DEFERRED' => 0,
+               'LEVEL_INDEX' => 3,
+               'DATA_TYPE' => 'uint8',
+               'CONTAINS_DEFERRED' => 0,
+               'TYPE' => 'DATA',
+               'IS_SURROUNDING' => 0,
+       }
+]);
+
 # representation_type
 $e = {
        'FILE' => 'foo.idl',