r7102: fix subcontext(0)
[samba.git] / source / build / pidl / ndr.pm
index 019300d7843a7c8d64d9e1b18cfa9f402c527c4f..febf292c8a3ec35716a7041059f23c5ab5967f47 100644 (file)
 ###################################################
-# Samba4 NDR parser generator for IDL structures
+# Samba4 NDR info tree generator
 # Copyright tridge@samba.org 2000-2003
 # Copyright tpot@samba.org 2001
 # Copyright jelmer@samba.org 2004-2005
 # released under the GNU GPL
 
-package NdrParser;
+package Ndr;
 
 use strict;
-use needed;
-use typelist;
+use pidl::typelist;
 
-# list of known types
-my %typefamily;
-
-sub get_typefamily($)
+#####################################################################
+# return a table describing the order in which the parts of an element
+# should be parsed
+# Possible level types:
+#  - POINTER
+#  - ARRAY
+#  - SUBCONTEXT
+#  - SWITCH
+#  - DATA
+sub GetElementLevelTable($)
 {
-       my $n = shift;
-       return $typefamily{$n};
-}
+       my $e = shift;
 
-my %scalar_alignments = 
-(
-     "char"           => 1,
-     "int8"           => 1,
-     "uint8"          => 1,
-     "short"          => 2,
-     "wchar_t"        => 2,
-     "int16"          => 2,
-     "uint16"         => 2,
-     "long"           => 4,
-     "int32"          => 4,
-     "uint32"         => 4,
-     "dlong"          => 4,
-     "udlong"         => 4,
-     "udlongr"        => 4,
-     "NTTIME"         => 4,
-     "NTTIME_1sec"    => 4,
-     "time_t"         => 4,
-     "DATA_BLOB"      => 4,
-     "error_status_t" => 4,
-     "WERROR"         => 4,
-        "NTSTATUS"       => 4,
-     "boolean32"      => 4,
-     "unsigned32"     => 4,
-     "ipv4address"    => 4,
-     "hyper"          => 8,
-     "NTTIME_hyper"   => 8
-);
-
-$typefamily{SCALAR} = {
-       ALIGN => sub { 
-               my $t = shift;
-               return $scalar_alignments{$t->{NAME}}; 
+       my $order = [];
+       my $is_deferred = 0;
+       my @bracket_array = ();
+       my @length_is = ();
+       my @size_is = ();
+
+       if (util::has_property($e, "size_is")) {
+               @size_is = split /,/, util::has_property($e, "size_is");
        }
-};
 
-sub is_scalar_type($)
-{
-    my $type = shift;
+       if (util::has_property($e, "length_is")) {
+               @length_is = split /,/, util::has_property($e, "length_is");
+       }
+
+       if (defined($e->{ARRAY_LEN})) {
+               @bracket_array = @{$e->{ARRAY_LEN}};
+       }
+       
+       # Parse the [][][][] style array stuff
+       foreach my $d (@bracket_array) {
+               my $size = $d;
+               my $length = $d;
+               my $is_surrounding = 0;
+               my $is_varying = 0;
+               my $is_conformant = 0;
+
+               if ($d eq "*") {
+                       $is_conformant = 1;
+                       unless ($size = shift @size_is) {
+                               print "$e->{FILE}:$e->{LINE}: Must specify size_is() for conformant array!\n";
+                               exit 1;
+                       }
+
+                       if ($length = shift @length_is) {
+                               $is_varying = 1;
+                       } else {
+                               $length = $size;
+                       }
+
+                       if ($e == $e->{PARENT}->{ELEMENTS}[-1] 
+                               and $e->{PARENT}->{TYPE} ne "FUNCTION") {
+                               $is_surrounding = 1;
+                       }
+               }
 
-       return 0 unless typelist::hasType($type);
+               push (@$order, {
+                       TYPE => "ARRAY",
+                       SIZE_IS => $size,
+                       LENGTH_IS => $length,
+                       IS_DEFERRED => "$is_deferred",
+                       # Inline arrays (which are a pidl extension) are never encoded
+                       # as surrounding the struct they're part of
+                       IS_SURROUNDING => "$is_surrounding",
+                       IS_VARYING => "$is_varying",
+                       IS_CONFORMANT => "$is_conformant",
+                       IS_FIXED => (not $is_conformant and util::is_constant($size)),
+                       NO_METADATA => (not $is_conformant),
+                       IS_INLINE => (not $is_conformant and not util::is_constant($size))
+               });
+       }
+
+       # 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");
+
+               push (@$order, { 
+                       TYPE => "POINTER",
+                       # for now, there can only be one pointer type per element
+                       POINTER_TYPE => pointer_type($e),
+                       IS_DEFERRED => "$is_deferred",
+                       LEVEL => $level
+               });
+               
+               # everything that follows will be deferred
+               $is_deferred = 1 if ($e->{PARENT}->{TYPE} ne "FUNCTION");
+
+               my $array_size;
+               my $array_length;
+               if ($array_size = shift @size_is) {
+                       my $is_varying = 0;
+                       if ($array_length = shift @length_is) {
+                               $is_varying = 1;
+                       } else {
+                               $array_length = $array_size;
+                       }
+
+                       push (@$order, {
+                               TYPE => "ARRAY",
+                               SIZE_IS => $array_size,
+                               LENGTH_IS => $array_length,
+                               IS_DEFERRED => "$is_deferred",
+                               IS_SURROUNDING => 0,
+                               IS_VARYING => "$is_varying",
+                               IS_CONFORMANT => 1,
+                               IS_FIXED => 0,
+                               NO_METADATA => 0,
+                               IS_INLINE => 0,
+                       });
+
+                       $is_deferred = 0;
+               }
+       }
+
+       if (defined(util::has_property($e, "subcontext"))) {
+               my $hdr_size = util::has_property($e, "subcontext");
+               my $subsize = util::has_property($e, "subcontext_size");
+               if (not defined($subsize)) { 
+                       $subsize = -1; 
+               }
+               
+               push (@$order, {
+                       TYPE => "SUBCONTEXT",
+                       HEADER_SIZE => $hdr_size,
+                       SUBCONTEXT_SIZE => $subsize,
+                       IS_DEFERRED => $is_deferred,
+                       COMPRESSION => util::has_property($e, "compression"),
+                       OBFUSCATION => util::has_property($e, "obfuscation")
+               });
+       }
 
-       if (my $dt = typelist::getType($type)->{DATA}->{TYPE}) {
-               return 1 if ($dt eq "SCALAR" or $dt eq "ENUM" or $dt eq "BITMAP");
+       if (my $switch = util::has_property($e, "switch_is")) {
+               push (@$order, {
+                       TYPE => "SWITCH", 
+                       SWITCH_IS => $switch,
+                       IS_DEFERRED => $is_deferred
+               });
        }
 
-    return 0;
+       push (@$order, {
+               TYPE => "DATA",
+               DATA_TYPE => $e->{TYPE},
+               IS_DEFERRED => $is_deferred,
+               CONTAINS_DEFERRED => can_contain_deferred($e),
+               IS_SURROUNDING => is_surrounding_string($e)
+       });
+
+       my $i = 0;
+       foreach (@$order) { $_->{LEVEL_INDEX} = $i; $i+=1; }
+
+       return $order;
+}
+
+#####################################################################
+# see if a type contains any deferred data 
+sub can_contain_deferred
+{
+       my $e = shift;
+
+       return 1 if ($e->{POINTERS});
+       return 0 if (typelist::is_scalar($e->{TYPE}));
+       return 0 if (defined(util::has_property($e, "subcontext")));
+       return 1 unless (typelist::hasType($e->{TYPE})); # assume the worst
+
+       my $type = typelist::getType($e->{TYPE});
+
+       foreach my $x (@{$type->{DATA}->{ELEMENTS}}) {
+               return 1 if (can_contain_deferred ($x));
+       }
+       
+       return 0;
 }
 
 sub pointer_type($)
@@ -84,70 +206,65 @@ sub pointer_type($)
        return undef;
 }
 
-# return 1 if this is a fixed array
-sub is_fixed_array($)
+sub is_surrounding_string($)
 {
        my $e = shift;
-       my $len = $e->{"ARRAY_LEN"};
-       if (defined $len && util::is_constant($len)) {
-               return 1;
-       }
-       return 0;
-}
 
-# return 1 if this is a conformant array
-sub is_conformant_array($)
-{
-       my $e = shift;
-       return 1 if (util::has_property($e, "size_is"));
-       return 0;
+       return 0; #FIXME
+
+       return ($e->{TYPE} eq "string") and ($e->{POINTERS} == 0) 
+               and util::property_matches($e, "flag", ".*LIBNDR_FLAG_STR_CONFORMANT.*") 
+               and $e->{PARENT}->{TYPE} ne "FUNCTION";
 }
 
-# return 1 if this is a inline array
-sub is_inline_array($)
+
+#####################################################################
+# work out the correct alignment for a structure or union
+sub find_largest_alignment($)
 {
-       my $e = shift;
-       my $len = $e->{"ARRAY_LEN"};
-       if (is_fixed_array($e) ||
-           defined $len && $len ne "*") {
-               return 1;
+       my $s = shift;
+
+       my $align = 1;
+       for my $e (@{$s->{ELEMENTS}}) {
+               my $a = 1;
+
+               if (Ndr::need_wire_pointer($e)) {
+                       $a = 4; 
+               } else { 
+                       $a = align_type($e->{TYPE}); 
+               }
+
+               $align = $a if ($align < $a);
        }
-       return 0;
-}
 
-# return 1 if this is a varying array
-sub is_varying_array($)
-{
-       my $e = shift;
-       return 1 if (util::has_property($e, "length_is"));
-       return 0;
+       return $align;
 }
 
-# return 1 if this is a surrounding array (sometimes 
-# referred to as an embedded array). Can only occur as 
-# the last element in a struct and can not contain any pointers.
-sub is_surrounding_array($)
+#####################################################################
+# align a type
+sub align_type
 {
        my $e = shift;
 
-       return ($e->{POINTERS} == 0 
-               and defined $e->{ARRAY_LEN} 
-               and     $e->{ARRAY_LEN} eq "*"
-               and $e == $e->{PARENT}->{ELEMENTS}[-1] 
-               and $e->{PARENT}->{TYPE} ne "FUNCTION");
-}
+       unless (typelist::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";
+           return 4;
+       }
 
-sub array_type($)
-{
-       my $e = shift;
+       my $dt = typelist::getType($e)->{DATA};
 
-       return "conformant-varying" if (is_varying_array($e) and is_conformant_array($e));
-       return "conformant" if (is_varying_array($e));
-       return "varying" if (is_varying_array($e));
-       return "inline" if (is_inline_array($e));
-       return "fixed" if (is_fixed_array($e));
+       if ($dt->{TYPE} eq "ENUM") {
+               return align_type(typelist::enum_type_fn($dt));
+       } elsif ($dt->{TYPE} eq "BITMAP") {
+               return align_type(typelist::bitmap_type_fn($dt));
+       } elsif (($dt->{TYPE} eq "STRUCT") or ($dt->{TYPE} eq "UNION")) {
+               return find_largest_alignment($dt);
+       } elsif ($dt->{TYPE} eq "SCALAR") {
+               return typelist::getScalarAlignment($dt->{NAME});
+       }
 
-       return undef;
+       die("Unknown data type type $dt->{TYPE}");
 }
 
 # determine if an element needs a reference pointer on the wire
@@ -159,6 +276,7 @@ sub need_wire_pointer($)
        my $n = $e->{POINTERS};
        my $pt = pointer_type($e);
 
+       # Top level "ref" pointers do not have a referrent identifier
        if (    defined($pt) 
                and $pt eq "ref" 
                and $e->{PARENT}->{TYPE} eq "FUNCTION") 
@@ -169,1991 +287,363 @@ sub need_wire_pointer($)
        return $n;
 }
 
