pidl: add support for 'pipe' at the NDR layer
authorStefan Metzmacher <metze@samba.org>
Mon, 20 Sep 2010 23:44:38 +0000 (01:44 +0200)
committerStefan Metzmacher <metze@samba.org>
Thu, 10 Mar 2011 13:31:19 +0000 (14:31 +0100)
metze

pidl/lib/Parse/Pidl/NDR.pm
pidl/lib/Parse/Pidl/Samba4/Header.pm
pidl/lib/Parse/Pidl/Samba4/NDR/Client.pm
pidl/lib/Parse/Pidl/Samba4/NDR/Parser.pm
pidl/lib/Parse/Pidl/Typelist.pm

index 7b1e0078311957a4347860478d387053515c81cc..d91c324b536ebaf030b56eaded9e5de14eefeadb 100644 (file)
@@ -39,7 +39,7 @@ $VERSION = '0.01';
 
 use strict;
 use Parse::Pidl qw(warning fatal);
 
 use strict;
 use Parse::Pidl qw(warning fatal);
-use Parse::Pidl::Typelist qw(hasType getType expandAlias mapScalarType);
+use Parse::Pidl::Typelist qw(hasType getType typeIs expandAlias mapScalarType is_fixed_size_scalar);
 use Parse::Pidl::Util qw(has_property property_matches);
 
 # Alignment of the built-in scalar types
 use Parse::Pidl::Util qw(has_property property_matches);
 
 # Alignment of the built-in scalar types
@@ -115,6 +115,51 @@ sub GetElementLevelTable($$$)
                warning($e, "[out] argument `$e->{NAME}' not a pointer") if ($needptrs > $e->{POINTERS});
        }
 
                warning($e, "[out] argument `$e->{NAME}' not a pointer") if ($needptrs > $e->{POINTERS});
        }
 
+       my $allow_pipe = ($e->{PARENT}->{TYPE} eq "FUNCTION");
+       my $is_pipe = typeIs($e->{TYPE}, "PIPE");
+
+       if ($is_pipe) {
+               if (not $allow_pipe) {
+                       fatal($e, "argument `$e->{NAME}' is a pipe and not allowed on $e->{PARENT}->{TYPE}");
+               }
+
+               if ($e->{POINTERS} > 1) {
+                       fatal($e, "$e->{POINTERS} are not allowed on pipe element $e->{NAME}");
+               }
+
+               if ($e->{POINTERS} < 0) {
+                       fatal($e, "pipe element $e->{NAME} needs pointer");
+               }
+
+               if ($e->{POINTERS} == 1 and pointer_type($e) ne "ref") {
+                       fatal($e, "pointer should be 'ref' on pipe element $e->{NAME}");
+               }
+
+               if (scalar(@size_is) > 0) {
+                       fatal($e, "size_is() on pipe element");
+               }
+
+               if (scalar(@length_is) > 0) {
+                       fatal($e, "length_is() on pipe element");
+               }
+
+               if (scalar(@bracket_array) > 0) {
+                       fatal($e, "brackets on pipe element");
+               }
+
+               if (defined(has_property($e, "subcontext"))) {
+                       fatal($e, "subcontext on pipe element");
+               }
+
+               if (has_property($e, "switch_is")) {
+                       fatal($e, "switch_is on pipe element");
+               }
+
+               if (can_contain_deferred($e->{TYPE})) {
+                       fatal($e, "$e->{TYPE} can_contain_deferred - not allowed on pipe element");
+               }
+       }
+
        # Parse the [][][][] style array stuff
        for my $i (0 .. $#bracket_array) {
                my $d = $bracket_array[$#bracket_array - $i];
        # Parse the [][][][] style array stuff
        for my $i (0 .. $#bracket_array) {
                my $d = $bracket_array[$#bracket_array - $i];
@@ -259,6 +304,19 @@ sub GetElementLevelTable($$$)
                } 
        }
 
                } 
        }
 
+       if ($is_pipe) {
+               push (@$order, {
+                       TYPE => "PIPE",
+                       IS_DEFERRED => 0,
+                       CONTAINS_DEFERRED => 0,
+               });
+
+               my $i = 0;
+               foreach (@$order) { $_->{LEVEL_INDEX} = $i; $i+=1; }
+
+               return $order;
+       }
+
        if (defined(has_property($e, "subcontext"))) {
                my $hdr_size = has_property($e, "subcontext");
                my $subsize = has_property($e, "subcontext_size");
        if (defined(has_property($e, "subcontext"))) {
                my $hdr_size = has_property($e, "subcontext");
                my $subsize = has_property($e, "subcontext_size");
@@ -429,6 +487,8 @@ sub align_type($)
                # Struct/union without body: assume 4
                return 4 unless (defined($dt->{ELEMENTS}));
                return find_largest_alignment($dt);
                # Struct/union without body: assume 4
                return 4 unless (defined($dt->{ELEMENTS}));
                return find_largest_alignment($dt);
+       } elsif (($dt->{TYPE} eq "PIPE")) {
+               return 5;
        }
 
        die("Unknown data type type $dt->{TYPE}");
        }
 
        die("Unknown data type type $dt->{TYPE}");
