pidl: Remove declare tests, add more tests for typedef.
[ira/wip.git] / source / pidl / lib / Parse / Pidl / NDR.pm
index d2556cb8e60503639f0da263bac5ac294421b915..80ecec938aad694765229a1ce86737b70a8f7713 100644 (file)
@@ -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);
+@EXPORT_OK = qw(GetElementLevelTable ParseElement ValidElement align_type mapToScalar ParseType can_contain_deferred);
 
 use strict;
 use Parse::Pidl qw(warning fatal);
@@ -113,6 +113,8 @@ sub GetElementLevelTable($)
                my $is_varying = 0;
                my $is_conformant = 0;
                my $is_string = 0;
+               my $is_fixed = 0;
+               my $is_inline = 0;
 
                if ($d eq "*") {
                        $is_conformant = 1;
@@ -136,17 +138,20 @@ 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));
+
                push (@$order, {
                        TYPE => "ARRAY",
                        SIZE_IS => $size,
                        LENGTH_IS => $length,
-                       IS_DEFERRED => "$is_deferred",
-                       IS_SURROUNDING => "$is_surrounding",
-                       IS_ZERO_TERMINATED => "$is_string",
-                       IS_VARYING => "$is_varying",
-                       IS_CONFORMANT => "$is_conformant",
-                       IS_FIXED => (not $is_conformant and Parse::Pidl::Util::is_constant($size)),
-                       IS_INLINE => (not $is_conformant and not Parse::Pidl::Util::is_constant($size))
+                       IS_DEFERRED => $is_deferred,
+                       IS_SURROUNDING => $is_surrounding,
+                       IS_ZERO_TERMINATED => $is_string,
+                       IS_VARYING => $is_varying,
+                       IS_CONFORMANT => $is_conformant,
+                       IS_FIXED => $is_fixed,
+                       IS_INLINE => $is_inline
                });
        }
 
@@ -204,15 +209,15 @@ sub GetElementLevelTable($)
                if ($array_size or $is_string) {
                        push (@$order, {
                                TYPE => "ARRAY",
-                               IS_ZERO_TERMINATED => "$is_string",
                                SIZE_IS => $array_size,
                                LENGTH_IS => $array_length,
-                               IS_DEFERRED => "$is_deferred",
+                               IS_DEFERRED => $is_deferred,
                                IS_SURROUNDING => 0,
-                               IS_VARYING => "$is_varying",
-                               IS_CONFORMANT => "$is_conformant",
+                               IS_ZERO_TERMINATED => $is_string,
+                               IS_VARYING => $is_varying,
+                               IS_CONFORMANT => $is_conformant,
                                IS_FIXED => 0,
-                               IS_INLINE => 0,
+                               IS_INLINE => 0
                        });
 
                        $is_deferred = 0;
@@ -244,22 +249,22 @@ sub GetElementLevelTable($)
        }
 
        if (scalar(@size_is) > 0) {
-               warning($e, "size_is() on non-array element");
+               fatal($e, "size_is() on non-array element");
        }
 
        if (scalar(@length_is) > 0) {
-               warning($e, "length_is() on non-array element");
+               fatal($e, "length_is() on non-array element");
        }
 
        if (has_property($e, "string")) {
-               warning($e, "string() attribute on non-array element");
+               fatal($e, "string() attribute on non-array element");
        }
 
        push (@$order, {
                TYPE => "DATA",
                DATA_TYPE => $e->{TYPE},
                IS_DEFERRED => $is_deferred,
-               CONTAINS_DEFERRED => can_contain_deferred($e),
+               CONTAINS_DEFERRED => can_contain_deferred($e->{TYPE}),
                IS_SURROUNDING => 0 #FIXME
        });
 
@@ -274,18 +279,21 @@ sub GetElementLevelTable($)
 sub can_contain_deferred($)
 {
        sub can_contain_deferred($);
-       my $e = shift;
+       my ($type) = @_;
+
+       return 1 unless (hasType($type)); # assume the worst
 
-       return 0 if (Parse::Pidl::Typelist::is_scalar($e->{TYPE}));
-       return 1 unless (hasType($e->{TYPE})); # assume the worst
+       $type = getType($type);
 
-       my $type = getType($e->{TYPE});
+       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");
 
-       foreach my $x (@{$type->{DATA}->{ELEMENTS}}) {
-               return 1 if ($x->{POINTERS});
-               return 1 if (can_contain_deferred ($x));
+       return 0 unless defined($type->{ELEMENTS});
+
+       foreach (@{$type->{ELEMENTS}}) {
+               return 1 if ($_->{POINTERS});
+               return 1 if (can_contain_deferred ($_->{TYPE}));
        }
        
        return 0;
@@ -344,21 +352,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);
        }
 
@@ -392,6 +404,18 @@ sub ParseStruct($$)
        my @elements = ();
        my $surrounding = undef;
 
