pyldb: avoid segfault when adding an element with no name
[kai/samba-autobuild/.git] / pidl / lib / Parse / Pidl / NDR.pm
index a36f6380924977dd1285e0099e7ae16e988fc0c0..003156e3a11ef7efce7195afe0cb4e12c4ba183d 100644 (file)
@@ -34,12 +34,12 @@ require Exporter;
 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 is_charset_array);
+@EXPORT = qw(GetPrevLevel GetNextLevel ContainsDeferred ContainsPipe ContainsString);
+@EXPORT_OK = qw(GetElementLevelTable ParseElement ReturnTypeElement 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);
+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
@@ -50,8 +50,12 @@ my $scalar_alignment = {
        'uint8' => 1,
        'int16' => 2,
        'uint16' => 2,
+       'int1632' => 3,
+       'uint1632' => 3,
        'int32' => 4,
        'uint32' => 4,
+       'int3264' => 5,
+       'uint3264' => 5,
        'hyper' => 8,
        'double' => 8,
        'pointer' => 8,
@@ -62,20 +66,26 @@ 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,
        'WERROR' => 4,
        'NTSTATUS' => 4,
        'COMRESULT' => 4,
+       'dns_string' => 4,
        'nbt_string' => 4,
        'wrepl_nbt_name' => 4,
-       'ipv4address' => 4
+       'ipv4address' => 4,
+       'ipv6address' => 4, #16?
+       'dnsp_name' => 1,
+       'dnsp_string' => 1
 };
 