@@ -600,6 +660,57 @@ sub ParseBitmap($$$)
        };
 }
 
        };
 }
 
+sub ParsePipe($$$)
+{
+       my ($pipe, $pointer_default, $ms_union) = @_;
+
+       my $pname = $pipe->{NAME};
+       $pname = $pipe->{PARENT}->{NAME} unless defined $pname;
+
+       if (not defined($pipe->{PROPERTIES})
+           and defined($pipe->{PARENT}->{PROPERTIES})) {
+               $pipe->{PROPERTIES} = $pipe->{PARENT}->{PROPERTIES};
+       }
+
+       if (ref($pipe->{DATA}) eq "HASH") {
+               if (not defined($pipe->{DATA}->{PROPERTIES})
+                   and defined($pipe->{PROPERTIES})) {
+                       $pipe->{DATA}->{PROPERTIES} = $pipe->{PROPERTIES};
+               }
+       }
+
+       my $struct = ParseStruct($pipe->{DATA}, $pointer_default, $ms_union);
+       $struct->{ALIGN} = 5;
+       $struct->{NAME} = "$pname\_chunk";
+
+       # 'count' is element [0] and 'array' [1]
+       my $e = $struct->{ELEMENTS}[1];
+       # level [0] is of type "ARRAY"
+       my $l = $e->{LEVELS}[1];
+
+       # here we check that pipe elements have a fixed size type
+       while (defined($l)) {
+               my $cl = $l;
+               $l = GetNextLevel($e, $cl);
+               if ($cl->{TYPE} ne "DATA") {
+                       fatal($pipe, el_name($pipe) . ": pipe contains non DATA level");
+               }
+
+               # for now we only support scalars
+               next if is_fixed_size_scalar($cl->{DATA_TYPE});
+
+               fatal($pipe, el_name($pipe) . ": pipe contains non fixed size type[$cl->{DATA_TYPE}]");
+       }
+
+       return {
+               TYPE => "PIPE",
+               NAME => $pipe->{NAME},
+               DATA => $struct,
+               PROPERTIES => $pipe->{PROPERTIES},
+               ORIGINAL => $pipe,
+       };
+}
+
 sub ParseType($$$)
 {
        my ($d, $pointer_default, $ms_union) = @_;
 sub ParseType($$$)
 {
        my ($d, $pointer_default, $ms_union) = @_;
@@ -610,6 +721,7 @@ sub ParseType($$$)
                ENUM => \&ParseEnum,
                BITMAP => \&ParseBitmap,
                TYPEDEF => \&ParseTypedef,
                ENUM => \&ParseEnum,
                BITMAP => \&ParseBitmap,
                TYPEDEF => \&ParseTypedef,
+               PIPE => \&ParsePipe,
        }->{$d->{TYPE}}->($d, $pointer_default, $ms_union);
 
        return $data;
        }->{$d->{TYPE}}->($d, $pointer_default, $ms_union);
 
        return $data;