+       return {
+               TYPE => "STRUCT",
+               NAME => $struct->{NAME},
+               SURROUNDING_ELEMENT => undef,
+               ELEMENTS => undef,
+               PROPERTIES => $struct->{PROPERTIES},
+               ORIGINAL => $struct,
+               ALIGN => undef
+       } unless defined($struct->{ELEMENTS});
+
+       CheckPointerTypes($struct, $pointer_default);
+
        foreach my $x (@{$struct->{ELEMENTS}}) 
        {
                my $e = ParseElement($x, $pointer_default);
@@ -433,12 +457,23 @@ sub ParseUnion($$)
 {
        my ($e, $pointer_default) = @_;
        my @elements = ();
+       my $hasdefault = 0;
        my $switch_type = has_property($e, "switch_type");
        unless (defined($switch_type)) { $switch_type = "uint32"; }
-
        if (has_property($e, "nodiscriminant")) { $switch_type = undef; }
-       
-       my $hasdefault = 0;
+
+       return {
+               TYPE => "UNION",
+               NAME => $e->{NAME},
+               SWITCH_TYPE => $switch_type,
+               ELEMENTS => undef,
+               PROPERTIES => $e->{PROPERTIES},
+               HAS_DEFAULT => $hasdefault,
+               ORIGINAL => $e
+       } unless defined($e->{ELEMENTS});
+
+       CheckPointerTypes($e, $pointer_default);
+
        foreach my $x (@{$e->{ELEMENTS}}) 
        {
                my $t;
@@ -501,11 +536,6 @@ sub ParseType($$)
 {
        my ($d, $pointer_default) = @_;
 
-       if ($d->{TYPE} eq "STRUCT" or $d->{TYPE} eq "UNION") {
-               return $d if (not defined($d->{ELEMENTS}));
-               CheckPointerTypes($d, $pointer_default);
-       }
-
        my $data = {
                STRUCT => \&ParseStruct,
                UNION => \&ParseUnion,
@@ -589,6 +619,8 @@ sub CheckPointerTypes($$)
 {
        my ($s,$default) = @_;
 
+       return unless defined($s->{ELEMENTS});
+
        foreach my $e (@{$s->{ELEMENTS}}) {
                if ($e->{POINTERS} and not defined(pointer_type($e))) {
                        $e->{PROPERTIES}->{$default} = 1;
@@ -602,6 +634,8 @@ sub FindNestedTypes($$)
        my ($l, $t) = @_;
 
        return if not defined($t->{ELEMENTS});
+       return if ($t->{TYPE} eq "ENUM");
+       return if ($t->{TYPE} eq "BITMAP");
 
        foreach (@{$t->{ELEMENTS}}) {
                if (ref($_->{TYPE}) eq "HASH") {
@@ -618,7 +652,6 @@ sub ParseInterface($)
        my @consts = ();
        my @functions = ();
        my @endpoints;
-       my @declares = ();
        my $opnum = 0;
        my $version;
 
@@ -635,9 +668,7 @@ sub ParseInterface($)
        }
 
        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));
@@ -669,7 +700,6 @@ sub ParseInterface($)
                FUNCTIONS => \@functions,
                CONSTS => \@consts,
                TYPES => \@types,
-               DECLARES => \@declares,
                ENDPOINTS => \@endpoints
        };
 }
@@ -688,6 +718,7 @@ sub Parse($)
        my @ndr = ();
 
        foreach (@{$idl}) {
+               ($_->{TYPE} eq "CPP_QUOTE") && push(@ndr, $_);
                ($_->{TYPE} eq "INTERFACE") && push(@ndr, ParseInterface($_));
                ($_->{TYPE} eq "IMPORT") && push(@ndr, $_);
        }
@@ -1003,6 +1034,8 @@ sub ValidStruct($)
 
        ValidProperties($struct, "STRUCT");
 
+       return unless defined($struct->{ELEMENTS});
+
        foreach my $e (@{$struct->{ELEMENTS}}) {
                $e->{PARENT} = $struct;
                ValidElement($e);
@@ -1020,7 +1053,9 @@ sub ValidUnion($)
        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");
        }
-       
+
+       return unless defined($union->{ELEMENTS});
+
        foreach my $e (@{$union->{ELEMENTS}}) {
                $e->{PARENT} = $union;
 
@@ -1127,7 +1162,7 @@ sub ValidInterface($)
                 $d->{TYPE} eq "STRUCT" or
                 $d->{TYPE} eq "UNION" or 
                 $d->{TYPE} eq "ENUM" or
-            $d->{TYPE} eq "BITMAP") && ValidType($d);
+                $d->{TYPE} eq "BITMAP") && ValidType($d);
        }
 
 }
@@ -1142,7 +1177,7 @@ sub Validate($)
                ($x->{TYPE} eq "INTERFACE") && 
                    ValidInterface($x);
                ($x->{TYPE} eq "IMPORTLIB") &&
-                       warning($x, "importlib() not supported");
+                       fatal($x, "importlib() not supported");
        }
 }