-sub GetElementLevelTable($$)
+sub GetElementLevelTable($$$)
 {
-       my ($e, $pointer_default) = @_;
+       my ($e, $pointer_default, $ms_union) = @_;
 
        my $order = [];
        my $is_deferred = 0;
@@ -99,12 +109,57 @@ sub GetElementLevelTable($$)
        if (has_property($e, "out")) {
                my $needptrs = 1;
 
-               if (has_property($e, "string")) { $needptrs++; }
+               if (has_property($e, "string") and not has_property($e, "in")) { $needptrs++; }
                if ($#bracket_array >= 0) { $needptrs = 0; }
 
                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];
@@ -116,10 +171,15 @@ sub GetElementLevelTable($$)
                my $is_string = 0;
                my $is_fixed = 0;
                my $is_inline = 0;
+               my $is_to_null = 0;
 
                if ($d eq "*") {
                        $is_conformant = 1;
                        if ($size = shift @size_is) {
+                               if ($e->{POINTERS} < 1 and has_property($e, "string")) {
+                                       $is_string = 1;
+                                       delete($e->{PROPERTIES}->{string});
+                               }
                        } elsif ((scalar(@size_is) == 0) and has_property($e, "string")) {
                                $is_string = 1;
                                delete($e->{PROPERTIES}->{string});
@@ -149,6 +209,10 @@ sub GetElementLevelTable($$)
                        delete($e->{PROPERTIES}->{string});
                }
 
+               if (has_property($e, "to_null")) {
+                       $is_to_null = 1;
+               }
+
                push (@$order, {
                        TYPE => "ARRAY",
                        SIZE_IS => $size,
@@ -159,7 +223,8 @@ sub GetElementLevelTable($$)
                        IS_VARYING => $is_varying,
                        IS_CONFORMANT => $is_conformant,
                        IS_FIXED => $is_fixed,
-                       IS_INLINE => $is_inline
+                       IS_INLINE => $is_inline,
+                       IS_TO_NULL => $is_to_null
                });
        }
 
@@ -245,6 +310,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");
@@ -295,9 +373,9 @@ sub GetElementLevelTable($$)
        return $order;
 }
 
-sub GetTypedefLevelTable($$$)
+sub GetTypedefLevelTable($$$$)
 {
-       my ($e, $data, $pointer_default) = @_;
+       my ($e, $data, $pointer_default, $ms_union) = @_;
 
        my $order = [];
 
@@ -347,6 +425,7 @@ sub pointer_type($)
        return "sptr" if (has_property($e, "sptr"));
        return "unique" if (has_property($e, "unique"));
        return "relative" if (has_property($e, "relative"));
+       return "relative_short" if (has_property($e, "relative_short"));
        return "ignore" if (has_property($e, "ignore"));
 
        return undef;
@@ -363,7 +442,10 @@ sub find_largest_alignment($)
                my $a = 1;
 
                if ($e->{POINTERS}) {
-                       $a = 4; 
+                       # this is a hack for NDR64
+                       # the NDR layer translates this into
+                       # an alignment of 4 for NDR and 8 for NDR64
+                       $a = 5;
                } elsif (has_property($e, "subcontext")) { 
                        $a = 1;
                } elsif (has_property($e, "transmit_as")) {
@@ -401,6 +483,8 @@ sub align_type($)
 
        if ($dt->{TYPE} eq "TYPEDEF") {
                return align_type($dt->{DATA});
+       } elsif ($dt->{TYPE} eq "CONFORMANCE") {
+               return $dt->{DATA}->{ALIGN};
        } elsif ($dt->{TYPE} eq "ENUM") {
                return align_type(Parse::Pidl::Typelist::enum_type_fn($dt));
        } elsif ($dt->{TYPE} eq "BITMAP") {
@@ -409,35 +493,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;
 
@@ -455,7 +541,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");
@@ -492,8 +578,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"; }
@@ -506,7 +594,9 @@ sub ParseUnion($$)
                ELEMENTS => undef,
                PROPERTIES => $e->{PROPERTIES},
                HAS_DEFAULT => $hasdefault,
-               ORIGINAL => $e
+               IS_MS_UNION => $is_ms_union,
+               ORIGINAL => $e,
+               ALIGN => undef
        } unless defined($e->{ELEMENTS});
 
        CheckPointerTypes($e, $pointer_default);
@@ -517,7 +607,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";
@@ -530,6 +620,11 @@ sub ParseUnion($$)
                push @elements, $t;
        }
 
+       my $align = undef;
+       if ($e->{NAME}) {
+               $align = align_type($e->{NAME});
+       }
+
        return {
                TYPE => "UNION",
                NAME => $e->{NAME},
@@ -537,13 +632,15 @@ sub ParseUnion($$)
                ELEMENTS => \@elements,
                PROPERTIES => $e->{PROPERTIES},
                HAS_DEFAULT => $hasdefault,
-               ORIGINAL => $e
+               IS_MS_UNION => $is_ms_union,
+               ORIGINAL => $e,
+               ALIGN => $align
        };
 }
 
 sub ParseEnum($$)
 {
-       my ($e, $pointer_default) = @_;
+       my ($e, $pointer_default, $ms_union) = @_;
 
        return {
                TYPE => "ENUM",
@@ -555,9 +652,9 @@ sub ParseEnum($$)
        };
 }
 
-sub ParseBitmap($$)
+sub ParseBitmap($$$)
 {
-       my ($e, $pointer_default) = @_;
+       my ($e, $pointer_default, $ms_union) = @_;
 
        return {
                TYPE => "BITMAP",
@@ -569,9 +666,60 @@ sub ParseBitmap($$)
        };
 }
 
-sub ParseType($$)
+sub ParsePipe($$$)
+{
+       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) = @_;
+       my ($d, $pointer_default, $ms_union) = @_;
 
        my $data = {
                STRUCT => \&ParseStruct,
@@ -579,27 +727,35 @@ 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) = @_;
 
-       if (defined($d->{DATA}->{PROPERTIES}) && !defined($d->{PROPERTIES})) {
-               $d->{PROPERTIES} = $d->{DATA}->{PROPERTIES};
-       }
+       my $data;
 
-       my $data = ParseType($d->{DATA}, $pointer_default);
-       $data->{ALIGN} = align_type($d->{NAME});
+       if (ref($d->{DATA}) eq "HASH") {
+               if (defined($d->{DATA}->{PROPERTIES})
+                   and not defined($d->{PROPERTIES})) {
+                       $d->{PROPERTIES} = $d->{DATA}->{PROPERTIES};
+               }
+
+               $data = ParseType($d->{DATA}, $pointer_default, $ms_union);
+               $data->{ALIGN} = align_type($d->{NAME});
+       } else {
+               $data = getType($d->{DATA});
+       }
 
        return {
                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
        };
@@ -612,9 +768,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;
@@ -627,7 +783,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"));
 
@@ -638,14 +794,10 @@ sub ParseFunction($$$)
                $rettype = expandAlias($d->{RETURN_TYPE});
        }
        
-       my $async = 0;
-       if (has_property($d, "async")) { $async = 1; }
-       
        return {
                        NAME => $d->{NAME},
                        TYPE => "FUNCTION",
                        OPNUM => $thisopnum,
-                       ASYNC => $async,
                        RETURN_TYPE => $rettype,
                        PROPERTIES => $d->{PROPERTIES},
                        ELEMENTS => \@elements,
@@ -653,6 +805,25 @@ sub ParseFunction($$$)
                };
 }
 
+sub ReturnTypeElement($)
+{
+       my ($fn) = @_;
+
+       return undef unless defined($fn->{RETURN_TYPE});
+
+       my $e = {
+               "NAME" => "result",
+               "TYPE" => $fn->{RETURN_TYPE},
+               "PROPERTIES" => undef,
+               "POINTERS" => 0,
+               "ARRAY_LEN" => [],
+               "FILE" => $fn->{FILE},
+               "LINE" => $fn->{LINE},
+       };
+
+       return ParseElement($e, 0, 0);
+}
+
 sub CheckPointerTypes($$)
 {
        my ($s,$default) = @_;
@@ -692,6 +863,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)
@@ -701,11 +874,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);
                }
        }