-# determine if an element is a pure scalar. pure scalars do not
-# have a "buffers" section in NDR
-sub is_pure_scalar($)
-{
-       my $e = shift;
-       if (is_scalar_type($e->{TYPE}) && 
-           need_wire_pointer($e) == 0 && 
-           !util::array_size($e)) {
-               return 1;
-       }
-       return 0;
-}
-
-# see if a variable needs to be allocated by the NDR subsystem on pull
-sub need_alloc($)
+sub ParseElement($)
 {
        my $e = shift;
 
-       return 0 if (util::has_property($e, "ref"));
-       return 1 if ($e->{POINTERS} || util::array_size($e));
-       return 0;
+       return {
+               NAME => $e->{NAME},
+               TYPE => $e->{TYPE},
+               PROPERTIES => $e->{PROPERTIES},
+               LEVELS => GetElementLevelTable($e)
+       };
 }
 
-sub c_ptr_prefix($)
+sub ParseStruct($)
 {
-       my $e = shift;
-       my $pointers = "";
-       foreach my $i (need_wire_pointer($e)..$e->{POINTERS}-1) { $pointers.="*"; }
-       return $pointers;
-}
+       my $struct = shift;
+       my @elements = ();
+       my $surrounding = undef;
 
-# determine the C prefix used to refer to a variable when passing to a push
-# function. This will be '*' for pointers to scalar types, '' for scalar
-# types and normal pointers and '&' for pass-by-reference structures
-sub c_push_prefix($)
-{
-       my $e = shift;
+       foreach my $x (@{$struct->{ELEMENTS}}) 
+       {
+               push @elements, ParseElement($x);
+       }
 
-       my $ret = "";
-
-       if ($e->{TYPE} =~ "string") {
-               $ret = "";
-       } elsif (is_scalar_type($e->{TYPE}) &&
-           $e->{POINTERS}) {
-               $ret = "*";
-       } elsif (!is_scalar_type($e->{TYPE}) &&
-           !$e->{POINTERS} &&
-           !util::array_size($e)) {
-               return "&";
+       my $e = $elements[-1];
+       if (defined($e) and defined($e->{LEVELS}[0]->{IS_SURROUNDING}) and
+               $e->{LEVELS}[0]->{IS_SURROUNDING}) {
+               $surrounding = $e;
        }
 
-       foreach my $i (2..$e->{POINTERS}) { $ret.="*"; }
-       
-       return $ret;
+       if (defined $e->{TYPE} && $e->{TYPE} eq "string"
+           &&  util::property_matches($e, "flag", ".*LIBNDR_FLAG_STR_CONFORMANT.*")) {
+               $surrounding = $struct->{ELEMENTS}[-1];
+       }
+               
+       return {
+               TYPE => "STRUCT",
+               SURROUNDING_ELEMENT => $surrounding,
+               ELEMENTS => \@elements,
+               PROPERTIES => $struct->{PROPERTIES}
+       };
 }
 
-# determine the C prefix used to refer to a variable when passing to a pull
-# return '&' or ''
-sub c_pull_prefix($)
+sub ParseUnion($)
 {
        my $e = shift;
+       my @elements = ();
+       my $switch_type = util::has_property($e, "switch_type");
+       unless (defined($switch_type)) { $switch_type = "uint32"; }
 
-       if (!$e->{POINTERS} && !util::array_size($e)) {
-               return "&";
-       }
-
-       if ($e->{TYPE} =~ "string") {
-               return "&";
+       if (util::has_property($e, "nodiscriminant")) { $switch_type = undef; }
+       
+       foreach my $x (@{$e->{ELEMENTS}}) 
+       {
+               my $t;
+               if ($x->{TYPE} eq "EMPTY") {
+                       $t = { TYPE => "EMPTY" };
+               } else {
+                       $t = ParseElement($x);
+               }
+               if (util::has_property($x, "default")) {
+                       $t->{CASE} = "default";
+               } elsif (defined($x->{PROPERTIES}->{case})) {
+                       $t->{CASE} = "case $x->{PROPERTIES}->{case}";
+               } else {
+                       die("Union element $x->{NAME} has neither default nor case property");
+               }
+               push @elements, $t;
        }
 
-       my $ret = "";
-       foreach my $i (2..$e->{POINTERS}) { $ret.="*"; }
-       return $ret;
-}
-my $res = "";
-my $tabs = "";
-sub pidl($)
-{
-       my $d = shift;
-       if ($d) {
-               $res .= $tabs;
-               $res .= $d;
-       }
-       $res .="\n";
+       return {
+               TYPE => "UNION",
+               SWITCH_TYPE => $switch_type,
+               ELEMENTS => \@elements,
+               PROPERTIES => $e->{PROPERTIES}
+       };
 }
 
-sub indent
+sub ParseEnum($)
 {
-       $tabs .= "\t";
-}
+       my $e = shift;
 
-sub deindent
-{
-       $tabs = substr($tabs, 0, -1);
+       return {
+               TYPE => "ENUM",
+               BASE_TYPE => typelist::enum_type_fn($e),
+               ELEMENTS => $e->{ELEMENTS},
+               PROPERTIES => $e->{PROPERTIES}
+       };
 }
 
-###################################
-# find a sibling var in a structure
-sub find_sibling($$)
+sub ParseBitmap($)
 {
-       my($e) = shift;
-       my($name) = shift;
-       my($fn) = $e->{PARENT};
-
-       if ($name =~ /\*(.*)/) {
-               $name = $1;
-       }
-
-       for my $e2 (@{$fn->{ELEMENTS}}) {
-               return $e2 if ($e2->{NAME} eq $name);
-       }
+       my $e = shift;
 
-       die "invalid sibling '$name'";
+       return {
+               TYPE => "BITMAP",
+               BASE_TYPE => typelist::bitmap_type_fn($e),
+               ELEMENTS => $e->{ELEMENTS},
+               PROPERTIES => $e->{PROPERTIES}
+       };
 }
 
-####################################################################
-# work out the name of a size_is() variable
-sub ParseExpr($$$)
+sub ParseDeclare($$)
 {
-       my($e) = shift;
-       my($size) = shift;
-       my($var_prefix) = shift;
-
-       my($fn) = $e->{PARENT};
-
-       return $size if (util::is_constant($size));
+       my $ndr = shift;
+       my $d = shift;
 
-       return $size if ($size =~ /ndr->|\(/);
+}
 
-       my $prefix = "";
+sub ParseTypedef($$)
+{
+       my $ndr = shift;
+       my $d = shift;
+       my $data;
 
-       if ($size =~ /\*(.*)/) {
-               $size = $1;
-               $prefix = "*";
+       if ($d->{DATA}->{TYPE} eq "STRUCT" or $d->{DATA}->{TYPE} eq "UNION") {
+               CheckPointerTypes($d->{DATA}, $ndr->{PROPERTIES}->{pointer_default});
        }
 
-       if ($fn->{TYPE} ne "FUNCTION") {
-               return $prefix . "r->$size";
+       if (defined($d->{PROPERTIES}) && !defined($d->{DATA}->{PROPERTIES})) {
+               $d->{DATA}->{PROPERTIES} = $d->{PROPERTIES};
        }
 
-       my $e2 = find_sibling($e, $size);
-
-       if (util::has_property($e2, "in") && util::has_property($e2, "out")) {
-               return $prefix . "$var_prefix$size";
-       }
-       
-       if (util::has_property($e2, "in")) {
-               return $prefix . "r->in.$size";
-       }
-       
-       if (util::has_property($e2, "out")) {
-               return $prefix . "r->out.$size";
+       if ($d->{DATA}->{TYPE} eq "STRUCT") {
+               $data = ParseStruct($d->{DATA});
+       } elsif ($d->{DATA}->{TYPE} eq "UNION") {
+               $data = ParseUnion($d->{DATA});
+       } elsif ($d->{DATA}->{TYPE} eq "ENUM") {
+               $data = ParseEnum($d->{DATA});
+       } elsif ($d->{DATA}->{TYPE} eq "BITMAP") {
+               $data = ParseBitmap($d->{DATA});
+       } else {
+               die("Unknown data type '$d->{DATA}->{TYPE}'");
        }
 
-       die "invalid variable in $size for element $e->{NAME} in $fn->{NAME}\n";
+       $data->{ALIGN} = align_type($d->{NAME});
+
+       return {
+               NAME => $d->{NAME},
+               TYPE => $d->{TYPE},
+               PROPERTIES => $d->{PROPERTIES},
+               DATA => $data
+       };
 }
 
-#####################################################################
-# check that a variable we get from ParseExpr isn't a null pointer
-sub check_null_pointer($)
+sub ParseConst($$)
 {
-       my $size = shift;
-       if ($size =~ /^\*/) {
-               my $size2 = substr($size, 1);
-               pidl "if ($size2 == NULL) return NT_STATUS_INVALID_PARAMETER_MIX;";
-       }
+       my $ndr = shift;
+       my $d = shift;
+
+       return $d;
 }
 
-#####################################################################
-# check that a variable we get from ParseExpr isn't a null pointer
-# void return varient
-sub check_null_pointer_void($)
+sub ParseFunction($$$)
 {
-       my $size = shift;
-       if ($size =~ /^\*/) {
-               my $size2 = substr($size, 1);
-               pidl "if ($size2 == NULL) return;";
+       my $ndr = shift;
+       my $d = shift;
+       my $opnum = shift;
+       my @elements = ();
+       my $rettype = undef;
+       my $thisopnum = undef;
+
+       CheckPointerTypes($d, 
+               $ndr->{PROPERTIES}->{pointer_default_top}
+       );
+
+       if (not defined($d->{PROPERTIES}{noid})) {
+               $thisopnum = ${$opnum};
+               ${$opnum}++;
        }
-}
 
-#####################################################################
-# work out is a parse function should be declared static or not
-sub fn_prefix($)
-{
-       my $fn = shift;
-       if ($fn->{TYPE} eq "TYPEDEF") {
-               if (util::has_property($fn, "public")) {
-                       return "";
+       foreach my $x (@{$d->{ELEMENTS}}) {
+               my $e = ParseElement($x);
+               if (util::has_property($x, "in")) {
+                       push (@{$e->{DIRECTION}}, "in");
                }
-       }
 
-       if ($fn->{TYPE} eq "FUNCTION") {
-               if (util::has_property($fn, "public")) {
-                       return "";
+               if (util::has_property($x, "out")) {
+                       push (@{$e->{DIRECTION}}, "out");
                }
-       }
-       return "static ";
-}
 
-###################################################################
-# setup any special flags for an element or structure
-sub start_flags($)
-{
-       my $e = shift;
-       my $flags = util::has_property($e, "flag");
-       if (defined $flags) {
-               pidl "{ uint32_t _flags_save_$e->{TYPE} = ndr->flags;";
-               pidl "ndr_set_flags(&ndr->flags, $flags);";
+               push (@elements, $e);
        }
-}
 
-###################################################################
-# end any special flags for an element or structure
-sub end_flags($)
-{
-       my $e = shift;
-       my $flags = util::has_property($e, "flag");
-       if (defined $flags) {
-               pidl "ndr->flags = _flags_save_$e->{TYPE};\n\t}";
+       if ($d->{RETURN_TYPE} ne "void") {
+               $rettype = $d->{RETURN_TYPE};
        }
+       
+       return {
+                       NAME => $d->{NAME},
+                       TYPE => "FUNCTION",
+                       OPNUM => $thisopnum,
+                       RETURN_TYPE => $rettype,
+                       PROPERTIES => $d->{PROPERTIES},
+                       ELEMENTS => \@elements
+               };
 }
 
-#####################################################################
-# work out the correct alignment for a structure or union
-sub find_largest_alignment($)
+sub CheckPointerTypes($$)
 {
        my $s = shift;
+       my $default = shift;
 
-       my $align = 1;
-       for my $e (@{$s->{ELEMENTS}}) {
-               my $a = 1;
+       foreach my $e (@{$s->{ELEMENTS}}) {
+               if ($e->{POINTERS}) {
+                       if (not defined(Ndr::pointer_type($e))) {
+                               $e->{PROPERTIES}->{$default} = 1;
+                       }
 
-               if (need_wire_pointer($e)) {
-                       $a = 4; 
-               } else { 
-                       $a = align_type($e->{TYPE}); 
+                       if (Ndr::pointer_type($e) eq "ptr") {
+                               print "Warning: ptr is not supported by pidl yet\n";
+                       }
                }
-
-               $align = $a if ($align < $a);
        }
-
-       return $align;
 }
 
-#####################################################################
-# align a type
-sub align_type
+sub ParseInterface($)
 {
-       my $e = shift;
-
-       unless (typelist::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";
-           return 4;
+       my $idl = shift;
+       my @typedefs = ();
+       my @consts = ();
+       my @functions = ();
+       my @endpoints;
+       my @declares = ();
+       my $opnum = 0;
+       my $version;
+
+       if (not util::has_property($idl, "pointer_default")) {
+               # MIDL defaults to "ptr" in DCE compatible mode (/osf)
+               # and "unique" in Microsoft Extensions mode (default)
+               $idl->{PROPERTIES}->{pointer_default} = "unique";
        }
 
-       my $dt = typelist::getType($e)->{DATA};
-
-       my $tmp = $typefamily{$dt->{TYPE}}->{ALIGN}->($dt);
-       return $tmp;
-}
-
-#####################################################################
-# parse array preceding data - push side
-sub ParseArrayPushPreceding($$$)
-{
-       my $e = shift;
-       my $var_prefix = shift;
-       my $ndr_flags = shift;
-
-       my $size = ParseExpr($e, util::array_size($e), $var_prefix);
-
-       if (!is_inline_array($e)) {
-               # we need to emit the array size
-               pidl "NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, $size));";
+       if (not util::has_property($idl, "pointer_default_top")) {
+               $idl->{PROPERTIES}->{pointer_default_top} = "ref";
        }
-}
 
-#####################################################################
-# parse the data of an array - push side
-sub ParseArrayPush($$$)
-{
-       my $e = shift;
-       my $var_prefix = shift;
-       my $ndr_flags = shift;
+       foreach my $d (@{$idl->{DATA}}) {
+               if ($d->{TYPE} eq "TYPEDEF") {
+                       push (@typedefs, ParseTypedef($idl, $d));
+               }
 
-       my $size = ParseExpr($e, util::array_size($e), $var_prefix);
+               if ($d->{TYPE} eq "DECLARE") {
+                       push (@declares, ParseDeclare($idl, $d));
+               }
 
-       if (!is_surrounding_array($e)) {
-               ParseArrayPushPreceding($e, $var_prefix, $ndr_flags);
-       }
-       
-       if (is_varying_array($e)) {
-               my $length = util::has_property($e, "length_is");
-               $length = ParseExpr($e, $length, $var_prefix);
-               pidl "NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0));";
-               pidl "NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, $length));";
-               $size = $length;
-       }
+               if ($d->{TYPE} eq "FUNCTION") {
+                       push (@functions, ParseFunction($idl, $d, \$opnum));
+               }
 
-       if (is_scalar_type($e->{TYPE})) {
-               pidl "NDR_CHECK(ndr_push_array_$e->{TYPE}(ndr, $ndr_flags, $var_prefix$e->{NAME}, $size));";
-       } else {
-               pidl "NDR_CHECK(ndr_push_array(ndr, $ndr_flags, $var_prefix$e->{NAME}, sizeof($var_prefix$e->{NAME}\[0]), $size, (ndr_push_flags_fn_t)ndr_push_$e->{TYPE}));";
+               if ($d->{TYPE} eq "CONST") {
+                       push (@consts, ParseConst($idl, $d));
+               }
        }
-}
 
-#####################################################################
-# print an array
-sub ParseArrayPrint($$)
-{
-       my $e = shift;
-       my $var_prefix = shift;
-       my $size = ParseExpr($e, util::array_size($e), $var_prefix);
+       $version = "0.0";
 
-       if (is_varying_array($e)) {
-               $size = ParseExpr($e, util::has_property($e, "length_is"), $var_prefix);
+       if(defined $idl->{PROPERTIES}->{version}) { 
+               $version = $idl->{PROPERTIES}->{version}; 
        }
 
-       if (is_scalar_type($e->{TYPE})) {
-               pidl "ndr_print_array_$e->{TYPE}(ndr, \"$e->{NAME}\", $var_prefix$e->{NAME}, $size);";
+       # 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 {
-               pidl "ndr_print_array(ndr, \"$e->{NAME}\", $var_prefix$e->{NAME}, sizeof($var_prefix$e->{NAME}\[0]), $size, (ndr_print_fn_t)ndr_print_$e->{TYPE});";
-       }
-}
-
-#####################################################################
-# check the size_is and length_is constraints
-sub CheckArraySizes($$)
+               @endpoints = split / /, $idl->{PROPERTIES}->{endpoint};
+       }
+
+       return { 
+               NAME => $idl->{NAME},
+               UUID => util::has_property($idl, "uuid"),
+               VERSION => $version,
+               TYPE => "INTERFACE",
+               PROPERTIES => $idl->{PROPERTIES},
+               FUNCTIONS => \@functions,
+               CONSTS => \@consts,
+               TYPEDEFS => \@typedefs,
+               DECLARES => \@declares,
+               ENDPOINTS => \@endpoints
+       };
+}
+
+# Convert a IDL tree to a NDR tree
+# Gives a result tree describing all that's necessary for easily generating
+# NDR parsers
+# - list of interfaces
+#  - list with functions
+#   - list with in elements
+#   - list with out elements
+#  - list of typedefs
+#   - list with structs
+#    - alignment of structure
+#    - list with elements
+#   - list with unions
+#    - alignment of union
+#    - list with elements
+#   - list with enums
+#    - base type
+#   - list with bitmaps
+#    - base type
+# per element: 
+#  - alignment
+#  - "level" table
+# properties are saved
+# pointer types explicitly specified
+sub Parse($)
 {
-       my $e = shift;
-       my $var_prefix = shift;
-
-       if (!is_surrounding_array($e) && is_conformant_array($e)) {
-               my $size = ParseExpr($e, util::array_size($e), $var_prefix);
-               pidl "if ($var_prefix$e->{NAME}) {";
-               indent;
-               check_null_pointer($size);
-               pidl "NDR_CHECK(ndr_check_array_size(ndr, (void*)&$var_prefix$e->{NAME}, $size));";
-               deindent;
-               pidl "}";
-       }
+       my $idl = shift;
+       my @ndr = ();
 
-       if (is_varying_array($e)) {
-               my $length = util::has_property($e, "length_is");
-               $length = ParseExpr($e, $length, $var_prefix);
-               pidl "if ($var_prefix$e->{NAME}) {";
-               indent;
-               check_null_pointer($length);
-               pidl "NDR_CHECK(ndr_check_array_length(ndr, (void*)&$var_prefix$e->{NAME}, $length));";
-               deindent;
-               pidl "}"
+       foreach my $x (@{$idl}) {
+               push @ndr, ParseInterface($x);
        }
-}
 
-sub ParseArrayPullPreceding($$$)
-{
-       my $e = shift;
-       my $var_prefix = shift;
-       my $ndr_flags = shift;
-
-       if (!is_inline_array($e)) {
-               # non fixed arrays encode the size just before the array
-               pidl "NDR_CHECK(ndr_pull_array_size(ndr, &$var_prefix$e->{NAME}));";
-       }
+       return \@ndr;
 }
 
-#####################################################################
-# parse an array - pull side
-sub ParseArrayPull($$$)
+sub GetNextLevel($$)
 {
        my $e = shift;
-       my $var_prefix = shift;
-       my $ndr_flags = shift;
-
-       my $size = ParseExpr($e, util::array_size($e), $var_prefix);
-       my $alloc_size = $size;
-
-       # if this is a conformant array then we use that size to allocate, and make sure
-       # we allocate enough to pull the elements
-       if (is_conformant_array($e) and is_surrounding_array($e)) {
-               $alloc_size = "ndr_get_array_size(ndr, &$var_prefix$e->{NAME})";
-               check_null_pointer($size);
-               pidl "if ($size > $alloc_size) {";
-               indent;
-               pidl "return ndr_pull_error(ndr, NDR_ERR_CONFORMANT_SIZE, \"Bad conformant size %u should be %u\", $alloc_size, $size);";
-               deindent;
-               pidl "}";
-       } elsif (!is_inline_array($e)) {
-               if ($var_prefix =~ /^r->out/ && $size =~ /^\*r->in/) {
-                       my $size2 = substr($size, 1);
-                       pidl "if (ndr->flags & LIBNDR_FLAG_REF_ALLOC) { NDR_ALLOC(ndr, $size2); }";
-               }
-
-               ParseArrayPullPreceding($e, $var_prefix, $ndr_flags);
-
-               $alloc_size = "ndr_get_array_size(ndr, &$var_prefix$e->{NAME})";
-       }
-
-       if ((need_alloc($e) && !is_fixed_array($e)) ||
-           ($var_prefix eq "r->in." && util::has_property($e, "ref"))) {
-               if (!is_inline_array($e) || $ndr_flags eq "NDR_SCALARS") {
-                       pidl "NDR_ALLOC_N(ndr, $var_prefix$e->{NAME}, $alloc_size);";
-               }
-       }
+       my $fl = shift;
 
-       if (($var_prefix eq "r->out." && util::has_property($e, "ref"))) {
-               if (!is_inline_array($e) || $ndr_flags eq "NDR_SCALARS") {
-                       pidl "if (ndr->flags & LIBNDR_FLAG_REF_ALLOC) {";
-                       indent;
-                       pidl "NDR_ALLOC_N(ndr, $var_prefix$e->{NAME}, $alloc_size);";
-                       deindent;
-                       pidl "}";
-               }
-       }
+       my $seen = 0;
 
-       if (is_varying_array($e)) {
-               pidl "NDR_CHECK(ndr_pull_array_length(ndr, &$var_prefix$e->{NAME}));";
-               $size = "ndr_get_array_length(ndr, &$var_prefix$e->{NAME})";
+       foreach my $l (@{$e->{LEVELS}}) {
+               return $l if ($seen);
+               ($seen = 1) if ($l == $fl);
        }
 
-       check_null_pointer($size);
-
-       if (is_scalar_type($e->{TYPE})) {
-               pidl "NDR_CHECK(ndr_pull_array_$e->{TYPE}(ndr, $ndr_flags, $var_prefix$e->{NAME}, $size));";
-       } else {
-               pidl "NDR_CHECK(ndr_pull_array(ndr, $ndr_flags, (void **)$var_prefix$e->{NAME}, sizeof($var_prefix$e->{NAME}\[0]), $size, (ndr_pull_flags_fn_t)ndr_pull_$e->{TYPE}));";
-       }
+       return undef;
 }
 
-#####################################################################
-# parse scalars in a structure element
-sub ParseElementPushScalar($$$)
+sub GetPrevLevel($$)
 {
-       my($e) = shift;
-       my($var_prefix) = shift;
-       my($ndr_flags) = shift;
-       my $cprefix = c_push_prefix($e);
-       my $ptr_prefix = c_ptr_prefix($e);
-       my $sub_size = util::has_property($e, "subcontext");
-
-       start_flags($e);
-
-       if (my $value = util::has_property($e, "value")) {
-               pidl "$cprefix$var_prefix$e->{NAME} = $value;";
-       }
+       my $e = shift;
+       my $fl = shift;
+       my $prev = undef;
 
-       if (util::has_property($e, "relative")) {
-               pidl "NDR_CHECK(ndr_push_relative_ptr1(ndr, $ptr_prefix$var_prefix$e->{NAME}));";
-       } elsif (need_wire_pointer($e)) {
-               ParseElementPushPtr($e, $ptr_prefix.$var_prefix, "NDR_SCALARS");
-       } elsif (is_inline_array($e)) {
-               ParseArrayPush($e, "r->", "NDR_SCALARS");
-       } elsif (need_alloc($e)) {
-               # no scalar component
-       } elsif (my $switch = util::has_property($e, "switch_is")) {
-               ParseElementPushSwitch($e, $var_prefix, $ndr_flags, $switch);
-       } elsif (defined $sub_size) {
-               pidl "NDR_CHECK(ndr_push_subcontext_flags_fn(ndr, $sub_size, $cprefix$var_prefix$e->{NAME}, (ndr_push_flags_fn_t) ndr_push_$e->{TYPE}));";
-       } else {
-               pidl "NDR_CHECK(ndr_push_$e->{TYPE}(ndr, $ndr_flags, $cprefix$var_prefix$e->{NAME}));";
+       foreach my $l (@{$e->{LEVELS}}) {
+               (return $prev) if ($l == $fl);
+               $prev = $l;
        }
 
-       end_flags($e);
+       return undef;
 }
 
-#####################################################################
-# parse a pointer in a struct element or function
-sub ParseElementPushPtr($$$)
+sub ContainsDeferred($$)
 {
        my $e = shift;
-       my $var_prefix = shift;
-       my $ndr_flags = shift;
+       my $l = shift;
 
-       pidl "NDR_CHECK(ndr_push_unique_ptr(ndr, $var_prefix$e->{NAME}));";
+       do {
+               return 1 if ($l->{IS_DEFERRED}); 
+               return 1 if ($l->{CONTAINS_DEFERRED});
+       } while ($l = Ndr::GetNextLevel($e,$l));
+       
+       return 0;
 }
 
-#####################################################################
-# print scalars in a structure element
-sub ParseElementPrint($$)
-{
-       my($e) = shift;
-       my($var_prefix) = shift;
-       my $cprefix = c_push_prefix($e);
-       my $ptr_prefix = c_ptr_prefix($e);
-
-       return if (util::has_property($e, "noprint"));
-
-       if (my $value = util::has_property($e, "value")) {
-               pidl "if (ndr->flags & LIBNDR_PRINT_SET_VALUES) {";
-               indent;
-               pidl "$cprefix$var_prefix$e->{NAME} = $value;";
-               deindent;
-               pidl "}";
-       }
-
-       my $l = $e->{POINTERS};
-       $l++ if (util::array_size($e) and $l == 0 and !is_fixed_array($e));
-
-       foreach my $i (1..$l) {
-               pidl "ndr_print_ptr(ndr, \"$e->{NAME}\", $var_prefix$e->{NAME});";
-               pidl "ndr->depth++;";
-               if ($i > $l-need_wire_pointer($e)) {
-                       pidl "if ($ptr_prefix$var_prefix$e->{NAME}) {";
-                       indent;
-               }
-       }
-
-       if (util::array_size($e)) {
-               ParseArrayPrint($e, $var_prefix)
-       } elsif (my $switch = util::has_property($e, "switch_is")) {
-               my $switch_var = ParseExpr($e, $switch, $var_prefix);
-               check_null_pointer_void($switch_var);
-
-               pidl "ndr_print_$e->{TYPE}(ndr, \"$e->{NAME}\", $switch_var, $cprefix$var_prefix$e->{NAME});";
-       } else {
-               pidl "ndr_print_$e->{TYPE}(ndr, \"$e->{NAME}\", $cprefix$var_prefix$e->{NAME});";
-       }
-
-       foreach my $i (1..$l) {
-               if ($i > $l-need_wire_pointer($e)) {
-                       deindent;
-                       pidl "}";
-               }
-               pidl "ndr->depth--;";
-       }
-}
-
-#####################################################################
-# parse scalars in a structure element - pull size
-sub ParseElementPullSwitch($$$$)
-{
-       my($e) = shift;
-       my($var_prefix) = shift;
-       my($ndr_flags) = shift;
-       my $switch = shift;
-       my $switch_var = ParseExpr($e, $switch, $var_prefix);
-
-       my $cprefix = c_pull_prefix($e);
-
-       my $utype = typelist::getType($e->{TYPE});
-
-       check_null_pointer($switch_var);
-
-       if (!defined $utype ||
-           !util::has_property($utype, "nodiscriminant")) {
-               my $e2 = find_sibling($e, $switch);
-               my $type_decl = typelist::mapType($e2);
-               pidl "if (($ndr_flags) & NDR_SCALARS) {";
-               indent;
-               pidl "$type_decl _level;";
-               pidl "NDR_CHECK(ndr_pull_$e2->{TYPE}(ndr, NDR_SCALARS, &_level));";
-               if ($switch_var =~ /r->in/) {
-                       pidl "if (!(ndr->flags & LIBNDR_FLAG_REF_ALLOC) && _level != $switch_var) {";
-                       indent;
-               } else {
-                       pidl "if (_level != $switch_var) {"; 
-                       indent;
-               }
-               pidl "return ndr_pull_error(ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value %u in $e->{NAME}\", _level);";
-               deindent;
-               if ($switch_var =~ /r->/) {
-                       pidl "} else { $switch_var = _level; }";
-               } else {
-                       pidl "}";
-               }
-               deindent;
-               pidl "}";
-       }
-
-       my $sub_size = util::has_property($e, "subcontext");
-       if (defined $sub_size) {
-               pidl "if (($ndr_flags) & NDR_SCALARS) {";
-               indent;
-               pidl "NDR_CHECK(ndr_pull_subcontext_union_fn(ndr, $sub_size, $switch_var, $cprefix$var_prefix$e->{NAME}, (ndr_pull_union_fn_t) ndr_pull_$e->{TYPE}));";
-               deindent;
-               pidl "}";
-       } else {
-               pidl "NDR_CHECK(ndr_pull_$e->{TYPE}(ndr, $ndr_flags, $switch_var, $cprefix$var_prefix$e->{NAME}));";
-       }
-
-
-}
-
-#####################################################################
-# push switch element
-sub ParseElementPushSwitch($$$$)
-{
-       my($e) = shift;
-       my($var_prefix) = shift;
-       my($ndr_flags) = shift;
-       my $switch = shift;
-       my $switch_var = ParseExpr($e, $switch, $var_prefix);
-       my $cprefix = c_push_prefix($e);
-
-       check_null_pointer($switch_var);
-
-       my $utype = typelist::getType($e->{TYPE});
-       if (!defined $utype ||
-           !util::has_property($utype, "nodiscriminant")) {
-               my $e2 = find_sibling($e, $switch);
-               pidl "if (($ndr_flags) & NDR_SCALARS) {";
-               indent;
-               pidl "NDR_CHECK(ndr_push_$e2->{TYPE}(ndr, NDR_SCALARS, $switch_var));";
-               deindent;
-               pidl "}";
-       }
-
-       my $sub_size = util::has_property($e, "subcontext");
-       if (defined $sub_size) {
-               pidl "if(($ndr_flags) & NDR_SCALARS) {";
-               indent;
-               pidl "NDR_CHECK(ndr_push_subcontext_union_fn(ndr, $sub_size, $switch_var, $cprefix$var_prefix$e->{NAME}, (ndr_push_union_fn_t) ndr_push_$e->{TYPE}));";
-               deindent;
-               pidl "}";
-       } else {
-               pidl "NDR_CHECK(ndr_push_$e->{TYPE}(ndr, $ndr_flags, $switch_var, $cprefix$var_prefix$e->{NAME}));";
-       }
-}
-
-#####################################################################
-# parse scalars in a structure element - pull size
-sub ParseElementPullScalar($$$)
-{
-       my($e) = shift;
-       my($var_prefix) = shift;
-       my($ndr_flags) = shift;
-       my $cprefix = c_pull_prefix($e);
-       my $ptr_prefix = c_ptr_prefix($e);
-       my $sub_size = util::has_property($e, "subcontext");
-
-       start_flags($e);
-
-       if (is_inline_array($e)) {
-               ParseArrayPull($e, "r->", "NDR_SCALARS");
-       } elsif (need_wire_pointer($e)) {
-               ParseElementPullPtr($e, $ptr_prefix.$var_prefix, "NDR_SCALARS");
-       } elsif (is_surrounding_array($e)) {
-       } elsif (my $switch = util::has_property($e, "switch_is")) {
-               ParseElementPullSwitch($e, $var_prefix, $ndr_flags, $switch);
-       } elsif (defined $sub_size) {
-               pidl "NDR_CHECK(ndr_pull_subcontext_flags_fn(ndr, $sub_size, $cprefix$var_prefix$e->{NAME}, (ndr_pull_flags_fn_t) ndr_pull_$e->{TYPE}));";
-       } else {
-               pidl "NDR_CHECK(ndr_pull_$e->{TYPE}(ndr, $ndr_flags, $cprefix$var_prefix$e->{NAME}));";
-       }
-
-       if (my $range = util::has_property($e, "range")) {
-               my ($low, $high) = split(/ /, $range, 2);
-               pidl "if ($var_prefix$e->{NAME} < $low || $var_prefix$e->{NAME} > $high) {";
-               pidl "\treturn ndr_pull_error(ndr, NDR_ERR_RANGE, \"value out of range\");";
-               pidl "}";
-       }
-
-       end_flags($e);
-}
-
-#####################################################################
-# parse a pointer in a struct element or function
-sub ParseElementPullPtr($$$)
-{
-       my($e) = shift;
-       my($var_prefix) = shift;
-       my($ndr_flags) = shift;
-
-       pidl "NDR_CHECK(ndr_pull_unique_ptr(ndr, &_ptr_$e->{NAME}));";
-       pidl "if (_ptr_$e->{NAME}) {";
-       indent;
-       pidl "NDR_ALLOC(ndr, $var_prefix$e->{NAME});";
-       if (util::has_property($e, "relative")) {
-               pidl "NDR_CHECK(ndr_pull_relative_ptr1(ndr, $var_prefix$e->{NAME}, _ptr_$e->{NAME}));";
-       }
-       deindent;
-       pidl "} else {";
-       pidl "\t$var_prefix$e->{NAME} = NULL;";
-       pidl "}";
-}
-
-#####################################################################
-# parse buffers in a structure element
-sub ParseElementPushBuffer($$$)
-{
-       my($e) = shift;
-       my($var_prefix) = shift;
-       my($ndr_flags) = shift;
-       my $cprefix = c_push_prefix($e);
-       my $sub_size = util::has_property($e, "subcontext");
-
-       return if (is_pure_scalar($e));
-
-       start_flags($e);
-
-       my $pointers = c_ptr_prefix($e);
-       for my $i (1..need_wire_pointer($e)) {
-               if ($i > 1) {
-                       ParseElementPushPtr($e,$pointers.$var_prefix,$ndr_flags);
-               }
-               pidl "if ($pointers$var_prefix$e->{NAME}) {";
-               indent;
-               $pointers.="*";
-       }
-               
-       if (util::has_property($e, "relative")) {
-               pidl "NDR_CHECK(ndr_push_relative_ptr2(ndr, $var_prefix$e->{NAME}));";
-       }
-           
-       if (is_inline_array($e)) {
-               ParseArrayPush($e, "r->", "NDR_BUFFERS");
-       } elsif (util::array_size($e)) {
-               ParseArrayPush($e, "r->", "NDR_SCALARS|NDR_BUFFERS");
-       } elsif (my $switch = util::has_property($e, "switch_is")) {
-               if ($e->{POINTERS}) {
-                       ParseElementPushSwitch($e, $var_prefix, "NDR_BUFFERS|NDR_SCALARS", $switch);
-               } else {
-                       ParseElementPushSwitch($e, $var_prefix, "NDR_BUFFERS", $switch);
-               }
-       } elsif (defined $sub_size) {
-               if ($e->{POINTERS}) {
-                       pidl "NDR_CHECK(ndr_push_subcontext_flags_fn(ndr, $sub_size, $cprefix$var_prefix$e->{NAME}, (ndr_push_flags_fn_t) ndr_push_$e->{TYPE}));";
-               }
-       } elsif ($e->{POINTERS}) {
-               pidl "NDR_CHECK(ndr_push_$e->{TYPE}(ndr, NDR_SCALARS|NDR_BUFFERS, $cprefix$var_prefix$e->{NAME}));";
-       } else {
-               pidl "NDR_CHECK(ndr_push_$e->{TYPE}(ndr, $ndr_flags, $cprefix$var_prefix$e->{NAME}));";
-       }
-
-       for my $i (1..need_wire_pointer($e)) {
-               deindent;
-               pidl "}";
-       }
-
-       end_flags($e);
-}
-
-#####################################################################
-# parse buffers in a structure element - pull side
-sub ParseElementPullBuffer($$$)
-{
-       my($e) = shift;
-       my($var_prefix) = shift;
-       my($ndr_flags) = shift;
-       my $cprefix = c_pull_prefix($e);
-       my $sub_size = util::has_property($e, "subcontext");
-
-       return if (is_pure_scalar($e));
-
-       start_flags($e);
-
-       my $pointers = c_ptr_prefix($e);
-       for my $i (1..need_wire_pointer($e)) {
-               if ($i > 1) {
-                       ParseElementPullPtr($e,$pointers.$var_prefix,"NDR_SCALARS");
-               }
-               pidl "if ($pointers$var_prefix$e->{NAME}) {";
-               indent;
-               $pointers.="*";
-       }
-       if (util::has_property($e, "relative")) {
-               pidl "struct ndr_pull_save _relative_save;";
-               pidl "ndr_pull_save(ndr, &_relative_save);";
-               pidl "NDR_CHECK(ndr_pull_relative_ptr2(ndr, $var_prefix$e->{NAME}));";
-       }
-           
-       if (is_inline_array($e)) {
-               ParseArrayPull($e, "r->", "NDR_BUFFERS");
-       } elsif (util::array_size($e)) {
-               ParseArrayPull($e, "r->", "NDR_SCALARS|NDR_BUFFERS");
-       } elsif (my $switch = util::has_property($e, "switch_is")) {
-               if ($e->{POINTERS}) {
-                       ParseElementPullSwitch($e, $var_prefix, "NDR_SCALARS|NDR_BUFFERS", $switch);
-               } else {
-                       ParseElementPullSwitch($e, $var_prefix, "NDR_BUFFERS", $switch);
-               }
-       } elsif (defined $sub_size) {
-               if ($e->{POINTERS}) {
-                       pidl "NDR_CHECK(ndr_pull_subcontext_flags_fn(ndr, $sub_size, $cprefix$var_prefix$e->{NAME}, (ndr_pull_flags_fn_t) ndr_pull_$e->{TYPE}));";
-               }
-       } elsif ($e->{POINTERS}) {
-               pidl "NDR_CHECK(ndr_pull_$e->{TYPE}(ndr, NDR_SCALARS|NDR_BUFFERS, $cprefix$var_prefix$e->{NAME}));";
-       } else {
-               pidl "NDR_CHECK(ndr_pull_$e->{TYPE}(ndr, $ndr_flags, $cprefix$var_prefix$e->{NAME}));";
-       }
-
-       if (util::has_property($e, "relative")) {
-               pidl "ndr_pull_restore(ndr, &_relative_save);";
-       }
-       for my $i (1..need_wire_pointer($e)) {
-               deindent;
-               pidl "}";
-       }
-
-       end_flags($e);
-}
-
-#####################################################################
-# parse a struct
-sub ParseStructPush($)
-{
-       my($struct) = shift;
-       
-       return unless defined($struct->{ELEMENTS});
-
-       start_flags($struct);
-
-       # see if the structure contains a conformant array. If it
-       # does, then it must be the last element of the structure, and
-       # we need to push the conformant length early, as it fits on
-       # the wire before the structure (and even before the structure
-       # alignment)
-       my $e = $struct->{ELEMENTS}[-1];
-       if (is_conformant_array($e) and is_surrounding_array($e)) {
-               ParseArrayPushPreceding($e, "r->", "NDR_SCALARS");
-       }
-
-       if (defined $e->{TYPE} && $e->{TYPE} eq "string" 
-           &&  util::property_matches($e, "flag", ".*LIBNDR_FLAG_STR_CONFORMANT.*")) {
-               pidl "NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_string_array_size(ndr, r->$e->{NAME})));";
-       }
-
-       pidl "if (!(ndr_flags & NDR_SCALARS)) goto buffers;";
-
-       pidl "NDR_CHECK(ndr_push_struct_start(ndr));";
-
-       my $align = find_largest_alignment($struct);
-       pidl "NDR_CHECK(ndr_push_align(ndr, $align));";
-
-       foreach my $e (@{$struct->{ELEMENTS}}) {
-               ParseElementPushScalar($e, "r->", "NDR_SCALARS");
-       }       
-
-       pidl "buffers:";
-       pidl "if (!(ndr_flags & NDR_BUFFERS)) goto done;";
-       foreach my $e (@{$struct->{ELEMENTS}}) {
-               ParseElementPushBuffer($e, "r->", "NDR_BUFFERS");
-       }
-
-       pidl "ndr_push_struct_end(ndr);";
-
-       pidl "done:";
-
-       end_flags($struct);
-}
-
-#####################################################################
-# generate a push function for an enum
-sub ParseEnumPush($)
-{
-       my($enum) = shift;
-       my($type_fn) = typelist::enum_type_fn($enum);
-
-       start_flags($enum);
-
-       pidl "NDR_CHECK(ndr_push_$type_fn(ndr, NDR_SCALARS, r));";
-
-       end_flags($enum);
-}
-
-#####################################################################
-# generate a pull function for an enum
-sub ParseEnumPull($)
-{
-       my($enum) = shift;
-       my($type_fn) = typelist::enum_type_fn($enum);
-       my($type_v_decl) = typelist::mapScalarType(typelist::enum_type_fn($enum));
-
-       pidl "$type_v_decl v;";
-       start_flags($enum);
-       pidl "NDR_CHECK(ndr_pull_$type_fn(ndr, NDR_SCALARS, &v));";
-       pidl "*r = v;";
-
-       end_flags($enum);
-}
-
-#####################################################################
-# generate a print function for an enum
-sub ParseEnumPrint($)
-{
-       my($enum) = shift;
-
-       pidl "const char *val = NULL;";
-       pidl "";
-
-       start_flags($enum);
-
-       pidl "switch (r) {";
-       indent;
-       my $els = \@{$enum->{ELEMENTS}};
-       foreach my $i (0 .. $#{$els}) {
-               my $e = ${$els}[$i];
-               chomp $e;
-               if ($e =~ /^(.*)=/) {
-                       $e = $1;
-               }
-               pidl "case $e: val = \"$e\"; break;";
-       }
-
-       deindent;
-       pidl "}";
-       
-       pidl "ndr_print_enum(ndr, name, \"$enum->{TYPE}\", val, r);";
-
-       end_flags($enum);
-}
-
-sub ArgsEnumPush($)
-{
-       my $e = shift;
-       return "struct ndr_push *ndr, int ndr_flags, enum $e->{NAME} r";
-}
-
-sub ArgsEnumPrint($)
-{
-       my $e = shift;
-       return "struct ndr_print *ndr, const char *name, enum $e->{NAME} r";
-}
-
-sub ArgsEnumPull($)
-{
-       my $e = shift;
-       return "struct ndr_pull *ndr, int ndr_flags, enum $e->{NAME} *r";
-}
-
-$typefamily{ENUM} = {
-       PUSH_FN_BODY => \&ParseEnumPush,
-       PUSH_FN_ARGS => \&ArgsEnumPush,
-       PULL_FN_BODY => \&ParseEnumPull,
-       PULL_FN_ARGS => \&ArgsEnumPull,
-       PRINT_FN_BODY => \&ParseEnumPrint,
-       PRINT_FN_ARGS => \&ArgsEnumPrint,
-       ALIGN => sub { return align_type(typelist::enum_type_fn(shift)); }
-};
-
-#####################################################################
-# generate a push function for a bitmap
-sub ParseBitmapPush($)
-{
-       my($bitmap) = shift;
-       my($type_fn) = typelist::bitmap_type_fn($bitmap);
-
-       start_flags($bitmap);
-
-       pidl "NDR_CHECK(ndr_push_$type_fn(ndr, NDR_SCALARS, r));";
-
-       end_flags($bitmap);
-}
-
-#####################################################################
-# generate a pull function for an bitmap
-sub ParseBitmapPull($)
-{
-       my($bitmap) = shift;
-       my($type_fn) = typelist::bitmap_type_fn($bitmap);
-       my($type_decl) = typelist::mapType($bitmap);
-
-       pidl "$type_decl v;";
-       start_flags($bitmap);
-       pidl "NDR_CHECK(ndr_pull_$type_fn(ndr, NDR_SCALARS, &v));";
-       pidl "*r = v;";
-
-       end_flags($bitmap);
-}
-
-#####################################################################
-# generate a print function for an bitmap
-sub ParseBitmapPrintElement($$)
-{
-       my($e) = shift;
-       my($bitmap) = shift;
-       my($type_decl) = typelist::mapType($bitmap);
-       my($type_fn) = typelist::bitmap_type_fn($bitmap);
-       my($name) = $bitmap->{PARENT}->{NAME};
-       my($flag);
-
-       if ($e =~ /^(\w+) .*$/) {
-               $flag = "$1";
-       } else {
-               die "Bitmap: \"$name\" invalid Flag: \"$e\"";
-       }
-
-       pidl "ndr_print_bitmap_flag(ndr, sizeof($type_decl), \"$flag\", $flag, r);";
-}
-
-#####################################################################
-# generate a print function for an bitmap
-sub ParseBitmapPrint($)
-{
-       my($bitmap) = shift;
-       my($type_decl) = typelist::mapType($bitmap);
-       my($type_fn) = typelist::bitmap_type_fn($bitmap);
-
-       start_flags($bitmap);
-
-       pidl "ndr_print_$type_fn(ndr, name, r);";
-
-       pidl "ndr->depth++;";
-       foreach my $e (@{$bitmap->{ELEMENTS}}) {
-               ParseBitmapPrintElement($e, $bitmap);
-       }
-       pidl "ndr->depth--;";
-
-       end_flags($bitmap);
-}
-
-sub ArgsBitmapPush($)
-{
-       my $e = shift;
-       my $type_decl = typelist::mapType($e->{DATA});
-       return "struct ndr_push *ndr, int ndr_flags, $type_decl r";
-}
-
-sub ArgsBitmapPrint($)
-{
-       my $e = shift;
-       my $type_decl = typelist::mapType($e->{DATA});
-       return "struct ndr_print *ndr, const char *name, $type_decl r";
-}
-
-sub ArgsBitmapPull($)
-{
-       my $e = shift;
-       my $type_decl = typelist::mapType($e->{DATA});
-       return "struct ndr_pull *ndr, int ndr_flags, $type_decl *r";
-}
-
-$typefamily{BITMAP} = {
-       PUSH_FN_BODY => \&ParseBitmapPush,
-       PUSH_FN_ARGS => \&ArgsBitmapPush,
-       PULL_FN_BODY => \&ParseBitmapPull,
-       PULL_FN_ARGS => \&ArgsBitmapPull,
-       PRINT_FN_BODY => \&ParseBitmapPrint,
-       PRINT_FN_ARGS => \&ArgsBitmapPrint,
-       ALIGN => sub { return align_type(typelist::bitmap_type_fn(shift)); }
-};
-
-#####################################################################
-# generate a struct print function
-sub ParseStructPrint($)
-{
-       my($struct) = shift;
-       my($name) = $struct->{PARENT}->{NAME};
-
-       return unless defined $struct->{ELEMENTS};
-
-       pidl "ndr_print_struct(ndr, name, \"$name\");";
-
-       start_flags($struct);
-
-       pidl "ndr->depth++;";
-       foreach my $e (@{$struct->{ELEMENTS}}) {
-               ParseElementPrint($e, "r->");
-       }
-       pidl "ndr->depth--;";
-
-       end_flags($struct);
-}
-
-#####################################################################
-# parse a struct - pull side
-sub ParseStructPull($)
-{
-       my($struct) = shift;
-       my $conform_e;
-
-       return unless defined $struct->{ELEMENTS};
-
-       # see if the structure contains a conformant array. If it
-       # does, then it must be the last element of the structure, and
-       # we need to pull the conformant length early, as it fits on
-       # the wire before the structure (and even before the structure
-       # alignment)
-       my $e = $struct->{ELEMENTS}[-1];
-       if (is_conformant_array($e) and is_surrounding_array($e)) {
-               $conform_e = $e;
-       }
-
-       if (defined $e->{TYPE} && $e->{TYPE} eq "string"
-           &&  util::property_matches($e, "flag", ".*LIBNDR_FLAG_STR_CONFORMANT.*")) {
-               $conform_e = $e;
-       }
-
-       # declare any internal pointers we need
-       foreach my $e (@{$struct->{ELEMENTS}}) {
-               if (need_wire_pointer($e)) {
-                       pidl "uint32_t _ptr_$e->{NAME};";
-               }
-       }
-
-       start_flags($struct);
-
-       pidl "if (!(ndr_flags & NDR_SCALARS)) goto buffers;";
-
-       pidl "NDR_CHECK(ndr_pull_struct_start(ndr));";
-
-       if (defined $conform_e) {
-               ParseArrayPullPreceding($conform_e, "r->", "NDR_SCALARS");
-       }
-
-       my $align = find_largest_alignment($struct);
-       pidl "NDR_CHECK(ndr_pull_align(ndr, $align));";
-
-       foreach my $e (@{$struct->{ELEMENTS}}) {
-               ParseElementPullScalar($e, "r->", "NDR_SCALARS");
-       }       
-
-       pidl "buffers:\n";
-       pidl "if (!(ndr_flags & NDR_BUFFERS)) goto done;";
-       foreach my $e (@{$struct->{ELEMENTS}}) {
-               ParseElementPullBuffer($e, "r->", "NDR_BUFFERS");
-       }
-
-       foreach my $e (@{$struct->{ELEMENTS}}) {
-               CheckArraySizes($e, "r->");
-       }
-
-       pidl "ndr_pull_struct_end(ndr);";
-
-       pidl "done:";
-
-       end_flags($struct);
-}
-
-#####################################################################
-# calculate size of ndr struct
-sub ParseStructNdrSize($)
-{
-       my $t = shift;
-       my $static = fn_prefix($t);
-       my $sizevar;
-
-       if (my $flags = util::has_property($t, "flag")) {
-               pidl "flags |= $flags;";
-       }
-       pidl "return ndr_size_struct(r, flags, (ndr_push_flags_fn_t)ndr_push_$t->{NAME});";
-}
-
-sub ArgsStructPush($)
-{
-       my $e = shift;
-       return "struct ndr_push *ndr, int ndr_flags, struct $e->{NAME} *r";
-}
-
-sub ArgsStructPrint($)
-{
-       my $e = shift;
-       return "struct ndr_print *ndr, const char *name, struct $e->{NAME} *r";
-}
-
-sub ArgsStructPull($)
-{
-       my $e = shift;
-       return "struct ndr_pull *ndr, int ndr_flags, struct $e->{NAME} *r";
-}
-
-sub ArgsStructNdrSize($)
-{
-       my $d = shift;
-       return "const struct $d->{NAME} *r, int flags";
-}
-
-$typefamily{STRUCT} = {
-       PUSH_FN_BODY => \&ParseStructPush,
-       PUSH_FN_ARGS => \&ArgsStructPush,
-       PULL_FN_BODY => \&ParseStructPull,
-       PULL_FN_ARGS => \&ArgsStructPull,
-       PRINT_FN_BODY => \&ParseStructPrint,
-       PRINT_FN_ARGS => \&ArgsStructPrint,
-       SIZE_FN_BODY => \&ParseStructNdrSize,
-       SIZE_FN_ARGS => \&ArgsStructNdrSize,
-       ALIGN => \&find_largest_alignment
-};
-
-#####################################################################
-# calculate size of ndr struct
-sub ParseUnionNdrSize($)
-{
-       my $t = shift;
-       my $static = fn_prefix($t);
-       my $sizevar;
-
-       if (my $flags = util::has_property($t, "flag")) {
-               pidl "flags |= $flags;";
-       }
-       pidl "return ndr_size_union(r, flags, level, (ndr_push_union_fn_t)ndr_push_$t->{NAME});";
-}
-
-#####################################################################
-# parse a union - push side
-sub ParseUnionPush($)
-{
-       my $e = shift;
-       my $have_default = 0;
-
-       start_flags($e);
-
-       pidl "if (!(ndr_flags & NDR_SCALARS)) goto buffers;";
-
-       pidl "NDR_CHECK(ndr_push_struct_start(ndr));";
-
-#      my $align = union_alignment($e);
-#      pidl "NDR_CHECK(ndr_push_align(ndr, $align));";
-
-       pidl "switch (level) {";
-       indent;
-       foreach my $el (@{$e->{ELEMENTS}}) {
-               if (util::has_property($el, "default")) {
-                       pidl "default:";
-                       $have_default = 1;
-               } else {
-                       pidl "case $el->{PROPERTIES}->{case}:";
-
-               }
-               if ($el->{TYPE} ne "EMPTY") {
-                       indent;
-                       ParseElementPushScalar($el, "r->", "NDR_SCALARS");
-                       deindent;
-               }
-               pidl "break;";
-               pidl "";
-       }
-       if (! $have_default) {
-               pidl "default:";
-               pidl "\treturn ndr_push_error(ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value \%u\", level);";
-       }
-       deindent;
-       pidl "}";
-       pidl "buffers:";
-       pidl "if (!(ndr_flags & NDR_BUFFERS)) goto done;";
-       pidl "switch (level) {";
-       indent;
-       foreach my $el (@{$e->{ELEMENTS}}) {
-               if (util::has_property($el, "default")) {
-                       pidl "default:";
-               } else {
-                       pidl "case $el->{PROPERTIES}->{case}:";
-               }
-               if ($el->{TYPE} ne "EMPTY") {
-                       indent;
-                       ParseElementPushBuffer($el, "r->", "NDR_BUFFERS");
-                       deindent;
-               }
-               pidl "break;";
-               pidl "";
-       }
-       if (! $have_default) {
-               pidl "default:";
-               pidl "\treturn ndr_push_error(ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value \%u\", level);";
-       }
-       deindent;
-       pidl "}";
-       pidl "ndr_push_struct_end(ndr);";
-       pidl "done:";
-       end_flags($e);
-}
-
-#####################################################################
-# print a union
-sub ParseUnionPrint($)
-{
-       my $e = shift;
-       my $have_default = 0;
-       my($name) = $e->{PARENT}->{NAME};
-
-       pidl "ndr_print_union(ndr, name, level, \"$name\");";
-       start_flags($e);
-
-       pidl "switch (level) {";
-       indent;
-       foreach my $el (@{$e->{ELEMENTS}}) {
-               if (util::has_property($el, "default")) {
-                       $have_default = 1;
-                       pidl "default:";
-               } else {
-                       pidl "case $el->{PROPERTIES}->{case}:";
-               }
-               if ($el->{TYPE} ne "EMPTY") {
-                       indent;
-                       ParseElementPrint($el, "r->");
-                       deindent;
-               }
-               pidl "break;";
-               pidl "";
-       }
-       if (! $have_default) {
-               pidl "default:";
-               pidl "\tndr_print_bad_level(ndr, name, level);";
-       }
-       deindent;
-       pidl "}";
-
-       end_flags($e);
-}
-
-#####################################################################
-# parse a union - pull side
-sub ParseUnionPull($)
-{
-       my $e = shift;
-       my $have_default = 0;
-
-       start_flags($e);
-
-       pidl "if (!(ndr_flags & NDR_SCALARS)) goto buffers;";
-
-       pidl "NDR_CHECK(ndr_pull_struct_start(ndr));";
-
-#      my $align = union_alignment($e);
-#      pidl "\tNDR_CHECK(ndr_pull_align(ndr, $align));\n";
-
-       pidl "switch (level) {";
-       indent;
-       foreach my $el (@{$e->{ELEMENTS}}) {
-               if (util::has_property($el, "default")) {
-                       pidl "default: {";
-                       $have_default = 1;
-               } else {
-                       pidl "case $el->{PROPERTIES}->{case}: {";
-               }
-               if ($el->{TYPE} ne "EMPTY") {
-                       indent;
-                       if ($el->{POINTERS}) {
-                               pidl "uint32_t _ptr_$el->{NAME};";
-                       }
-                       ParseElementPullScalar($el, "r->", "NDR_SCALARS");
-                       deindent;
-               }
-               pidl "break; }";
-               pidl "";
-       }
-       if (! $have_default) {
-               pidl "default:";
-               pidl "\treturn ndr_pull_error(ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value \%u\", level);";
-       }
-       deindent;
-       pidl "}";
-       pidl "buffers:";
-       pidl "if (!(ndr_flags & NDR_BUFFERS)) goto done;";
-       pidl "switch (level) {";
-       indent;
-       foreach my $el (@{$e->{ELEMENTS}}) {
-               if (util::has_property($el, "default")) {
-                       pidl "default:";
-               } else {
-                       pidl "case $el->{PROPERTIES}->{case}:";
-               }
-               if ($el->{TYPE} ne "EMPTY") {
-                       indent;
-                       ParseElementPullBuffer($el, "r->", "NDR_BUFFERS");
-                       deindent;
-               }
-               pidl "break;";
-               pidl "";
-       }
-       if (! $have_default) {
-               pidl "default:";
-               pidl "\treturn ndr_pull_error(ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value \%u\", level);";
-       }
-       deindent;
-       pidl "}";
-       pidl "ndr_pull_struct_end(ndr);";
-       pidl "done:";
-       end_flags($e);
-}
-
-sub ArgsUnionPush($)
-{
-       my $e = shift;
-       return "struct ndr_push *ndr, int ndr_flags, int level, union $e->{NAME} *r";
-}
-
-sub ArgsUnionPrint($)
-{
-       my $e = shift;
-       return "struct ndr_print *ndr, const char *name, int level, union $e->{NAME} *r";
-}
-
-sub ArgsUnionPull($)
-{
-       my $e = shift;
-       return "struct ndr_pull *ndr, int ndr_flags, int level, union $e->{NAME} *r";
-}
-
-sub ArgsUnionNdrSize($)
-{
-       my $d = shift;
-       return "const union $d->{NAME} *r, uint32_t level, int flags";
-}
-
-$typefamily{UNION} = {
-       PUSH_FN_BODY => \&ParseUnionPush,
-       PUSH_FN_ARGS => \&ArgsUnionPush,
-       PULL_FN_BODY => \&ParseUnionPull,
-       PULL_FN_ARGS => \&ArgsUnionPull,
-       PRINT_FN_BODY => \&ParseUnionPrint,
-       PRINT_FN_ARGS => \&ArgsUnionPrint,
-       SIZE_FN_ARGS => \&ArgsUnionNdrSize,
-       SIZE_FN_BODY => \&ParseUnionNdrSize,
-       ALIGN => \&find_largest_alignment
-};
-       
-#####################################################################
-# parse a typedef - push side
-sub ParseTypedefPush($)
-{
-       my($e) = shift;
-       my $static = fn_prefix($e);
-
-       return unless needed::is_needed("push_$e->{NAME}");
-
-       my $args = $typefamily{$e->{DATA}->{TYPE}}->{PUSH_FN_ARGS}->($e);
-       pidl $static . "NTSTATUS ndr_push_$e->{NAME}($args)";
-
-       pidl "{";
-       indent;
-       $typefamily{$e->{DATA}->{TYPE}}->{PUSH_FN_BODY}->($e->{DATA});
-       pidl "return NT_STATUS_OK;";
-       deindent;
-       pidl "}";
-       pidl "";;
-}
-
-
-#####################################################################
-# parse a typedef - pull side
-sub ParseTypedefPull($)
-{
-       my($e) = shift;
-       my $static = fn_prefix($e);
-
-       return unless needed::is_needed("pull_$e->{NAME}");
-
-       my $args = $typefamily{$e->{DATA}->{TYPE}}->{PULL_FN_ARGS}->($e);
-
-       pidl $static . "NTSTATUS ndr_pull_$e->{NAME}($args)";
-
-       pidl "{";
-       indent;
-       $typefamily{$e->{DATA}->{TYPE}}->{PULL_FN_BODY}->($e->{DATA});
-       pidl "return NT_STATUS_OK;";
-       deindent;
-       pidl "}";
-       pidl "";
-}
-
-#####################################################################
-# parse a typedef - print side
-sub ParseTypedefPrint($)
-{
-       my($e) = shift;
-
-       my $args = $typefamily{$e->{DATA}->{TYPE}}->{PRINT_FN_ARGS}->($e);
-
-       pidl "void ndr_print_$e->{NAME}($args)";
-       pidl "{";
-       indent;
-       $typefamily{$e->{DATA}->{TYPE}}->{PRINT_FN_BODY}->($e->{DATA});
-       deindent;
-       pidl "}";
-}
-
-#####################################################################
-## calculate the size of a structure
-sub ParseTypedefNdrSize($)
-{
-       my($t) = shift;
-
-       return unless needed::is_needed("ndr_size_$t->{NAME}");
-
-       my $tf = $typefamily{$t->{DATA}->{TYPE}};
-       my $args = $tf->{SIZE_FN_ARGS}->($t);
-
-       pidl "size_t ndr_size_$t->{NAME}($args)";
-       pidl "{";
-       indent;
-       $typefamily{$t->{DATA}->{TYPE}}->{SIZE_FN_BODY}->($t);
-       deindent;
-       pidl "}";
-       pidl "";
-}
-
-#####################################################################
-# parse a function - print side
-sub ParseFunctionPrint($)
-{
-       my($fn) = shift;
-
-       pidl "void ndr_print_$fn->{NAME}(struct ndr_print *ndr, const char *name, int flags, struct $fn->{NAME} *r)";
-       pidl "{";
-       indent;
-       pidl "ndr_print_struct(ndr, name, \"$fn->{NAME}\");";
-       pidl "ndr->depth++;";
-
-       pidl "if (flags & NDR_SET_VALUES) {";
-       pidl "\tndr->flags |= LIBNDR_PRINT_SET_VALUES;";
-       pidl "}";
-
-       pidl "if (flags & NDR_IN) {";
-       indent;
-       pidl "ndr_print_struct(ndr, \"in\", \"$fn->{NAME}\");";
-       pidl "ndr->depth++;";
-
-       foreach my $e (@{$fn->{ELEMENTS}}) {
-               if (util::has_property($e, "in")) {
-                       ParseElementPrint($e, "r->in.");
-               }
-       }
-       pidl "ndr->depth--;";
-       deindent;
-       pidl "}";
-       
-       pidl "if (flags & NDR_OUT) {";
-       indent;
-       pidl "ndr_print_struct(ndr, \"out\", \"$fn->{NAME}\");";
-       pidl "ndr->depth++;";
-       foreach my $e (@{$fn->{ELEMENTS}}) {
-               if (util::has_property($e, "out")) {
-                       ParseElementPrint($e, "r->out.");
-               }
-       }
-       if ($fn->{RETURN_TYPE} && $fn->{RETURN_TYPE} ne "void") {
-               my $cprefix = "&";
-               $cprefix = "" if (is_scalar_type($fn->{RETURN_TYPE})) ; # FIXME: Should really use util::c_push_prefix here
-               pidl "ndr_print_$fn->{RETURN_TYPE}(ndr, \"result\", $cprefix"."r->out.result);";
-       }
-       pidl "ndr->depth--;";
-       deindent;
-       pidl "}";
-       
-       pidl "ndr->depth--;";
-       deindent;
-       pidl "}";
-       pidl "";
-}
-
-#####################################################################
-# parse a function element
-sub ParseFunctionElementPush($$)
-{ 
-       my $e = shift;
-       my $inout = shift;
-
-       if (util::array_size($e)) {
-               if (need_wire_pointer($e)) {
-                       pidl "NDR_CHECK(ndr_push_unique_ptr(ndr, r->$inout.$e->{NAME}));";
-                       pidl "if (r->$inout.$e->{NAME}) {";
-                       indent;
-                       ParseArrayPush($e, "r->$inout.", "NDR_SCALARS|NDR_BUFFERS");
-                       deindent;
-                       pidl "}";
-               } else {
-                       ParseArrayPush($e, "r->$inout.", "NDR_SCALARS|NDR_BUFFERS");
-               }
-       } else {
-               ParseElementPushScalar($e, "r->$inout.", "NDR_SCALARS|NDR_BUFFERS");
-
-               if (need_wire_pointer($e)) {
-                       ParseElementPushBuffer($e, "r->$inout.", "NDR_SCALARS|NDR_BUFFERS");
-               }
-       }
-}      
-
-#####################################################################
-# parse a function
-sub ParseFunctionPush($)
-{ 
-       my($fn) = shift;
-       my $static = fn_prefix($fn);
-
-       pidl $static . "NTSTATUS ndr_push_$fn->{NAME}(struct ndr_push *ndr, int flags, struct $fn->{NAME} *r)";
-       pidl "{";
-       indent;
-
-       pidl "if (!(flags & NDR_IN)) goto ndr_out;";
-       pidl "";
-
-       foreach my $e (@{$fn->{ELEMENTS}}) {
-               if (util::has_property($e, "in")) {
-                       ParseFunctionElementPush($e, "in");
-               }               
-       }
-
-       pidl "ndr_out:";
-       pidl "if (!(flags & NDR_OUT)) goto done;";
-       pidl "";
-
-       foreach my $e (@{$fn->{ELEMENTS}}) {
-               if (util::has_property($e, "out")) {
-                       ParseFunctionElementPush($e, "out");
-               }               
-       }
-
-       if ($fn->{RETURN_TYPE} && $fn->{RETURN_TYPE} ne "void") {
-               pidl "NDR_CHECK(ndr_push_$fn->{RETURN_TYPE}(ndr, NDR_SCALARS, r->out.result));";
-       }
-    
-       pidl "done:";
-       pidl "return NT_STATUS_OK;";
-       deindent;
-       pidl "}";
-       pidl "";
-}
-
-#####################################################################
-# parse a function element
-sub ParseFunctionElementPull($$)
-{ 
-       my $e = shift;
-       my $inout = shift;
-
-       if (util::array_size($e)) {
-               if (need_wire_pointer($e)) {
-                       pidl "NDR_CHECK(ndr_pull_unique_ptr(ndr, &_ptr_$e->{NAME}));";
-                       pidl "r->$inout.$e->{NAME} = NULL;";
-                       pidl "if (_ptr_$e->{NAME}) {";
-               } elsif ($inout eq "out" && util::has_property($e, "ref")) {
-                       pidl "if (r->$inout.$e->{NAME}) {";
-               } else {
-                       pidl "{";
-               }
-               indent;
-               ParseArrayPull($e, "r->$inout.", "NDR_SCALARS|NDR_BUFFERS");
-               deindent;
-               pidl "}";
-       } else {
-               if ($inout eq "out" && util::has_property($e, "ref")) {
-                       pidl "if (ndr->flags & LIBNDR_FLAG_REF_ALLOC) {";
-                       pidl "\tNDR_ALLOC(ndr, r->out.$e->{NAME});";
-                       pidl "}";
-               }
-
-               if ($inout eq "in" && util::has_property($e, "ref")) {
-                       pidl "NDR_ALLOC(ndr, r->in.$e->{NAME});";
-               }
-
-               ParseElementPullScalar($e, "r->$inout.", "NDR_SCALARS|NDR_BUFFERS");
-               if (need_wire_pointer($e)) {
-                       ParseElementPullBuffer($e, "r->$inout.", "NDR_SCALARS|NDR_BUFFERS");
-               }
-       }
-}
-
-############################################################
-# allocate ref variables
-sub AllocateRefVars($)
-{
-       my $e = shift;
-       my $asize = util::array_size($e);
-
-       # note that if the variable is also an "in"
-       # variable then we copy the initial value from
-       # the in side
-
-       if (!defined $asize) {
-               # its a simple variable
-               pidl "NDR_ALLOC(ndr, r->out.$e->{NAME});";
-               if (util::has_property($e, "in")) {
-                       pidl "*r->out.$e->{NAME} = *r->in.$e->{NAME};";
-               } else {
-                       pidl "ZERO_STRUCTP(r->out.$e->{NAME});";
-               }
-               return;
-       }
-
-       # its an array
-       my $size = ParseExpr($e, $asize, "r->out.");
-       check_null_pointer($size);
-       pidl "NDR_ALLOC_N(ndr, r->out.$e->{NAME}, $size);";
-       if (util::has_property($e, "in")) {
-               pidl "memcpy(r->out.$e->{NAME},r->in.$e->{NAME},$size * sizeof(*r->in.$e->{NAME}));";
-       } else {
-               pidl "memset(r->out.$e->{NAME}, 0, $size * sizeof(*r->out.$e->{NAME}));";
-       }
-}
-
-#####################################################################
-# parse a function
-sub ParseFunctionPull($)
-{ 
-       my($fn) = shift;
-       my $static = fn_prefix($fn);
-
-       # pull function args
-       pidl $static . "NTSTATUS ndr_pull_$fn->{NAME}(struct ndr_pull *ndr, int flags, struct $fn->{NAME} *r)";
-       pidl "{";
-       indent;
-
-       # declare any internal pointers we need
-       foreach my $e (@{$fn->{ELEMENTS}}) {
-               if (need_wire_pointer($e)) {
-                       pidl "uint32_t _ptr_$e->{NAME};";
-               }
-       }
-
-       pidl "if (!(flags & NDR_IN)) goto ndr_out;";
-       pidl "";
-
-       # auto-init the out section of a structure. I originally argued that
-       # this was a bad idea as it hides bugs, but coping correctly
-       # with initialisation and not wiping ref vars is turning
-       # out to be too tricky (tridge)
-       foreach my $e (@{$fn->{ELEMENTS}}) {
-               if (util::has_property($e, "out")) {
-                       pidl "ZERO_STRUCT(r->out);";
-                       pidl "";
-                       last;
-               }
-       }
-
-       foreach my $e (@{$fn->{ELEMENTS}}) {
-               if (util::has_property($e, "in")) {
-                       ParseFunctionElementPull($e, "in");
-               }
-               # we need to allocate any reference output variables, so that
-               # a dcerpc backend can be sure they are non-null
-               if (util::has_property($e, "out") && util::has_property($e, "ref")) {
-                       AllocateRefVars($e);
-               }
-       }
-
-       foreach my $e (@{$fn->{ELEMENTS}}) {
-               if (util::has_property($e, "in")) {
-                       CheckArraySizes($e, "r->in.");
-               }
-       }
-
-       pidl "ndr_out:";
-       pidl "if (!(flags & NDR_OUT)) goto done;";
-       pidl "";
-
-       foreach my $e (@{$fn->{ELEMENTS}}) {
-               if (util::has_property($e, "out")) {
-                       ParseFunctionElementPull($e, "out");
-               }
-       }
-
-       foreach my $e (@{$fn->{ELEMENTS}}) {
-               if (util::has_property($e, "out")) {
-                       CheckArraySizes($e, "r->out.");
-               }
-       }
-
-       if ($fn->{RETURN_TYPE} && $fn->{RETURN_TYPE} ne "void") {
-               pidl "NDR_CHECK(ndr_pull_$fn->{RETURN_TYPE}(ndr, NDR_SCALARS, &r->out.result));";
-       }
-
-       pidl "done:";
-       pidl "";
-       pidl "return NT_STATUS_OK;";
-       deindent;
-       pidl "}";
-       pidl "";
-}
-
-#####################################################################
-# produce a function call table
-sub FunctionTable($)
-{
-       my($interface) = shift;
-       my($data) = $interface->{INHERITED_DATA};
-       my $count = 0;
-       my $uname = uc $interface->{NAME};
-
-       foreach my $d (@{$data}) {
-               if ($d->{TYPE} eq "FUNCTION") { $count++; }
-       }
-
-       return if ($count == 0);
-
-       pidl "static const struct dcerpc_interface_call $interface->{NAME}\_calls[] = {";
-       foreach my $d (@{$data}) {
-               if ($d->{TYPE} eq "FUNCTION") {
-                       pidl "\t{";
-                       pidl "\t\t\"$d->{NAME}\",";
-                       pidl "\t\tsizeof(struct $d->{NAME}),";
-                       pidl "\t\t(ndr_push_flags_fn_t) ndr_push_$d->{NAME},";
-                       pidl "\t\t(ndr_pull_flags_fn_t) ndr_pull_$d->{NAME},";
-                       pidl "\t\t(ndr_print_function_t) ndr_print_$d->{NAME}";
-                       pidl "\t},";
-               }
-       }
-       pidl "\t{ NULL, 0, NULL, NULL, NULL }";
-       pidl "};";
-       pidl "";
-
-       # If no endpoint is set, default to the interface name as a named pipe
-       if (! defined $interface->{PROPERTIES}->{endpoint}) {
-               $interface->{PROPERTIES}->{endpoint} = "\"ncacn_np:[\\\\pipe\\\\" . $interface->{NAME} . "]\"";
-       }
-
-       my @e = split / /, $interface->{PROPERTIES}->{endpoint};
-       my $endpoint_count = $#e + 1;
-
-       pidl "static const char * const $interface->{NAME}\_endpoint_strings[] = {";
-       foreach my $ep (@e) {
-               pidl "\t$ep, ";
-       }
-       pidl "};";
-       pidl "";
-
-       pidl "static const struct dcerpc_endpoint_list $interface->{NAME}\_endpoints = {";
-       pidl "\t$endpoint_count, $interface->{NAME}\_endpoint_strings";
-       pidl "};";
-       pidl "";
-
-       pidl "\nconst struct dcerpc_interface_table dcerpc_table_$interface->{NAME} = {";
-       pidl "\t\"$interface->{NAME}\",";
-       pidl "\tDCERPC_$uname\_UUID,";
-       pidl "\tDCERPC_$uname\_VERSION,";
-       pidl "\tDCERPC_$uname\_HELPSTRING,";
-       pidl "\t$count,";
-       pidl "\t$interface->{NAME}\_calls,";
-       pidl "\t&$interface->{NAME}\_endpoints";
-       pidl "};";
-       pidl "";
-
-       pidl "static NTSTATUS dcerpc_ndr_$interface->{NAME}_init(void)";
-       pidl "{";
-       pidl "\treturn librpc_register_interface(&dcerpc_table_$interface->{NAME});";
-       pidl "}";
-       pidl "";
-}
-
-#####################################################################
-# parse the interface definitions
-sub ParseInterface($)
-{
-       my($interface) = shift;
-       my($data) = $interface->{DATA};
-
-       # Push functions
-       foreach my $d (@{$data}) {
-               ($d->{TYPE} eq "TYPEDEF") &&
-                   ParseTypedefPush($d);
-               ($d->{TYPE} eq "FUNCTION") && 
-                   ParseFunctionPush($d);
-       }
-
-       # Pull functions
-       foreach my $d (@{$data}) {
-               ($d->{TYPE} eq "TYPEDEF") &&
-                   ParseTypedefPull($d);
-               ($d->{TYPE} eq "FUNCTION") && 
-                   ParseFunctionPull($d);
-       }
-       
-       # Print functions
-       foreach my $d (@{$data}) {
-               if ($d->{TYPE} eq "TYPEDEF" &&
-                   !util::has_property($d, "noprint")) {
-                       ParseTypedefPrint($d);
-               }
-               if ($d->{TYPE} eq "FUNCTION" &&
-                   !util::has_property($d, "noprint")) {
-                       ParseFunctionPrint($d);
-               }
-       }
-
-       # Size functions
-       foreach my $d (@{$data}) {
-               ($d->{TYPE} eq "TYPEDEF") && 
-                       ParseTypedefNdrSize($d);
-       }
-
-       FunctionTable($interface);
-}
-
-sub RegistrationFunction($$)
-{
-       my $idl = shift;
-       my $filename = shift;
-
-       $filename =~ /.*\/ndr_(.*).c/;
-       my $basename = $1;
-       pidl "NTSTATUS dcerpc_$basename\_init(void)";
-       pidl "{";
-       indent;
-       pidl "NTSTATUS status = NT_STATUS_OK;";
-       foreach my $interface (@{$idl}) {
-               next if $interface->{TYPE} ne "INTERFACE";
-
-               my $data = $interface->{INHERITED_DATA};
-               my $count = 0;
-               foreach my $d (@{$data}) {
-                       if ($d->{TYPE} eq "FUNCTION") { $count++; }
-               }
-
-               next if ($count == 0);
-
-               pidl "status = dcerpc_ndr_$interface->{NAME}_init();";
-               pidl "if (NT_STATUS_IS_ERR(status)) {";
-               pidl "\treturn status;";
-               pidl "}";
-               pidl "";
-       }
-       pidl "return status;";
-       deindent;
-       pidl "}";
-       pidl "";
-}
-
-sub CheckPointerTypes($$)
-{
-       my $s = shift;
-       my $default = shift;
-
-       foreach my $e (@{$s->{ELEMENTS}}) {
-               if ($e->{POINTERS}) {
-                       if (not defined(pointer_type($e))) {
-                               $e->{PROPERTIES}->{$default} = 1;
-                       }
-
-                       if (pointer_type($e) eq "ptr") {
-                               print "Warning: ptr is not supported by pidl yet\n";
-                       }
-               }
-       }
-}
-
-sub LoadInterface($)
-{
-       my $x = shift;
-
-       if (not util::has_property($x, "pointer_default")) {
-               # MIDL defaults to "ptr" in DCE compatible mode (/osf)
-               # and "unique" in Microsoft Extensions mode (default)
-               $x->{PROPERTIES}->{pointer_default} = "unique";
-       }
-
-       foreach my $d (@{$x->{DATA}}) {
-               if (($d->{TYPE} eq "DECLARE") or ($d->{TYPE} eq "TYPEDEF")) {
-                       if ($d->{DATA}->{TYPE} eq "STRUCT" or $d->{DATA}->{TYPE} eq "UNION") {
-                               CheckPointerTypes($d->{DATA}, $x->{PROPERTIES}->{pointer_default});
-                       }
-
-                       if (defined($d->{PROPERTIES}) && !defined($d->{DATA}->{PROPERTIES})) {
-                               $d->{DATA}->{PROPERTIES} = $d->{PROPERTIES};
-                       }
-               }
-               if ($d->{TYPE} eq "FUNCTION") {
-                       CheckPointerTypes($d, 
-                               $x->{PROPERTIES}->{pointer_default}  # MIDL defaults to "ref"
-                       );
-               }
-       }
-}
-
-sub Load($)
-{
-       my $idl = shift;
-
-       foreach my $x (@{$idl}) {
-               LoadInterface($x);
-       }
-}
-
-#####################################################################
-# parse a parsed IDL structure back into an IDL file
-sub Parse($$)
-{
-       my($idl) = shift;
-       my($filename) = shift;
-       my $h_filename = $filename;
-       $res = "";
-
-       Load($idl);
-
-       if ($h_filename =~ /(.*)\.c/) {
-               $h_filename = "$1.h";
-       }
-
-       pidl "/* parser auto-generated by pidl */";
-       pidl "";
-       pidl "#include \"includes.h\"";
-       pidl "#include \"$h_filename\"";
-       pidl "";
-
-       foreach my $x (@{$idl}) {
-               if ($x->{TYPE} eq "INTERFACE") { 
-                       needed::BuildNeeded($x);
-                       ParseInterface($x);
-               }
-       }
-
-       RegistrationFunction($idl, $filename);
-
-       return $res;
-}
 
 1;