r8806: Move data representation-independent data into seperate header
[sfrench/samba-autobuild/.git] / source4 / build / pidl / Parse / Pidl / Samba / NDR / Parser.pm
index 421f854e3ef123a63d3f880f5072d3d2aa748f7f..cde96ca0b28acb3261f7cfc36780f927f296abe9 100644 (file)
@@ -8,9 +8,9 @@
 package Parse::Pidl::Samba::NDR::Parser;
 
 use strict;
-use Parse::Pidl::Typelist;
-use Parse::Pidl::Util qw(has_property);
-use Parse::Pidl::NDR;
+use Parse::Pidl::Typelist qw(hasType getType mapType);
+use Parse::Pidl::Util qw(has_property ParseExpr);
+use Parse::Pidl::NDR qw(GetPrevLevel GetNextLevel ContainsDeferred);
 
 # list of known types
 my %typefamily;
@@ -45,15 +45,20 @@ sub append_prefix($$)
        return $var_name;
 }
 
-sub is_scalar_array($$)
+sub has_fast_array($$)
 {
        my ($e,$l) = @_;
 
        return 0 if ($l->{TYPE} ne "ARRAY");
 
-       my $nl = Parse::Pidl::NDR::GetNextLevel($e,$l);
-       return (($nl->{TYPE} eq "DATA") and 
-               (Parse::Pidl::Typelist::is_scalar($nl->{DATA_TYPE})));
+       my $nl = GetNextLevel($e,$l);
+       return 0 unless ($nl->{TYPE} eq "DATA");
+       return 0 unless (hasType($nl->{DATA_TYPE}));
+
+       my $t = getType($nl->{DATA_TYPE});
+
+       # Only uint8 and string have fast array functions at the moment
+       return ($t->{NAME} eq "uint8") or ($t->{NAME} eq "string");
 }
 
 sub get_pointer_to($)
@@ -212,18 +217,14 @@ sub ParseArrayPushHeader($$$$$)
 {
        my ($e,$l,$ndr,$var_name,$env) = @_;
 
-       if ($l->{IS_CONFORMANT} or $l->{IS_VARYING}) {
-               $var_name = get_pointer_to($var_name);
-       }
-
        my $size;
        my $length;
 
        if ($l->{IS_ZERO_TERMINATED}) {
                $size = $length = "ndr_string_length($var_name, sizeof(*$var_name))";
        } else {
-               $size = Parse::Pidl::Util::ParseExpr($l->{SIZE_IS}, $env);
-               $length = Parse::Pidl::Util::ParseExpr($l->{LENGTH_IS}, $env);
+               $size = ParseExpr($l->{SIZE_IS}, $env);
+               $length = ParseExpr($l->{LENGTH_IS}, $env);
        }
 
        if ((!$l->{IS_SURROUNDING}) and $l->{IS_CONFORMANT}) {
@@ -231,7 +232,7 @@ sub ParseArrayPushHeader($$$$$)
        }
        
        if ($l->{IS_VARYING}) {
-               pidl "NDR_CHECK(ndr_push_uint32($ndr, NDR_SCALARS, 0));";
+               pidl "NDR_CHECK(ndr_push_uint32($ndr, NDR_SCALARS, 0));";  # array offset
                pidl "NDR_CHECK(ndr_push_uint32($ndr, NDR_SCALARS, $length));";
        } 
 
@@ -244,10 +245,6 @@ sub ParseArrayPullHeader($$$$$)
 {
        my ($e,$l,$ndr,$var_name,$env) = @_;
 
-       if ($l->{IS_CONFORMANT} or $l->{IS_VARYING}) {
-               $var_name = get_pointer_to($var_name);
-       }
-
        my $length;
        my $size;
 
@@ -256,7 +253,7 @@ sub ParseArrayPullHeader($$$$$)
        } elsif ($l->{IS_ZERO_TERMINATED}) { # Noheader arrays
                $length = $size = "ndr_get_string_size($ndr, sizeof(*$var_name))";
        } else {
-               $length = $size = Parse::Pidl::Util::ParseExpr($l->{SIZE_IS}, $env);
+               $length = $size = ParseExpr($l->{SIZE_IS}, $env);
        }
 
        if ((!$l->{IS_SURROUNDING}) and $l->{IS_CONFORMANT}) {
@@ -280,13 +277,13 @@ sub ParseArrayPullHeader($$$$$)
        }
 
        if ($l->{IS_CONFORMANT} and not $l->{IS_ZERO_TERMINATED}) {
-               my $size = Parse::Pidl::Util::ParseExpr($l->{SIZE_IS}, $env);
+               my $size = ParseExpr($l->{SIZE_IS}, $env);
                check_null_pointer($size);
                pidl "NDR_CHECK(ndr_check_array_size(ndr, (void*)" . get_pointer_to($var_name) . ", $size));";
        }
 
        if ($l->{IS_VARYING} and not $l->{IS_ZERO_TERMINATED}) {
-               my $length = Parse::Pidl::Util::ParseExpr($l->{LENGTH_IS}, $env);
+               my $length = ParseExpr($l->{LENGTH_IS}, $env);
                check_null_pointer($length);
                pidl "NDR_CHECK(ndr_check_array_length(ndr, (void*)" . get_pointer_to($var_name) . ", $length));";
        }
@@ -313,7 +310,7 @@ sub compression_clen($$$)
        my $compression = $l->{COMPRESSION};
        my ($alg, $clen, $dlen) = split(/ /, $compression);
 
-       return Parse::Pidl::Util::ParseExpr($clen, $env);
+       return ParseExpr($clen, $env);
 }
 
 sub compression_dlen($$$)