@@ -737,7 +910,8 @@ sub ParseInterface($)
                FUNCTIONS => \@functions,
                CONSTS => \@consts,
                TYPES => \@types,
-               ENDPOINTS => \@endpoints
+               ENDPOINTS => \@endpoints,
+               ORIGINAL => $idl
        };
 }
 
@@ -795,9 +969,22 @@ sub ContainsString($)
 {
        my ($e) = @_;
 
+       if (property_matches($e, "flag", ".*STR_NULLTERM.*")) {
+               return 1;
+       }
+       if (exists($e->{LEVELS}) and $e->{LEVELS}->[0]->{TYPE} eq "ARRAY" and
+               ($e->{LEVELS}->[0]->{IS_FIXED} or $e->{LEVELS}->[0]->{IS_INLINE}) and
+               has_property($e, "charset"))
+       {
+               return 1;
+       }
+
        foreach my $l (@{$e->{LEVELS}}) {
                return 1 if ($l->{TYPE} eq "ARRAY" and $l->{IS_ZERO_TERMINATED});
        }
+       if (property_matches($e, "charset", ".*DOS.*")) {
+               return 1;
+       }
 
        return 0;
 }
@@ -817,6 +1004,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;
@@ -865,7 +1066,8 @@ my %property_list = (
        "helper"                => ["INTERFACE"],
        "pyhelper"              => ["INTERFACE"],
        "authservice"           => ["INTERFACE"],
-       "restricted"    => ["INTERFACE"],
+       "restricted"            => ["INTERFACE"],
+        "no_srv_register"       => ["INTERFACE"],
 
        # dcom
        "object"                => ["INTERFACE"],
@@ -878,33 +1080,37 @@ my %property_list = (
        "noopnum"               => ["FUNCTION"],
        "in"                    => ["ELEMENT"],
        "out"                   => ["ELEMENT"],
-       "async"                 => ["FUNCTION"],
 
        # pointer
-       "ref"                   => ["ELEMENT"],
-       "ptr"                   => ["ELEMENT"],
-       "unique"                => ["ELEMENT"],
+       "ref"                   => ["ELEMENT", "TYPEDEF"],
+       "ptr"                   => ["ELEMENT", "TYPEDEF"],
+       "unique"                => ["ELEMENT", "TYPEDEF"],
        "ignore"                => ["ELEMENT"],
-       "relative"              => ["ELEMENT"],
-       "null_is_ffffffff" => ["ELEMENT"],
+       "relative"              => ["ELEMENT", "TYPEDEF"],
+       "relative_short"        => ["ELEMENT", "TYPEDEF"],
+       "null_is_ffffffff"      => ["ELEMENT"],
        "relative_base"         => ["TYPEDEF", "STRUCT", "UNION"],
 
        "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"],
+       "skip"                  => ["ELEMENT"],
+       "skip_noinit"           => ["ELEMENT"],
 
        # union
        "switch_is"             => ["ELEMENT"],
        "switch_type"           => ["ELEMENT", "UNION"],
        "nodiscriminant"        => ["UNION"],
+       "ms_union"              => ["INTERFACE", "UNION"],
        "case"                  => ["ELEMENT"],
        "default"               => ["ELEMENT"],
 
@@ -934,6 +1140,7 @@ my %property_list = (
        "noheader"              => ["ELEMENT"],
        "charset"               => ["ELEMENT"],
        "length_is"             => ["ELEMENT"],
+       "to_null"               => ["ELEMENT"],
 );
 
 #####################################################################
@@ -994,13 +1201,13 @@ sub ValidElement($)
                        my $discriminator_type = has_property($type->{DATA}, "switch_type");
                        $discriminator_type = "uint32" unless defined ($discriminator_type);
 
-                       my $t1 = mapToScalar($discriminator_type);
+                       my $t1 = mapScalarType(mapToScalar($discriminator_type));
 
                        if (not defined($t1)) {
                                fatal($e, el_name($e) . ": unable to map discriminator type '$discriminator_type' to scalar");
                        }
 
-                       my $t2 = mapToScalar($e2->{TYPE});
+                       my $t2 = mapScalarType(mapToScalar($e2->{TYPE}));
                        if (not defined($t2)) {
                                fatal($e, el_name($e) . ": unable to map variable used for switch_is() to scalar");
                        }
@@ -1043,6 +1250,7 @@ sub ValidElement($)
                has_property($e, "ptr") or
                has_property($e, "unique") or
                has_property($e, "relative") or
+               has_property($e, "relative_short") or
                has_property($e, "ref"))) {
                fatal($e, el_name($e) . " : pointer properties on non-pointer element\n");      
        }
@@ -1124,11 +1332,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);
 }
 
 #####################################################################
@@ -1140,12 +1353,14 @@ sub ValidTypedef($)
 
        ValidProperties($typedef, "TYPEDEF");
 
+       return unless (ref($data) eq "HASH");
+
        $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");
+       ValidType($data);
 }
 
 #####################################################################