@@ -942,14 +1054,14 @@ my %property_list = (
 
        "gensize"               => ["TYPEDEF", "STRUCT", "UNION"],
        "value"                 => ["ELEMENT"],
 
        "gensize"               => ["TYPEDEF", "STRUCT", "UNION"],
        "value"                 => ["ELEMENT"],
-       "flag"                  => ["ELEMENT", "TYPEDEF", "STRUCT", "UNION", "ENUM", "BITMAP"],
+       "flag"                  => ["ELEMENT", "TYPEDEF", "STRUCT", "UNION", "ENUM", "BITMAP", "PIPE"],
 
        # generic
 
        # generic
-       "public"                => ["FUNCTION", "TYPEDEF", "STRUCT", "UNION", "ENUM", "BITMAP"],
-       "nopush"                => ["FUNCTION", "TYPEDEF", "STRUCT", "UNION", "ENUM", "BITMAP"],
-       "nopull"                => ["FUNCTION", "TYPEDEF", "STRUCT", "UNION", "ENUM", "BITMAP"],
+       "public"                => ["FUNCTION", "TYPEDEF", "STRUCT", "UNION", "ENUM", "BITMAP", "PIPE"],
+       "nopush"                => ["FUNCTION", "TYPEDEF", "STRUCT", "UNION", "ENUM", "BITMAP", "PIPE"],
+       "nopull"                => ["FUNCTION", "TYPEDEF", "STRUCT", "UNION", "ENUM", "BITMAP", "PIPE"],
        "nosize"                => ["FUNCTION", "TYPEDEF", "STRUCT", "UNION", "ENUM", "BITMAP"],
        "nosize"                => ["FUNCTION", "TYPEDEF", "STRUCT", "UNION", "ENUM", "BITMAP"],
-       "noprint"               => ["FUNCTION", "TYPEDEF", "STRUCT", "UNION", "ENUM", "BITMAP", "ELEMENT"],
+       "noprint"               => ["FUNCTION", "TYPEDEF", "STRUCT", "UNION", "ENUM", "BITMAP", "ELEMENT", "PIPE"],
        "nopython"              => ["FUNCTION", "TYPEDEF", "STRUCT", "UNION", "ENUM", "BITMAP"],
        "todo"                  => ["FUNCTION"],
 
        "nopython"              => ["FUNCTION", "TYPEDEF", "STRUCT", "UNION", "ENUM", "BITMAP"],
        "todo"                  => ["FUNCTION"],
 
@@ -1178,11 +1290,16 @@ sub ValidUnion($)
 sub ValidPipe($)
 {
        my ($pipe) = @_;
 sub ValidPipe($)
 {
        my ($pipe) = @_;
-       my $data = $pipe->{DATA};
+       my $struct = $pipe->{DATA};
 
        ValidProperties($pipe, "PIPE");
 
 
        ValidProperties($pipe, "PIPE");
 
-       fatal($pipe, $pipe->{NAME} . ": 'pipe' is not yet supported by pidl");
+       $struct->{PARENT} = $pipe;
+
+       $struct->{FILE} = $pipe->{FILE} unless defined($struct->{FILE});
+       $struct->{LINE} = $pipe->{LINE} unless defined($struct->{LINE});
+
+       ValidType($struct);
 }
 
 #####################################################################
 }
 
 #####################################################################
index 9788b2c12396d8e25fa3fbf4ec7166e6efb9c039..37363151207f6d380817055b4569cdcc8e695003 100644 (file)
@@ -215,6 +215,30 @@ sub HeaderUnion($$;$)
        pidl $tail if defined($tail);
 }
 
        pidl $tail if defined($tail);
 }
 
+#####################################################################
+# parse a pipe
+sub HeaderPipe($$;$)
+{
+       my($pipe,$name,$tail) = @_;
+
+       my $struct = $pipe->{DATA};
+       my $e = $struct->{ELEMENTS}[1];
+
+       pidl "struct $name;\n";
+       pidl "struct $struct->{NAME} {\n";
+       $tab_depth++;
+       pidl tabs()."uint32_t count;\n";
+       pidl tabs().mapTypeName($e->{TYPE})." *array;\n";
+       $tab_depth--;
+       pidl "}";
+
+       if (defined $struct->{PROPERTIES}) {
+               HeaderProperties($struct->{PROPERTIES}, []);
+       }
+
+       pidl $tail if defined($tail);
+}
+
 #####################################################################
 # parse a type
 sub HeaderType($$$;$)
 #####################################################################
 # parse a type
 sub HeaderType($$$;$)
@@ -225,6 +249,7 @@ sub HeaderType($$$;$)
                ($data->{TYPE} eq "BITMAP") && HeaderBitmap($data, $name);
                ($data->{TYPE} eq "STRUCT") && HeaderStruct($data, $name, $tail);
                ($data->{TYPE} eq "UNION") && HeaderUnion($data, $name, $tail);
                ($data->{TYPE} eq "BITMAP") && HeaderBitmap($data, $name);
                ($data->{TYPE} eq "STRUCT") && HeaderStruct($data, $name, $tail);
                ($data->{TYPE} eq "UNION") && HeaderUnion($data, $name, $tail);
+               ($data->{TYPE} eq "PIPE") && HeaderPipe($data, $name, $tail);
                return;
        }
 
                return;
        }
 
@@ -385,6 +410,7 @@ sub HeaderInterface($)
                HeaderUnion($t, $t->{NAME}, ";\n\n") if ($t->{TYPE} eq "UNION");
                HeaderEnum($t, $t->{NAME}, ";\n\n") if ($t->{TYPE} eq "ENUM");
                HeaderBitmap($t, $t->{NAME}) if ($t->{TYPE} eq "BITMAP");
                HeaderUnion($t, $t->{NAME}, ";\n\n") if ($t->{TYPE} eq "UNION");
                HeaderEnum($t, $t->{NAME}, ";\n\n") if ($t->{TYPE} eq "ENUM");
                HeaderBitmap($t, $t->{NAME}) if ($t->{TYPE} eq "BITMAP");