@@ -322,7 +319,7 @@ sub compression_dlen($$$)
        my $compression = $l->{COMPRESSION};
        my ($alg, $clen, $dlen) = split(/ /, $compression);
 
-       return Parse::Pidl::Util::ParseExpr($dlen, $env);
+       return ParseExpr($dlen, $env);
 }
 
 sub ParseCompressionPushStart($$$)
@@ -441,7 +438,7 @@ sub ParseSubcontextPushEnd($$$$)
 {
        my ($e,$l,$ndr_flags,$env) = @_;
        my $ndr = "_ndr_$e->{NAME}";
-       my $subcontext_size = Parse::Pidl::Util::ParseExpr($l->{SUBCONTEXT_SIZE},$env);
+       my $subcontext_size = ParseExpr($l->{SUBCONTEXT_SIZE},$env);
 
        if (defined $l->{COMPRESSION}) {
                ParseCompressionPushEnd($e, $l, $ndr);
@@ -461,7 +458,7 @@ sub ParseSubcontextPullStart($$$$$$)
 {
        my ($e,$l,$ndr,$var_name,$ndr_flags,$env) = @_;
        my $retndr = "_ndr_$e->{NAME}";
-       my $subcontext_size = Parse::Pidl::Util::ParseExpr($l->{SUBCONTEXT_SIZE},$env);
+       my $subcontext_size = ParseExpr($l->{SUBCONTEXT_SIZE},$env);
 
        pidl "{";
        indent;
@@ -495,7 +492,7 @@ sub ParseSubcontextPullEnd($$$)
 
        my $advance;
        if (defined($l->{SUBCONTEXT_SIZE}) and ($l->{SUBCONTEXT_SIZE} ne "-1")) {
-               $advance = Parse::Pidl::Util::ParseExpr($l->{SUBCONTEXT_SIZE},$env);
+               $advance = ParseExpr($l->{SUBCONTEXT_SIZE},$env);
        } elsif ($l->{HEADER_SIZE}) {
                $advance = "$ndr->data_size";
        } else {
@@ -512,28 +509,28 @@ sub ParseElementPushLevel
 
        my $ndr_flags = CalcNdrFlags($l, $primitives, $deferred);
 
+       if ($l->{TYPE} eq "ARRAY" and ($l->{IS_CONFORMANT} or $l->{IS_VARYING})) {
+               $var_name = get_pointer_to($var_name);
+       }
+
        if (defined($ndr_flags)) {
                if ($l->{TYPE} eq "SUBCONTEXT") {
                        $ndr = ParseSubcontextPushStart($e, $l, $ndr, $var_name, $ndr_flags);
-                       ParseElementPushLevel($e, Parse::Pidl::NDR::GetNextLevel($e, $l), $ndr, $var_name, $env, 1, 1);
+                       ParseElementPushLevel($e, GetNextLevel($e, $l), $ndr, $var_name, $env, 1, 1);
                        ParseSubcontextPushEnd($e, $l, $ndr_flags, $env);
                } elsif ($l->{TYPE} eq "POINTER") {
                        ParsePtrPush($e, $l, $var_name);
                } elsif ($l->{TYPE} eq "ARRAY") {
                        my $length = ParseArrayPushHeader($e, $l, $ndr, $var_name, $env); 
-                       # Allow speedups for arrays of scalar types
-                       if (is_scalar_array($e,$l)) {
-                               if ($l->{IS_CONFORMANT} or $l->{IS_VARYING}) {
-                                       $var_name = get_pointer_to($var_name);
-                               }
 
-                               my $nl = Parse::Pidl::NDR::GetNextLevel($e, $l);
+                       my $nl = GetNextLevel($e, $l);
 
-                               if (has_property($e, "charset")) {
-                                       pidl "NDR_CHECK(ndr_push_charset($ndr, $ndr_flags, $var_name, $length, sizeof(" . Parse::Pidl::Typelist::mapType($nl->{DATA_TYPE}) . "), CH_$e->{PROPERTIES}->{charset}));";
-                               } else {
-                                       pidl "NDR_CHECK(ndr_push_array_$nl->{DATA_TYPE}($ndr, $ndr_flags, $var_name, $length));";
-                               } 
+                       # Allow speedups for arrays of scalar types
+                       if (has_property($e, "charset")) {
+                               pidl "NDR_CHECK(ndr_push_charset($ndr, $ndr_flags, $var_name, $length, sizeof(" . Parse::Pidl::Typelist::mapType($nl->{DATA_TYPE}) . "), CH_$e->{PROPERTIES}->{charset}));";
+                               return;
+                       } elsif (has_fast_array($e,$l)) {
+                               pidl "NDR_CHECK(ndr_push_array_$nl->{DATA_TYPE}($ndr, $ndr_flags, $var_name, $length));";
                                return;
                        } 
                } elsif ($l->{TYPE} eq "SWITCH") {
@@ -552,39 +549,36 @@ sub ParseElementPushLevel
                        }
                }
                $var_name = get_value_of($var_name);
-               ParseElementPushLevel($e, Parse::Pidl::NDR::GetNextLevel($e, $l), $ndr, $var_name, $env, $primitives, $deferred);
+               ParseElementPushLevel($e, GetNextLevel($e, $l), $ndr, $var_name, $env, 1, 1);
 
                if ($l->{POINTER_TYPE} ne "ref") {
                        deindent;
                        pidl "}";
                }
-       } elsif ($l->{TYPE} eq "ARRAY" and not is_scalar_array($e,$l)) {
-               my $length = Parse::Pidl::Util::ParseExpr($l->{LENGTH_IS}, $env);
+       } elsif ($l->{TYPE} eq "ARRAY" and not has_fast_array($e,$l) and
+               not has_property($e, "charset")) {
+               my $length = ParseExpr($l->{LENGTH_IS}, $env);
                my $counter = "cntr_$e->{NAME}_$l->{LEVEL_INDEX}";
 
                $var_name = $var_name . "[$counter]";
 
-               if ($l->{IS_VARYING} or $l->{IS_CONFORMANT}) {
-                       $var_name = get_pointer_to($var_name);
-               }
-
                if (($primitives and not $l->{IS_DEFERRED}) or ($deferred and $l->{IS_DEFERRED})) {
                        pidl "for ($counter = 0; $counter < $length; $counter++) {";
                        indent;
-                       ParseElementPushLevel($e, Parse::Pidl::NDR::GetNextLevel($e, $l), $ndr, $var_name, $env, 1, 0);
+                       ParseElementPushLevel($e, GetNextLevel($e, $l), $ndr, $var_name, $env, 1, 0);
                        deindent;
                        pidl "}";
                }
 
-               if ($deferred and Parse::Pidl::NDR::ContainsDeferred($e, $l)) {
+               if ($deferred and ContainsDeferred($e, $l)) {
                        pidl "for ($counter = 0; $counter < $length; $counter++) {";
                        indent;
-                       ParseElementPushLevel($e, Parse::Pidl::NDR::GetNextLevel($e, $l), $ndr, $var_name, $env, 0, 1);
+                       ParseElementPushLevel($e, GetNextLevel($e, $l), $ndr, $var_name, $env, 0, 1);
                        deindent;
                        pidl "}";
                }       
        } elsif ($l->{TYPE} eq "SWITCH") {
-               ParseElementPushLevel($e, Parse::Pidl::NDR::GetNextLevel($e, $l), $ndr, $var_name, $env, $primitives, $deferred);
+               ParseElementPushLevel($e, GetNextLevel($e, $l), $ndr, $var_name, $env, $primitives, $deferred);
        }
 }
 
@@ -599,12 +593,12 @@ sub ParseElementPush($$$$$$)
 
        $var_name = append_prefix($e, $var_name);
 
-       return unless $primitives or ($deferred and Parse::Pidl::NDR::ContainsDeferred($e, $e->{LEVELS}[0]));
+       return unless $primitives or ($deferred and ContainsDeferred($e, $e->{LEVELS}[0]));
 
        start_flags($e);
 
        if (my $value = has_property($e, "value")) {
-               $var_name = Parse::Pidl::Util::ParseExpr($value, $env);
+               $var_name = ParseExpr($value, $env);
        }
 
        ParseElementPushLevel($e, $e->{LEVELS}[0], $ndr, $var_name, $env, $primitives, $deferred);
@@ -645,7 +639,7 @@ sub ParseElementPrint($$$)
        return if (has_property($e, "noprint"));
 
        if (my $value = has_property($e, "value")) {
-               $var_name = "(ndr->flags & LIBNDR_PRINT_SET_VALUES)?" . Parse::Pidl::Util::ParseExpr($value,$env) . ":$var_name";
+               $var_name = "(ndr->flags & LIBNDR_PRINT_SET_VALUES)?" . ParseExpr($value,$env) . ":$var_name";
        }
 
        foreach my $l (@{$e->{LEVELS}}) {
@@ -660,48 +654,44 @@ sub ParseElementPrint($$$)
                } elsif ($l->{TYPE} eq "ARRAY") {
                        my $length;
 
-                       if (is_scalar_array($e, $l) and ($l->{IS_CONFORMANT} or $l->{IS_VARYING}))
+                       if ($l->{IS_CONFORMANT} or $l->{IS_VARYING}) 
                                $var_name = get_pointer_to($var_name); 
                        }
                        
                        if ($l->{IS_ZERO_TERMINATED}) {
                                $length = "ndr_string_length($var_name, sizeof(*$var_name))";
                        } else {
-                               $length = Parse::Pidl::Util::ParseExpr($l->{LENGTH_IS}, $env);
+                               $length = ParseExpr($l->{LENGTH_IS}, $env);
                        }
 
-                       if (is_scalar_array($e, $l)) {
-                               if (has_property($e, "charset")) {
-                                       pidl "ndr_print_string(ndr, \"$e->{NAME}\", $var_name);";
-                               } else {
-                                       my $nl = Parse::Pidl::NDR::GetNextLevel($e, $l);
-                                       pidl "ndr_print_array_$nl->{DATA_TYPE}(ndr, \"$e->{NAME}\", $var_name, $length);";
-                               } 
+                       if (has_property($e, "charset")) {
+                               pidl "ndr_print_string(ndr, \"$e->{NAME}\", $var_name);";
                                last;
-                       }
-
-                       my $counter = "cntr_$e->{NAME}_$l->{LEVEL_INDEX}";
-
-                       pidl "ndr->print(ndr, \"\%s: ARRAY(\%d)\", \"$e->{NAME}\", $length);";
-                       pidl 'ndr->depth++;';
-                       pidl "for ($counter=0;$counter<$length;$counter++) {";
-                       indent;
-                       pidl "char *idx_$l->{LEVEL_INDEX}=NULL;";
-                       pidl "asprintf(&idx_$l->{LEVEL_INDEX}, \"[\%d]\", $counter);";
-                       pidl "if (idx_$l->{LEVEL_INDEX}) {";
-                       indent;
-
-                       $var_name = $var_name . "[$counter]";
+                       } elsif (has_fast_array($e, $l)) {
+                               my $nl = GetNextLevel($e, $l);
+                               pidl "ndr_print_array_$nl->{DATA_TYPE}(ndr, \"$e->{NAME}\", $var_name, $length);";
+                               last;
+                       } else {
+                               my $counter = "cntr_$e->{NAME}_$l->{LEVEL_INDEX}";
 
-                       if ($l->{IS_VARYING} or $l->{IS_CONFORMANT}){ $var_name = get_pointer_to($var_name); }
+                               pidl "ndr->print(ndr, \"\%s: ARRAY(\%d)\", \"$e->{NAME}\", $length);";
+                               pidl 'ndr->depth++;';
+                               pidl "for ($counter=0;$counter<$length;$counter++) {";
+                               indent;
+                               pidl "char *idx_$l->{LEVEL_INDEX}=NULL;";
+                               pidl "asprintf(&idx_$l->{LEVEL_INDEX}, \"[\%d]\", $counter);";
+                               pidl "if (idx_$l->{LEVEL_INDEX}) {";
+                               indent;
 
+                               $var_name = $var_name . "[$counter]";
+                       }
                } elsif ($l->{TYPE} eq "DATA") {
                        if (not Parse::Pidl::Typelist::is_scalar($l->{DATA_TYPE}) or Parse::Pidl::Typelist::scalar_is_reference($l->{DATA_TYPE})) {
                                $var_name = get_pointer_to($var_name);
                        }
                        pidl "ndr_print_$l->{DATA_TYPE}(ndr, \"$e->{NAME}\", $var_name);";
                } elsif ($l->{TYPE} eq "SWITCH") {
-                       my $switch_var = Parse::Pidl::Util::ParseExpr($l->{SWITCH_IS}, $env);
+                       my $switch_var = ParseExpr($l->{SWITCH_IS}, $env);
                        check_null_pointer_void($switch_var);
                        pidl "ndr_print_set_switch_value(ndr, " . get_pointer_to($var_name) . ", $switch_var);";
                } 
@@ -714,7 +704,9 @@ sub ParseElementPrint($$$)
                                pidl "}";
                        }
                        pidl "ndr->depth--;";
-               } elsif ($l->{TYPE} eq "ARRAY" and not is_scalar_array($e, $l)) {
+               } elsif (($l->{TYPE} eq "ARRAY")
+                       and not has_property($e, "charset")
+                       and not has_fast_array($e,$l)) {
                        pidl "free(idx_$l->{LEVEL_INDEX});";
                        deindent;
                        pidl "}";
@@ -730,7 +722,7 @@ sub ParseElementPrint($$$)
 sub ParseSwitchPull($$$$$$)
 {
        my($e,$l,$ndr,$var_name,$ndr_flags,$env) = @_;
-       my $switch_var = Parse::Pidl::Util::ParseExpr($l->{SWITCH_IS}, $env);
+       my $switch_var = ParseExpr($l->{SWITCH_IS}, $env);
 
        check_null_pointer($switch_var);
 
@@ -743,7 +735,7 @@ sub ParseSwitchPull($$$$$$)
 sub ParseSwitchPush($$$$$$)
 {
        my($e,$l,$ndr,$var_name,$ndr_flags,$env) = @_;
-       my $switch_var = Parse::Pidl::Util::ParseExpr($l->{SWITCH_IS}, $env);
+       my $switch_var = ParseExpr($l->{SWITCH_IS}, $env);
 
        check_null_pointer($switch_var);
        $var_name = get_pointer_to($var_name);
@@ -814,31 +806,29 @@ sub ParseElementPullLevel
 
        my $ndr_flags = CalcNdrFlags($l, $primitives, $deferred);
 
+       if ($l->{TYPE} eq "ARRAY" and ($l->{IS_VARYING} or $l->{IS_CONFORMANT})) {
+               $var_name = get_pointer_to($var_name);
+       }
+
        # Only pull something if there's actually something to be pulled
        if (defined($ndr_flags)) {
                if ($l->{TYPE} eq "SUBCONTEXT") {
                        ($ndr,$var_name) = ParseSubcontextPullStart($e, $l, $ndr, $var_name, $ndr_flags, $env);
-                       ParseElementPullLevel($e,Parse::Pidl::NDR::GetNextLevel($e,$l), $ndr, $var_name, $env, 1, 1);
+                       ParseElementPullLevel($e, GetNextLevel($e,$l), $ndr, $var_name, $env, 1, 1);
                        ParseSubcontextPullEnd($e, $l, $env);
                } elsif ($l->{TYPE} eq "ARRAY") {
                        my $length = ParseArrayPullHeader($e, $l, $ndr, $var_name, $env); 
 
-                       # Speed things up a little - special array pull functions
-                       # for scalars
-                       if (is_scalar_array($e, $l)) {
-                               if ($l->{IS_VARYING} or $l->{IS_CONFORMANT}) {
-                                       $var_name = get_pointer_to($var_name);
-                               }
-                               my $nl = Parse::Pidl::NDR::GetNextLevel($e, $l);
-
-                               if (has_property($e, "charset")) {
-                                       pidl "NDR_CHECK(ndr_pull_charset($ndr, $ndr_flags, ".get_pointer_to($var_name).", $length, sizeof(" . Parse::Pidl::Typelist::mapType($nl->{DATA_TYPE}) . "), CH_$e->{PROPERTIES}->{charset}));";
-                               } else {
-                                       pidl "NDR_CHECK(ndr_pull_array_$nl->{DATA_TYPE}($ndr, $ndr_flags, $var_name, $length));";
-                                       if ($l->{IS_ZERO_TERMINATED}) {
-                                               # Make sure last element is zero!
-                                               pidl "NDR_CHECK(ndr_check_string_terminator($ndr, $var_name, $length, sizeof(*$var_name)));";
-                                       }
+                       my $nl = GetNextLevel($e, $l);
+
+                       if (has_property($e, "charset")) {
+                               pidl "NDR_CHECK(ndr_pull_charset($ndr, $ndr_flags, ".get_pointer_to($var_name).", $length, sizeof(" . Parse::Pidl::Typelist::mapType($nl->{DATA_TYPE}) . "), CH_$e->{PROPERTIES}->{charset}));";
+                               return;
+                       } elsif (has_fast_array($e, $l)) {
+                               pidl "NDR_CHECK(ndr_pull_array_$nl->{DATA_TYPE}($ndr, $ndr_flags, $var_name, $length));";
+                               if ($l->{IS_ZERO_TERMINATED}) {
+                                       # Make sure last element is zero!
+                                       pidl "NDR_CHECK(ndr_check_string_terminator($ndr, $var_name, $length, sizeof(*$var_name)));";
                                }
                                return;
                        }
@@ -865,7 +855,7 @@ sub ParseElementPullLevel
                }
 
                $var_name = get_value_of($var_name);
-               ParseElementPullLevel($e,Parse::Pidl::NDR::GetNextLevel($e,$l), $ndr, $var_name, $env, $primitives, $deferred);
+               ParseElementPullLevel($e,GetNextLevel($e,$l), $ndr, $var_name, $env, 1, 1);
 
                if ($l->{POINTER_TYPE} ne "ref") {
                        if ($l->{POINTER_TYPE} eq "relative") {
@@ -874,19 +864,17 @@ sub ParseElementPullLevel
                        deindent;
                        pidl "}";
                }
-       } elsif ($l->{TYPE} eq "ARRAY" and not is_scalar_array($e,$l)) {
-               my $length = Parse::Pidl::Util::ParseExpr($l->{LENGTH_IS}, $env);
+       } elsif ($l->{TYPE} eq "ARRAY" and 
+                       not has_fast_array($e,$l) and not has_property($e, "charset")) {
+               my $length = ParseExpr($l->{LENGTH_IS}, $env);
                my $counter = "cntr_$e->{NAME}_$l->{LEVEL_INDEX}";
 
                $var_name = $var_name . "[$counter]";
-               if ($l->{IS_VARYING} or $l->{IS_CONFORMANT}) {
-                       $var_name = get_pointer_to($var_name);
-               }
 
                if (($primitives and not $l->{IS_DEFERRED}) or ($deferred and $l->{IS_DEFERRED})) {
                        pidl "for ($counter = 0; $counter < $length; $counter++) {";
                        indent;
-                       ParseElementPullLevel($e,Parse::Pidl::NDR::GetNextLevel($e,$l), $ndr, $var_name, $env, 1, 0);
+                       ParseElementPullLevel($e,GetNextLevel($e,$l), $ndr, $var_name, $env, 1, 0);
                        deindent;
                        pidl "}";
 
@@ -896,15 +884,15 @@ sub ParseElementPullLevel
                        }
                }
 
-               if ($deferred and Parse::Pidl::NDR::ContainsDeferred($e, $l)) {
+               if ($deferred and ContainsDeferred($e, $l)) {
                        pidl "for ($counter = 0; $counter < $length; $counter++) {";
                        indent;
-                       ParseElementPullLevel($e,Parse::Pidl::NDR::GetNextLevel($e,$l), $ndr, $var_name, $env, 0, 1);
+                       ParseElementPullLevel($e,GetNextLevel($e,$l), $ndr, $var_name, $env, 0, 1);
                        deindent;
                        pidl "}";
                }
        } elsif ($l->{TYPE} eq "SWITCH") {
-               ParseElementPullLevel($e,Parse::Pidl::NDR::GetNextLevel($e,$l), $ndr, $var_name, $env, $primitives, $deferred);
+               ParseElementPullLevel($e,GetNextLevel($e,$l), $ndr, $var_name, $env, $primitives, $deferred);
        }
 }
 
@@ -918,7 +906,7 @@ sub ParseElementPull($$$$$$)
 
        $var_name = append_prefix($e, $var_name);
 
-       return unless $primitives or ($deferred and Parse::Pidl::NDR::ContainsDeferred($e, $e->{LEVELS}[0]));
+       return unless $primitives or ($deferred and ContainsDeferred($e, $e->{LEVELS}[0]));
 
        start_flags($e);
 
@@ -933,7 +921,7 @@ sub ParsePtrPull($$$$)
 {
        my($e,$l,$ndr,$var_name) = @_;
 
-       my $nl = Parse::Pidl::NDR::GetNextLevel($e, $l);
+       my $nl = GetNextLevel($e, $l);
        my $next_is_array = ($nl->{TYPE} eq "ARRAY");
        my $next_is_string = (($nl->{TYPE} eq "DATA") and 
                                                 ($nl->{DATA_TYPE} eq "string"));
@@ -1008,7 +996,7 @@ sub ParseStructPush($$)
 
                if (defined($e->{LEVELS}[0]) and 
                        $e->{LEVELS}[0]->{TYPE} eq "ARRAY") {
-                       my $size = Parse::Pidl::Util::ParseExpr($e->{LEVELS}[0]->{SIZE_IS}, $env);
+                       my $size = ParseExpr($e->{LEVELS}[0]->{SIZE_IS}, $env);
 
                        pidl "NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, $size));";
                } else {
@@ -1112,31 +1100,18 @@ sub ParseEnumPrint($$)
        end_flags($enum);
 }
 
-sub ArgsEnumPush($)
+sub DeclEnum($)
 {
-       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";
+       my ($e,$t) = @_;
+       return "enum $e->{NAME} " . 
+               ($t eq "pull"?"*":"") . "r";
 }
 
 $typefamily{ENUM} = {
+       DECL => \&DeclEnum,
        PUSH_FN_BODY => \&ParseEnumPush,
-       PUSH_FN_ARGS => \&ArgsEnumPush,
        PULL_FN_BODY => \&ParseEnumPull,
-       PULL_FN_ARGS => \&ArgsEnumPull,
        PRINT_FN_BODY => \&ParseEnumPrint,
-       PRINT_FN_ARGS => \&ArgsEnumPrint,
 };
 
 #####################################################################
@@ -1208,34 +1183,18 @@ sub ParseBitmapPrint($$)
        end_flags($bitmap);
 }
 
-sub ArgsBitmapPush($)
-{
-       my $e = shift;
-       my $type_decl = Parse::Pidl::Typelist::mapType($e->{DATA}->{BASE_TYPE});
-       return "struct ndr_push *ndr, int ndr_flags, $type_decl r";
-}
-
-sub ArgsBitmapPrint($)
+sub DeclBitmap($$)
 {
-       my $e = shift;
-       my $type_decl = Parse::Pidl::Typelist::mapType($e->{DATA}->{BASE_TYPE});
-       return "struct ndr_print *ndr, const char *name, $type_decl r";
-}
-
-sub ArgsBitmapPull($)
-{
-       my $e = shift;
-       my $type_decl = Parse::Pidl::Typelist::mapType($e->{DATA}->{BASE_TYPE});
-       return "struct ndr_pull *ndr, int ndr_flags, $type_decl *r";
+       my ($e,$t) = @_;
+       return mapType(Parse::Pidl::Typelist::bitmap_type_fn($e->{DATA})) . 
+               ($t eq "pull"?" *":" ") . "r";
 }
 
 $typefamily{BITMAP} = {
+       DECL => \&DeclBitmap,
        PUSH_FN_BODY => \&ParseBitmapPush,
-       PUSH_FN_ARGS => \&ArgsBitmapPush,
        PULL_FN_BODY => \&ParseBitmapPull,
-       PULL_FN_ARGS => \&ArgsBitmapPull,
        PRINT_FN_BODY => \&ParseBitmapPrint,
-       PRINT_FN_ARGS => \&ArgsBitmapPrint,
 };
 
 #####################################################################
@@ -1282,7 +1241,8 @@ sub DeclareArrayVariables($)
        my $e = shift;
 
        foreach my $l (@{$e->{LEVELS}}) {
-               next if (is_scalar_array($e,$l));
+               next if has_fast_array($e,$l);
+               next if has_property($e, "charset");
                if ($l->{TYPE} eq "ARRAY") {
                        pidl "uint32_t cntr_$e->{NAME}_$l->{LEVEL_INDEX};";
                }
@@ -1363,22 +1323,10 @@ sub ParseStructNdrSize($)
        pidl "return ndr_size_struct(r, flags, (ndr_push_flags_fn_t)ndr_push_$t->{NAME});";
 }
 
-sub ArgsStructPush($)
+sub DeclStruct($)
 {
-       my $e = shift;
-       return "struct ndr_push *ndr, int ndr_flags, const struct $e->{NAME} *r";
-}
-
-sub ArgsStructPrint($)
-{
-       my $e = shift;
-       return "struct ndr_print *ndr, const char *name, const struct $e->{NAME} *r";
-}
-
-sub ArgsStructPull($)
-{
-       my $e = shift;
-       return "struct ndr_pull *ndr, int ndr_flags, struct $e->{NAME} *r";
+       my ($e,$t) = @_;
+       return ($t ne "pull"?"const ":"") . "struct $e->{NAME} *r";
 }
 
 sub ArgsStructNdrSize($)
@@ -1389,11 +1337,9 @@ sub ArgsStructNdrSize($)
 
 $typefamily{STRUCT} = {
        PUSH_FN_BODY => \&ParseStructPush,
-       PUSH_FN_ARGS => \&ArgsStructPush,
+       DECL => \&DeclStruct,
        PULL_FN_BODY => \&ParseStructPull,
-       PULL_FN_ARGS => \&ArgsStructPull,
        PRINT_FN_BODY => \&ParseStructPrint,
-       PRINT_FN_ARGS => \&ArgsStructPrint,
        SIZE_FN_BODY => \&ParseStructNdrSize,
        SIZE_FN_ARGS => \&ArgsStructNdrSize,
 };
@@ -1552,7 +1498,7 @@ sub ParseUnionPull($$)
        pidl "int level;";
        if (defined($switch_type)) {
                if (Parse::Pidl::Typelist::typeIs($switch_type, "ENUM")) {
-                       $switch_type = Parse::Pidl::Typelist::enum_type_fn(Parse::Pidl::Typelist::getType($switch_type));
+                       $switch_type = Parse::Pidl::Typelist::enum_type_fn(getType($switch_type));
                }
                pidl Parse::Pidl::Typelist::mapType($switch_type) . " _level;";
        }
@@ -1636,22 +1582,10 @@ sub ParseUnionPull($$)
        pidl "ndr_pull_restore_relative_base_offset(ndr, _save_relative_base_offset);" if defined($e->{PROPERTIES}{relative_base});
 }
 
-sub ArgsUnionPush($)
+sub DeclUnion($$)
 {
-       my $e = shift;
-       return "struct ndr_push *ndr, int ndr_flags, const union $e->{NAME} *r";
-}
-
-sub ArgsUnionPrint($)
-{
-       my $e = shift;
-       return "struct ndr_print *ndr, const char *name, const union $e->{NAME} *r";
-}
-
-sub ArgsUnionPull($)
-{
-       my $e = shift;
-       return "struct ndr_pull *ndr, int ndr_flags, union $e->{NAME} *r";
+       my ($e,$t) = @_;
+       return ($t ne "pull"?"const ":"") . "union $e->{NAME} *r";
 }
 
 sub ArgsUnionNdrSize($)
@@ -1662,11 +1596,9 @@ sub ArgsUnionNdrSize($)
 
 $typefamily{UNION} = {
        PUSH_FN_BODY => \&ParseUnionPush,
-       PUSH_FN_ARGS => \&ArgsUnionPush,
+       DECL => \&DeclUnion,
        PULL_FN_BODY => \&ParseUnionPull,
-       PULL_FN_ARGS => \&ArgsUnionPull,
        PRINT_FN_BODY => \&ParseUnionPrint,
-       PRINT_FN_ARGS => \&ArgsUnionPrint,
        SIZE_FN_ARGS => \&ArgsUnionNdrSize,
        SIZE_FN_BODY => \&ParseUnionNdrSize,
 };
@@ -1677,8 +1609,8 @@ sub ParseTypedefPush($)
 {
        my($e) = shift;
 
-       my $args = $typefamily{$e->{DATA}->{TYPE}}->{PUSH_FN_ARGS}->($e);
-       pidl fn_prefix($e) . "NTSTATUS ndr_push_$e->{NAME}($args)";
+       my $args = $typefamily{$e->{DATA}->{TYPE}}->{DECL}->($e,"push");
+       pidl fn_prefix($e) . "NTSTATUS ndr_push_$e->{NAME}(struct ndr_push *ndr, int ndr_flags, $args)";
 
        pidl "{";
        indent;
@@ -1695,9 +1627,9 @@ sub ParseTypedefPull($)
 {
        my($e) = shift;
 
-       my $args = $typefamily{$e->{DATA}->{TYPE}}->{PULL_FN_ARGS}->($e);
+       my $args = $typefamily{$e->{DATA}->{TYPE}}->{DECL}->($e,"pull");
 
-       pidl fn_prefix($e) . "NTSTATUS ndr_pull_$e->{NAME}($args)";
+       pidl fn_prefix($e) . "NTSTATUS ndr_pull_$e->{NAME}(struct ndr_pull *ndr, int ndr_flags, $args)";
 
        pidl "{";
        indent;
@@ -1714,9 +1646,9 @@ sub ParseTypedefPrint($)
 {
        my($e) = shift;
 
-       my $args = $typefamily{$e->{DATA}->{TYPE}}->{PRINT_FN_ARGS}->($e);
+       my $args = $typefamily{$e->{DATA}->{TYPE}}->{DECL}->($e,"print");
 
-       pidl "void ndr_print_$e->{NAME}($args)";
+       pidl "void ndr_print_$e->{NAME}(struct ndr_print *ndr, const char *name, $args)";
        pidl "{";
        indent;
        $typefamily{$e->{DATA}->{TYPE}}->{PRINT_FN_BODY}->($e->{DATA}, $e->{NAME});
@@ -1864,10 +1796,10 @@ sub AllocateArrayLevel($$$$$)
 
        return if (has_property($e, "charset"));
 
-       my $var = Parse::Pidl::Util::ParseExpr($e->{NAME}, $env);
+       my $var = ParseExpr($e->{NAME}, $env);
 
        check_null_pointer($size);
-       my $pl = Parse::Pidl::NDR::GetPrevLevel($e, $l);
+       my $pl = GetPrevLevel($e, $l);
        if (defined($pl) and 
            $pl->{TYPE} eq "POINTER" and 
            $pl->{POINTER_TYPE} eq "ref"
@@ -1938,7 +1870,7 @@ sub ParseFunctionPull($)
                        and   $e->{LEVELS}[1]->{IS_ZERO_TERMINATED});
 
                if ($e->{LEVELS}[1]->{TYPE} eq "ARRAY") {
-                       my $size = Parse::Pidl::Util::ParseExpr($e->{LEVELS}[1]->{SIZE_IS}, $env);
+                       my $size = ParseExpr($e->{LEVELS}[1]->{SIZE_IS}, $env);
                        check_null_pointer($size);
                        
                        pidl "NDR_ALLOC_N(ndr, r->out.$e->{NAME}, $size);";
@@ -2145,6 +2077,8 @@ sub Parse($$)
        pidl "/* parser auto-generated by pidl */";
        pidl "";
        pidl "#include \"includes.h\"";
+       pidl "#include \"librpc/gen_ndr/ndr_misc.h\"";
+       pidl "#include \"librpc/gen_ndr/ndr_dcerpc.h\"";
        pidl "#include \"$h_filename\"";
        pidl "";