+               HeaderPipe($t, $t->{NAME}, "\n\n") if ($t->{TYPE} eq "PIPE");
        }
 
        foreach my $fn (@{$interface->{FUNCTIONS}}) {
        }
 
        foreach my $fn (@{$interface->{FUNCTIONS}}) {
index 8f43702ad57bf70810536e4156fa0080f8122b84..ab4f524b9f9e4a15bd11ae6de88862281528f3ff 100644 (file)
@@ -101,10 +101,11 @@ sub ParseFunction_r_Send($$$$)
        $self->pidl("");
 
        my $out_params = 0;
        $self->pidl("");
 
        my $out_params = 0;
-       foreach (@{$fn->{ELEMENTS}}) {
-               if (grep(/out/, @{$_->{DIRECTION}})) {
-                       $out_params++;
-               }
+       foreach my $e (@{$fn->{ELEMENTS}}) {
+               next unless grep(/out/, @{$e->{DIRECTION}});
+               next if ContainsPipe($e, $e->{LEVELS}[0]);
+               $out_params++;
+
        }
 
        my $submem;
        }
 
        my $submem;
@@ -490,6 +491,9 @@ sub ParseFunction_Send($$$$)
                next unless grep(/out/, @{$e->{DIRECTION}});
 
                $self->ParseCopyArgument($fn, $e, "state->orig.out.", "_");
                next unless grep(/out/, @{$e->{DIRECTION}});
 
                $self->ParseCopyArgument($fn, $e, "state->orig.out.", "_");
+
+               next if ContainsPipe($e, $e->{LEVELS}[0]);
+
                $out_params++;
        }
        $self->pidl("");
                $out_params++;
        }
        $self->pidl("");
@@ -569,6 +573,7 @@ sub ParseFunction_Done($$$$)
 
        $self->pidl("/* Copy out parameters */");
        foreach my $e (@{$fn->{ELEMENTS}}) {
 
        $self->pidl("/* Copy out parameters */");
        foreach my $e (@{$fn->{ELEMENTS}}) {
+               next if ContainsPipe($e, $e->{LEVELS}[0]);
                next unless (grep(/out/, @{$e->{DIRECTION}}));
 
                $self->ParseOutputArgument($fn, $e,
                next unless (grep(/out/, @{$e->{DIRECTION}}));
 
                $self->ParseOutputArgument($fn, $e,
@@ -698,6 +703,7 @@ sub ParseFunction_Sync($$$$)
 
        $self->pidl("/* Return variables */");
        foreach my $e (@{$fn->{ELEMENTS}}) {
 
        $self->pidl("/* Return variables */");
        foreach my $e (@{$fn->{ELEMENTS}}) {
+               next if ContainsPipe($e, $e->{LEVELS}[0]);
                next unless (grep(/out/, @{$e->{DIRECTION}}));
 
                $self->ParseOutputArgument($fn, $e, "r.", "_", "sync");
                next unless (grep(/out/, @{$e->{DIRECTION}}));
 
                $self->ParseOutputArgument($fn, $e, "r.", "_", "sync");
index 075ad8516eb2b93951f7381db76dfda0cddd1f90..f84610d6c81d796287cdc3a11d1cf2dc67b41918 100644 (file)
@@ -15,7 +15,7 @@ use strict;
 use Parse::Pidl::Typelist qw(hasType getType mapTypeName typeHasBody);
 use Parse::Pidl::Util qw(has_property ParseExpr ParseExprExt print_uuid unmake_str);
 use Parse::Pidl::CUtil qw(get_pointer_to get_value_of get_array_element);
 use Parse::Pidl::Typelist qw(hasType getType mapTypeName typeHasBody);
 use Parse::Pidl::Util qw(has_property ParseExpr ParseExprExt print_uuid unmake_str);
 use Parse::Pidl::CUtil qw(get_pointer_to get_value_of get_array_element);
-use Parse::Pidl::NDR qw(GetPrevLevel GetNextLevel ContainsDeferred is_charset_array);
+use Parse::Pidl::NDR qw(GetPrevLevel GetNextLevel ContainsDeferred ContainsPipe is_charset_array);
 use Parse::Pidl::Samba4 qw(is_intree choose_header ArrayDynamicallyAllocated);
 use Parse::Pidl::Samba4::Header qw(GenerateFunctionInEnv GenerateFunctionOutEnv EnvSubstituteValue GenerateStructEnv);
 use Parse::Pidl qw(warning);
 use Parse::Pidl::Samba4 qw(is_intree choose_header ArrayDynamicallyAllocated);
 use Parse::Pidl::Samba4::Header qw(GenerateFunctionInEnv GenerateFunctionOutEnv EnvSubstituteValue GenerateStructEnv);
 use Parse::Pidl qw(warning);
@@ -630,6 +630,8 @@ sub ParseElementPush($$$$$$)
 
        my $var_name = $env->{$e->{NAME}};
 
 
        my $var_name = $env->{$e->{NAME}};
 
+       return if ContainsPipe($e, $e->{LEVELS}[0]);
+
        return unless $primitives or ($deferred and ContainsDeferred($e, $e->{LEVELS}[0]));
 
        # Representation type is different from transmit_as
        return unless $primitives or ($deferred and ContainsDeferred($e, $e->{LEVELS}[0]));
 
        # Representation type is different from transmit_as
@@ -945,6 +947,7 @@ sub ParseMemCtxPullFlags($$$$)
 
        if (($l->{TYPE} eq "POINTER") and ($l->{POINTER_TYPE} eq "ref")) {
                my $nl = GetNextLevel($e, $l);
 
        if (($l->{TYPE} eq "POINTER") and ($l->{POINTER_TYPE} eq "ref")) {
                my $nl = GetNextLevel($e, $l);
+               return undef if ($nl->{TYPE} eq "PIPE");
                return undef if ($nl->{TYPE} eq "ARRAY");
                return undef if (($nl->{TYPE} eq "DATA") and ($nl->{DATA_TYPE} eq "string"));
 
                return undef if ($nl->{TYPE} eq "ARRAY");
                return undef if (($nl->{TYPE} eq "DATA") and ($nl->{DATA_TYPE} eq "string"));
 
@@ -1149,6 +1152,8 @@ sub ParseElementPull($$$$$$)
        my $represent_name;
        my $transmit_name;
 
        my $represent_name;
        my $transmit_name;
 
+       return if ContainsPipe($e, $e->{LEVELS}[0]);
+
        return unless $primitives or ($deferred and ContainsDeferred($e, $e->{LEVELS}[0]));
 
        if ($e->{REPRESENTATION_TYPE} ne $e->{TYPE}) {
        return unless $primitives or ($deferred and ContainsDeferred($e, $e->{LEVELS}[0]));
 
        if ($e->{REPRESENTATION_TYPE} ne $e->{TYPE}) {
@@ -2062,6 +2067,99 @@ $typefamily{TYPEDEF} = {
        SIZE_FN_BODY => \&ParseTypedefNdrSize,
 };
 
        SIZE_FN_BODY => \&ParseTypedefNdrSize,
 };
 
+sub ParsePipePushChunk($$)
+{
+       my ($self, $t) = @_;
+
+       my $pipe = $t;
+       $pipe = $t->{DATA} if ($t->{TYPE} eq "TYPEDEF");
+       my $struct = $pipe->{DATA};
+
+       my $name = "$struct->{NAME}";
+       my $ndr = "ndr";
+       my $varname = "r";
+
+       my $args = $typefamily{$struct->{TYPE}}->{DECL}->($struct, "push", $name, $varname);
+
+       $self->fn_declare("push", $struct, "enum ndr_err_code ndr_push_$name(struct ndr_push *$ndr, int ndr_flags, $args)") or return;
+
+       return if has_property($t, "nopush");
+
+       $self->pidl("{");
+       $self->indent;
+
+       $self->ParseStructPush($struct, $ndr, $varname);
+       $self->pidl("");
+
+       $self->pidl("NDR_CHECK(ndr_push_pipe_chunk_trailer(ndr, ndr_flags, $varname->count));");
+       $self->pidl("");
+
+       $self->pidl("return NDR_ERR_SUCCESS;");
+       $self->deindent;
+       $self->pidl("}");
+       $self->pidl("");
+}
+
+sub ParsePipePullChunk($$)
+{
+       my ($self, $t) = @_;
+
+       my $pipe = $t;
+       $pipe = $t->{DATA} if ($t->{TYPE} eq "TYPEDEF");
+       my $struct = $pipe->{DATA};
+
+       my $name = "$struct->{NAME}";
+       my $ndr = "ndr";
+       my $varname = "r";
+
+       my $args = $typefamily{$struct->{TYPE}}->{DECL}->($struct, "pull", $name, $varname);
+
+       $self->fn_declare("pull", $struct, "enum ndr_err_code ndr_pull_$name(struct ndr_pull *$ndr, int ndr_flags, $args)") or return;
+
+       return if has_property($struct, "nopull");
+
+       $self->pidl("{");
+       $self->indent;
+
+       $self->ParseStructPull($struct, $ndr, $varname);
+       $self->pidl("");
+
+       $self->pidl("NDR_CHECK(ndr_check_pipe_chunk_trailer($ndr, ndr_flags, $varname->count));");
+       $self->pidl("");
+
+       $self->pidl("return NDR_ERR_SUCCESS;");
+       $self->deindent;
+       $self->pidl("}");
+       $self->pidl("");
+}
+
+sub ParsePipePrintChunk($$)
+{
+       my ($self, $t) = @_;
+
+       my $pipe = $t;
+       $pipe = $t->{DATA} if ($t->{TYPE} eq "TYPEDEF");
+       my $struct = $pipe->{DATA};
+
+       my $name = "$struct->{NAME}";
+       my $ndr = "ndr";
+       my $varname = "r";
+
+       my $args = $typefamily{$struct->{TYPE}}->{DECL}->($struct, "print", $name, $varname);
+
+       $self->pidl_hdr("void ndr_print_$name(struct ndr_print *ndr, const char *name, $args);");
+
+       return if (has_property($t, "noprint"));
+
+       $self->pidl("_PUBLIC_ void ndr_print_$name(struct ndr_print *$ndr, const char *name, $args)");
+       $self->pidl("{");
+       $self->indent;
+       $self->ParseTypePrint($struct, $ndr, $varname);
+       $self->deindent;
+       $self->pidl("}");
+       $self->pidl("");
+}
+
 #####################################################################
 # parse a function - print side
 sub ParseFunctionPrint($$)
 #####################################################################
 # parse a function - print side
 sub ParseFunctionPrint($$)
@@ -2264,6 +2362,7 @@ sub ParseFunctionPull($$)
                             $e->{LEVELS}[0]->{POINTER_TYPE} eq "ref");
                next if (($e->{LEVELS}[1]->{TYPE} eq "DATA") and 
                                 ($e->{LEVELS}[1]->{DATA_TYPE} eq "string"));
                             $e->{LEVELS}[0]->{POINTER_TYPE} eq "ref");
                next if (($e->{LEVELS}[1]->{TYPE} eq "DATA") and 
                                 ($e->{LEVELS}[1]->{DATA_TYPE} eq "string"));
+               next if ($e->{LEVELS}[1]->{TYPE} eq "PIPE");
                next if (($e->{LEVELS}[1]->{TYPE} eq "ARRAY") 
                        and   $e->{LEVELS}[1]->{IS_ZERO_TERMINATED});
 
                next if (($e->{LEVELS}[1]->{TYPE} eq "ARRAY") 
                        and   $e->{LEVELS}[1]->{IS_ZERO_TERMINATED});
 
@@ -2279,6 +2378,12 @@ sub ParseFunctionPull($$)
                        } else {
                                $self->pidl("memset(r->out.$e->{NAME}, 0, ($size) * sizeof(*r->out.$e->{NAME}));");
                        }
                        } else {
                                $self->pidl("memset(r->out.$e->{NAME}, 0, ($size) * sizeof(*r->out.$e->{NAME}));");
                        }
+               } elsif ($e->{LEVELS}[1]->{TYPE} eq "ARRAY") {
+                       if (grep(/in/, @{$e->{DIRECTION}})) {
+                               $self->pidl("r->out.$e->{NAME} = r->in.$e->{NAME};");
+                       } else {
+                               $self->pidl("r->out.$e->{NAME} = NULL;");
+                       }
                } else {
                        $self->pidl("NDR_PULL_ALLOC($ndr, r->out.$e->{NAME});");
                
                } else {
                        $self->pidl("NDR_PULL_ALLOC($ndr, r->out.$e->{NAME});");
                
@@ -2337,16 +2442,102 @@ sub AuthServiceStruct($$$)
        $self->pidl("");
 }
 
        $self->pidl("");
 }
 
+sub ParseGeneratePipeArray($$$)
+{
+       my ($self, $fn, $direction) = @_;
+
+       $self->pidl("static const struct ndr_interface_call_pipe $fn->{NAME}\_$direction\_pipes[] = {");
+       $self->indent;
+
+       foreach my $e (@{$fn->{ELEMENTS}}) {
+               next unless ContainsPipe($e, $e->{LEVELS}[0]);
+               next unless (grep(/$direction/, @{$e->{DIRECTION}}));
+
+               my $cname = "$e->{TYPE}_chunk";
+
+               $self->pidl("{");
+               $self->indent;
+               $self->pidl("\"$direction.$e->{NAME}\",");
+               $self->pidl("\"$cname\",");
+               $self->pidl("sizeof(struct $cname),");
+               $self->pidl("(ndr_push_flags_fn_t) ndr_push_$cname,");
+               $self->pidl("(ndr_pull_flags_fn_t) ndr_pull_$cname,");
+               $self->pidl("(ndr_print_fn_t) ndr_print_$cname,");
+               $self->deindent;
+               $self->pidl("},");
+       }
+       $self->pidl("{ NULL, NULL, 0, NULL, NULL, NULL, NULL }");
+       $self->deindent;
+       $self->pidl("};");
+       $self->pidl("");
+}
+
+sub FunctionCallPipes($$)
+{
+       my ($self, $d) = @_;
+       return if not defined($d->{OPNUM});
+
+       my $in_pipes = 0;
+       my $out_pipes = 0;
+
+       foreach my $e (@{$d->{ELEMENTS}}) {
+               next unless ContainsPipe($e, $e->{LEVELS}[0]);
+
+               if (grep(/in/, @{$e->{DIRECTION}})) {
+                       $in_pipes++;
+               }
+               if (grep(/out/, @{$e->{DIRECTION}})) {
+                       $out_pipes++;
+               }
+       }
+
+       if ($in_pipes) {
+               $self->ParseGeneratePipeArray($d, "in");
+       }
+
+       if ($out_pipes) {
+               $self->ParseGeneratePipeArray($d, "out");
+       }
+}
+
 sub FunctionCallEntry($$)
 {
        my ($self, $d) = @_;
        return 0 if not defined($d->{OPNUM});
 sub FunctionCallEntry($$)
 {
        my ($self, $d) = @_;
        return 0 if not defined($d->{OPNUM});
+
+       my $in_pipes = 0;
+       my $out_pipes = 0;
+
+       foreach my $e (@{$d->{ELEMENTS}}) {
+               next unless ContainsPipe($e, $e->{LEVELS}[0]);
+
+               if (grep(/in/, @{$e->{DIRECTION}})) {
+                       $in_pipes++;
+               }
+               if (grep(/out/, @{$e->{DIRECTION}})) {
+                       $out_pipes++;
+               }
+       }
+
+       my $in_pipes_ptr = "NULL";
+       my $out_pipes_ptr = "NULL";
+
+       if ($in_pipes) {
+               $in_pipes_ptr = "\&$d->{NAME}_in_pipes";
+       }
+
+       if ($out_pipes) {
+               $out_pipes_ptr = "\&$d->{NAME}_out_pipes";
+       }
+
        $self->pidl("\t{");
        $self->pidl("\t\t\"$d->{NAME}\",");
        $self->pidl("\t\tsizeof(struct $d->{NAME}),");
        $self->pidl("\t\t(ndr_push_flags_fn_t) ndr_push_$d->{NAME},");
        $self->pidl("\t\t(ndr_pull_flags_fn_t) ndr_pull_$d->{NAME},");
        $self->pidl("\t\t(ndr_print_function_t) ndr_print_$d->{NAME},");
        $self->pidl("\t{");
        $self->pidl("\t\t\"$d->{NAME}\",");
        $self->pidl("\t\tsizeof(struct $d->{NAME}),");
        $self->pidl("\t\t(ndr_push_flags_fn_t) ndr_push_$d->{NAME},");
        $self->pidl("\t\t(ndr_pull_flags_fn_t) ndr_pull_$d->{NAME},");
        $self->pidl("\t\t(ndr_print_function_t) ndr_print_$d->{NAME},");
+       $self->pidl("\t\t{ $in_pipes, $in_pipes_ptr },");
+       $self->pidl("\t\t{ $out_pipes, $out_pipes_ptr },");
        $self->pidl("\t},");
        return 1;
 }
        $self->pidl("\t},");
        return 1;
 }
@@ -2362,6 +2553,10 @@ sub FunctionTable($$)
        return if ($#{$interface->{FUNCTIONS}}+1 == 0);
        return unless defined ($interface->{PROPERTIES}->{uuid});
 
        return if ($#{$interface->{FUNCTIONS}}+1 == 0);
        return unless defined ($interface->{PROPERTIES}->{uuid});
 
+       foreach my $d (@{$interface->{INHERITED_FUNCTIONS}},@{$interface->{FUNCTIONS}}) {
+               $self->FunctionCallPipes($d);
+       }
+
        $self->pidl("static const struct ndr_interface_call $interface->{NAME}\_calls[] = {");
 
        foreach my $d (@{$interface->{INHERITED_FUNCTIONS}},@{$interface->{FUNCTIONS}}) {
        $self->pidl("static const struct ndr_interface_call $interface->{NAME}\_calls[] = {");
 
        foreach my $d (@{$interface->{INHERITED_FUNCTIONS}},@{$interface->{FUNCTIONS}}) {
@@ -2615,6 +2810,20 @@ sub ParseInterface($$$)
 
        # Typedefs
        foreach my $d (@{$interface->{TYPES}}) {
 
        # Typedefs
        foreach my $d (@{$interface->{TYPES}}) {
+               if (Parse::Pidl::Typelist::typeIs($d, "PIPE")) {
+                       ($needed->{TypeFunctionName("ndr_push", $d)}) &&
+                               $self->ParsePipePushChunk($d);
+                       ($needed->{TypeFunctionName("ndr_pull", $d)}) &&
+                               $self->ParsePipePullChunk($d);
+                       ($needed->{TypeFunctionName("ndr_print", $d)}) &&
+                               $self->ParsePipePrintChunk($d);
+
+                       $needed->{TypeFunctionName("ndr_pull", $d)} = 0;
+                       $needed->{TypeFunctionName("ndr_push", $d)} = 0;
+                       $needed->{TypeFunctionName("ndr_print", $d)} = 0;
+                       next;
+               }
+
                next unless(typeHasBody($d));
 
                ($needed->{TypeFunctionName("ndr_push", $d)}) && $self->ParseTypePushFunction($d, "r");
                next unless(typeHasBody($d));
 
                ($needed->{TypeFunctionName("ndr_push", $d)}) && $self->ParseTypePushFunction($d, "r");
@@ -2756,6 +2965,7 @@ sub NeededType($$$)
        my ($t,$needed,$req) = @_;
 
        NeededType($t->{DATA}, $needed, $req) if ($t->{TYPE} eq "TYPEDEF");
        my ($t,$needed,$req) = @_;
 
        NeededType($t->{DATA}, $needed, $req) if ($t->{TYPE} eq "TYPEDEF");
+       NeededType($t->{DATA}, $needed, $req) if ($t->{TYPE} eq "PIPE");
 
        if ($t->{TYPE} eq "STRUCT" or $t->{TYPE} eq "UNION") {
                return unless defined($t->{ELEMENTS});
 
        if ($t->{TYPE} eq "STRUCT" or $t->{TYPE} eq "UNION") {
                return unless defined($t->{ELEMENTS});
@@ -2777,6 +2987,7 @@ sub NeededInterface($$)
        my ($interface,$needed) = @_;
        NeededFunction($_, $needed) foreach (@{$interface->{FUNCTIONS}});
        foreach (reverse @{$interface->{TYPES}}) {
        my ($interface,$needed) = @_;
        NeededFunction($_, $needed) foreach (@{$interface->{FUNCTIONS}});
        foreach (reverse @{$interface->{TYPES}}) {
+
                if (has_property($_, "public")) {
                        $needed->{TypeFunctionName("ndr_pull", $_)} = $needed->{TypeFunctionName("ndr_push", $_)} = 
                                $needed->{TypeFunctionName("ndr_print", $_)} = 1;
                if (has_property($_, "public")) {
                        $needed->{TypeFunctionName("ndr_pull", $_)} = $needed->{TypeFunctionName("ndr_push", $_)} = 
                                $needed->{TypeFunctionName("ndr_print", $_)} = 1;
index bf78717b12bd96fad9e39bfbc3eb5de6f65069c2..4f26a92ed2986fcb6f50b725726cac4cfdb2327c 100644 (file)
@@ -291,6 +291,7 @@ sub mapType($$)
        return "struct $n" if ($t->{TYPE} eq "STRUCT" or $t->{TYPE} eq "INTERFACE");
        return "union $n" if ($t->{TYPE} eq "UNION");
        return mapScalarType(bitmap_type_fn($t)) if ($t->{TYPE} eq "BITMAP");
        return "struct $n" if ($t->{TYPE} eq "STRUCT" or $t->{TYPE} eq "INTERFACE");
        return "union $n" if ($t->{TYPE} eq "UNION");
        return mapScalarType(bitmap_type_fn($t)) if ($t->{TYPE} eq "BITMAP");
+       return "struct $n" if ($t->{TYPE} eq "PIPE");
        die("Unknown type $t->{TYPE}");
 }
 
        die("Unknown type $t->{TYPE}");
 }
 
@@ -329,11 +330,12 @@ sub LoadIdl($;$)
                        }) if (has_property($x, "object"));
 
                foreach my $y (@{$x->{DATA}}) {
                        }) if (has_property($x, "object"));
 
                foreach my $y (@{$x->{DATA}}) {
-                       if ($y->{TYPE} eq "TYPEDEF" 
-                               or $y->{TYPE} eq "UNION"
-                               or $y->{TYPE} eq "STRUCT"
-                       or $y->{TYPE} eq "ENUM"
-                       or $y->{TYPE} eq "BITMAP") {
+                       if ($y->{TYPE} eq "TYPEDEF"
+                           or $y->{TYPE} eq "UNION"
+                           or $y->{TYPE} eq "STRUCT"
+                           or $y->{TYPE} eq "ENUM"
+                           or $y->{TYPE} eq "BITMAP"
+                           or $y->{TYPE} eq "PIPE") {
                                $y->{BASEFILE} = $basename;
                                addType($y);
                        }
                                $y->{BASEFILE} = $basename;
                                addType($y);
                        }