pidl/Samba4::NDR::Parser: pass down the correct $var_name to AllocateArrayLevel()
[ira/wip.git] / source / pidl / lib / Parse / Pidl / Samba4 / NDR / Parser.pm
index 166a3a6b59f4e5dfb0ae53169137ef3b3925ef86..9350a1087d1a3f7a91b662f7671935af55b410f1 100644 (file)
@@ -9,13 +9,15 @@ package Parse::Pidl::Samba4::NDR::Parser;
 
 require Exporter;
 @ISA = qw(Exporter);
-@EXPORT_OK = qw(check_null_pointer GenerateFunctionInEnv GenerateFunctionOutEnv EnvSubstituteValue GenerateStructEnv NeededFunction NeededElement NeededType $res NeededInterface TypeFunctionName ParseElementPrint);
+@EXPORT_OK = qw(check_null_pointer NeededFunction NeededElement NeededType $res NeededInterface TypeFunctionName ParseElementPrint);
 
 use strict;
-use Parse::Pidl::Typelist qw(hasType getType mapTypeName);
+use Parse::Pidl::Typelist qw(hasType getType mapTypeName typeHasBody);
 use Parse::Pidl::Util qw(has_property ParseExpr ParseExprExt print_uuid);
-use Parse::Pidl::NDR qw(GetPrevLevel GetNextLevel ContainsDeferred);
+use Parse::Pidl::CUtil qw(get_pointer_to get_value_of);
+use Parse::Pidl::NDR qw(GetPrevLevel GetNextLevel ContainsDeferred is_charset_array);
 use Parse::Pidl::Samba4 qw(is_intree choose_header);
+use Parse::Pidl::Samba4::Header qw(GenerateFunctionInEnv GenerateFunctionOutEnv EnvSubstituteValue GenerateStructEnv);
 use Parse::Pidl qw(warning);
 
 use vars qw($VERSION);
@@ -76,42 +78,6 @@ sub has_fast_array($$)
        return ($t->{NAME} eq "uint8") or ($t->{NAME} eq "string");
 }
 
-sub is_charset_array($$)
-{
-       my ($e,$l) = @_;
-
-       return 0 if ($l->{TYPE} ne "ARRAY");
-
-       my $nl = GetNextLevel($e,$l);
-
-       return 0 unless ($nl->{TYPE} eq "DATA");
-
-       return has_property($e, "charset");
-}
-
-sub get_pointer_to($)
-{
-       my $var_name = shift;
-       
-       if ($var_name =~ /^\*(.*)$/) {
-               return $1;
-       } elsif ($var_name =~ /^\&(.*)$/) {
-               return "&($var_name)";
-       } else {
-               return "&$var_name";
-       }
-}
-
-sub get_value_of($)
-{
-       my $var_name = shift;
-
-       if ($var_name =~ /^\&(.*)$/) {
-               return $1;
-       } else {
-               return "*$var_name";
-       }
-}
 
 ####################################
 # pidl() is our basic output routine
@@ -215,68 +181,6 @@ sub end_flags($$)
        }
 }
 
-sub GenerateStructEnv($$)
-{
-       my ($x, $v) = @_;
-       my %env;
-
-       foreach my $e (@{$x->{ELEMENTS}}) {
-               $env{$e->{NAME}} = "$v->$e->{NAME}";
-       }
-
-       $env{"this"} = $v;
-
-       return \%env;
-}
-
-sub EnvSubstituteValue($$)
-{
-       my ($env,$s) = @_;
-
-       # Substitute the value() values in the env
-       foreach my $e (@{$s->{ELEMENTS}}) {
-               next unless (defined(my $v = has_property($e, "value")));
-               
-               $env->{$e->{NAME}} = ParseExpr($v, $env, $e);
-       }
-
-       return $env;
-}
-
-sub GenerateFunctionInEnv($;$)
-{
-       my ($fn, $base) = @_;
-       my %env;
-
-       $base = "r->" unless defined($base);
-
-       foreach my $e (@{$fn->{ELEMENTS}}) {
-               if (grep (/in/, @{$e->{DIRECTION}})) {
-                       $env{$e->{NAME}} = $base."in.$e->{NAME}";
-               }
-       }
-
-       return \%env;
-}
-
-sub GenerateFunctionOutEnv($;$)
-{
-       my ($fn, $base) = @_;
-       my %env;
-
-       $base = "r->" unless defined($base);
-
-       foreach my $e (@{$fn->{ELEMENTS}}) {
-               if (grep (/out/, @{$e->{DIRECTION}})) {
-                       $env{$e->{NAME}} = $base."out.$e->{NAME}";
-               } elsif (grep (/in/, @{$e->{DIRECTION}})) {
-                       $env{$e->{NAME}} = $base."in.$e->{NAME}";
-               }
-       }
-
-       return \%env;
-}
-
 #####################################################################
 # parse the data of an array - push side
 sub ParseArrayPushHeader($$$$$$)
@@ -423,8 +327,10 @@ sub ParseArrayPullHeader($$$$$$)
        } elsif ($l->{IS_ZERO_TERMINATED}) { # Noheader arrays
                $length = $size = "ndr_get_string_size($ndr, sizeof(*$var_name))";
        } else {
-               $length = $size = ParseExprExt($l->{SIZE_IS}, $env, $e->{ORIGINAL}, 
-                   check_null_pointer($e, $env, sub { $self->pidl(shift); }, "return NT_STATUS_INVALID_PARAMETER_MIX;"), check_fully_dereferenced($e, $env));
+               $length = $size = ParseExprExt($l->{SIZE_IS}, $env, $e->{ORIGINAL},
+                       check_null_pointer($e, $env, sub { $self->pidl(shift); },
+                                          "return ndr_pull_error(ndr, NDR_ERR_INVALID_POINTER, \"NULL Pointer for size_is()\");"),
+                       check_fully_dereferenced($e, $env));
        }
 
        if ((!$l->{IS_SURROUNDING}) and $l->{IS_CONFORMANT}) {
@@ -447,7 +353,10 @@ sub ParseArrayPullHeader($$$$$$)
        if ($l->{IS_CONFORMANT} and not $l->{IS_ZERO_TERMINATED}) {
                $self->defer("if ($var_name) {");
                $self->defer_indent;
-               my $size = ParseExprExt($l->{SIZE_IS}, $env, $e->{ORIGINAL}, check_null_pointer($e, $env, sub { $self->defer(shift); }, "return NT_STATUS_INVALID_PARAMETER_MIX;"), check_fully_dereferenced($e, $env));
+               my $size = ParseExprExt($l->{SIZE_IS}, $env, $e->{ORIGINAL},
+                       check_null_pointer($e, $env, sub { $self->defer(shift); },
+                                          "return ndr_pull_error(ndr, NDR_ERR_INVALID_POINTER, \"NULL Pointer for size_is()\");"),
+                       check_fully_dereferenced($e, $env));
                $self->defer("NDR_CHECK(ndr_check_array_size(ndr, (void*)" . get_pointer_to($var_name) . ", $size));");
                $self->defer_deindent;
                $self->defer("}");
@@ -457,7 +366,8 @@ sub ParseArrayPullHeader($$$$$$)
                $self->defer("if ($var_name) {");
                $self->defer_indent;
                my $length = ParseExprExt($l->{LENGTH_IS}, $env, $e->{ORIGINAL}, 
-                       check_null_pointer($e, $env, sub { $self->defer(shift); }, "return NT_STATUS_INVALID_PARAMETER_MIX;"), 
+                       check_null_pointer($e, $env, sub { $self->defer(shift); },
+                                          "return ndr_pull_error(ndr, NDR_ERR_INVALID_POINTER, \"NULL Pointer for length_is()\");"),
                        check_fully_dereferenced($e, $env));
                $self->defer("NDR_CHECK(ndr_check_array_length(ndr, (void*)" . get_pointer_to($var_name) . ", $length));");
                $self->defer_deindent;
@@ -465,7 +375,7 @@ sub ParseArrayPullHeader($$$$$$)
        }
 
        if (not $l->{IS_FIXED} and not is_charset_array($e, $l)) {
-               $self->AllocateArrayLevel($e,$l,$ndr,$env,$size);
+               $self->AllocateArrayLevel($e,$l,$ndr,$var_name,$size);
        }
 
        return $length;
@@ -740,7 +650,11 @@ sub ParsePtrPush($$$$)
        my ($self,$e,$l,$var_name) = @_;
 
        if ($l->{POINTER_TYPE} eq "ref") {
-               $self->pidl("if ($var_name == NULL) return NT_STATUS_INVALID_PARAMETER_MIX;");
+               $self->pidl("if ($var_name == NULL) {");
+               $self->indent;
+               $self->pidl("return ndr_push_error(ndr, NDR_ERR_INVALID_POINTER, \"NULL [ref] pointer\");");
+               $self->deindent;
+               $self->pidl("}");
                if ($l->{LEVEL} eq "EMBEDDED") {
                        $self->pidl("NDR_CHECK(ndr_push_ref_ptr(ndr));");
                }
@@ -875,7 +789,9 @@ sub ParseSwitchPull($$$$$$)
 {
        my($self,$e,$l,$ndr,$var_name,$env) = @_;
        my $switch_var = ParseExprExt($l->{SWITCH_IS}, $env, $e->{ORIGINAL}, 
-               check_null_pointer($e, $env, sub { $self->pidl(shift); }, "return NT_STATUS_INVALID_PARAMETER_MIX;"), check_fully_dereferenced($e, $env));
+               check_null_pointer($e, $env, sub { $self->pidl(shift); },
+                                  "return ndr_pull_error(ndr, NDR_ERR_INVALID_POINTER, \"NULL Pointer for switch_is()\");"),
+               check_fully_dereferenced($e, $env));
 
        $var_name = get_pointer_to($var_name);
        $self->pidl("NDR_CHECK(ndr_pull_set_switch_value($ndr, $var_name, $switch_var));");
@@ -887,7 +803,9 @@ sub ParseSwitchPush($$$$$$)
 {
        my($self,$e,$l,$ndr,$var_name,$env) = @_;
        my $switch_var = ParseExprExt($l->{SWITCH_IS}, $env, $e->{ORIGINAL}, 
-               check_null_pointer($e, $env, sub { $self->pidl(shift); }, "return NT_STATUS_INVALID_PARAMETER_MIX;"), check_fully_dereferenced($e, $env));
+               check_null_pointer($e, $env, sub { $self->pidl(shift); },
+                                  "return ndr_push_error(ndr, NDR_ERR_INVALID_POINTER, \"NULL Pointer for switch_is()\");"),
+               check_fully_dereferenced($e, $env));
 
        $var_name = get_pointer_to($var_name);
        $self->pidl("NDR_CHECK(ndr_push_set_switch_value($ndr, $var_name, $switch_var));");
@@ -1081,8 +999,8 @@ sub ParseElementPullLevel
                        $self->indent;
 
                        if ($l->{POINTER_TYPE} eq "relative") {
-                               $self->pidl("struct ndr_pull_save _relative_save;");
-                               $self->pidl("ndr_pull_save(ndr, &_relative_save);");
+                               $self->pidl("uint32_t _relative_save_offset;");
+                               $self->pidl("_relative_save_offset = ndr->offset;");
                                $self->pidl("NDR_CHECK(ndr_pull_relative_ptr2(ndr, $var_name));");
                        }
                }
@@ -1096,7 +1014,7 @@ sub ParseElementPullLevel
 
                if ($l->{POINTER_TYPE} ne "ref") {
                        if ($l->{POINTER_TYPE} eq "relative") {
-                               $self->pidl("ndr_pull_restore(ndr, &_relative_save);");
+                               $self->pidl("ndr->offset = _relative_save_offset;");
                        }
                        $self->deindent;
                        $self->pidl("}");
@@ -2089,7 +2007,7 @@ sub ParseFunctionPush($$)
 { 
        my($self, $fn) = @_;
 
-       $self->fn_declare("push", $fn, "NTSTATUS ndr_push_$fn->{NAME}(struct ndr_push *ndr, int flags, const struct $fn->{NAME} *r)") or return;
+       $self->fn_declare("push", $fn, "enum ndr_err_code ndr_push_$fn->{NAME}(struct ndr_push *ndr, int flags, const struct $fn->{NAME} *r)") or return;
 
        return if has_property($fn, "nopush");
 
@@ -2132,7 +2050,7 @@ sub ParseFunctionPush($$)
     
        $self->deindent;
        $self->pidl("}");
-       $self->pidl("return NT_STATUS_OK;");
+       $self->pidl("return NDR_ERR_SUCCESS;");
        $self->deindent;
        $self->pidl("}");
        $self->pidl("");
@@ -2140,9 +2058,7 @@ sub ParseFunctionPush($$)
 
 sub AllocateArrayLevel($$$$$$)
 {
-       my ($self,$e,$l,$ndr,$env,$size) = @_;
-
-       my $var = ParseExpr($e->{NAME}, $env, $e->{ORIGINAL});
+       my ($self,$e,$l,$ndr,$var,$size) = @_;
 
        my $pl = GetPrevLevel($e, $l);
        if (defined($pl) and 
@@ -2169,7 +2085,7 @@ sub ParseFunctionPull($$)
        my($self,$fn) = @_;
 
        # pull function args
-       $self->fn_declare("pull", $fn, "NTSTATUS ndr_pull_$fn->{NAME}(struct ndr_pull *ndr, int flags, struct $fn->{NAME} *r)") or return;
+       $self->fn_declare("pull", $fn, "enum ndr_err_code ndr_pull_$fn->{NAME}(struct ndr_pull *ndr, int flags, struct $fn->{NAME} *r)") or return;
 
        $self->pidl("{");
        $self->indent;
@@ -2222,9 +2138,10 @@ sub ParseFunctionPull($$)
                        and   $e->{LEVELS}[1]->{IS_ZERO_TERMINATED});
 
                if ($e->{LEVELS}[1]->{TYPE} eq "ARRAY") {
-                       my $size = ParseExprExt($e->{LEVELS}[1]->{SIZE_IS}, $env, $e->{ORIGINAL}, check_null_pointer($e, $env, sub { $self->pidl(shift); }, "return NT_STATUS_INVALID_PARAMETER_MIX;"), 
+                       my $size = ParseExprExt($e->{LEVELS}[1]->{SIZE_IS}, $env, $e->{ORIGINAL},
+                               check_null_pointer($e, $env, sub { $self->pidl(shift); },
+                                                  "return ndr_pull_error(ndr, NDR_ERR_INVALID_POINTER, \"NULL Pointer for size_is()\");"),
                                check_fully_dereferenced($e, $env));
-                       
                        $self->pidl("NDR_PULL_ALLOC_N(ndr, r->out.$e->{NAME}, $size);");
 
                        if (grep(/in/, @{$e->{DIRECTION}})) {
@@ -2264,7 +2181,7 @@ sub ParseFunctionPull($$)
        $self->deindent;
        $self->pidl("}");
 
-       $self->pidl("return NT_STATUS_OK;");
+       $self->pidl("return NDR_ERR_SUCCESS;");
        $self->deindent;
        $self->pidl("}");
        $self->pidl("");
@@ -2290,11 +2207,11 @@ sub FunctionTable($$)
                $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".($d->{ASYNC}?"True":"False").",");
+               $self->pidl("\t\t".($d->{ASYNC}?"true":"false").",");
                $self->pidl("\t},");
                $count++;
        }
-       $self->pidl("\t{ NULL, 0, NULL, NULL, NULL, False }");
+       $self->pidl("\t{ NULL, 0, NULL, NULL, NULL, false }");
        $self->pidl("};");
        $self->pidl("");
 
@@ -2377,13 +2294,15 @@ sub HeaderInclude
 # generate prototypes and defines for the interface definitions
 # FIXME: these prototypes are for the DCE/RPC client functions, not the 
 # NDR parser and so do not belong here, technically speaking
-sub HeaderInterface($$)
+sub HeaderInterface($$$)
 {
-       my($self,$interface) = @_;
+       my($self,$interface,$needed) = @_;
 
        my $count = 0;
 
-       $self->pidl_hdr(choose_header("librpc/ndr/libndr.h", "ndr.h"));
+       if ($needed->{"compression"}) {
+               $self->pidl(choose_header("librpc/ndr/ndr_compression.h", "ndr/compression.h"));
+       }
 
        if (has_property($interface, "object")) {
                $self->pidl(choose_header("librpc/gen_ndr/ndr_orpc.h", "ndr/orpc.h"));
@@ -2451,12 +2370,12 @@ sub ParseTypePushFunction($$$)
        my ($self, $e, $varname) = @_;
 
        my $args = $typefamily{$e->{TYPE}}->{DECL}->($e, "push", $e->{NAME}, $varname);
-       $self->fn_declare("push", $e, "NTSTATUS ".TypeFunctionName("ndr_push", $e)."(struct ndr_push *ndr, int ndr_flags, $args)") or return;
+       $self->fn_declare("push", $e, "enum ndr_err_code ".TypeFunctionName("ndr_push", $e)."(struct ndr_push *ndr, int ndr_flags, $args)") or return;
 
        $self->pidl("{");
        $self->indent;
        $self->ParseTypePush($e, $varname, 1, 1);
-       $self->pidl("return NT_STATUS_OK;");
+       $self->pidl("return NDR_ERR_SUCCESS;");
        $self->deindent;
        $self->pidl("}");
        $self->pidl("");;
@@ -2479,12 +2398,12 @@ sub ParseTypePullFunction($$)
 
        my $args = $typefamily{$e->{TYPE}}->{DECL}->($e, "pull", $e->{NAME}, $varname);
 
-       $self->fn_declare("pull", $e, "NTSTATUS ".TypeFunctionName("ndr_pull", $e)."(struct ndr_pull *ndr, int ndr_flags, $args)") or return;
+       $self->fn_declare("pull", $e, "enum ndr_err_code ".TypeFunctionName("ndr_pull", $e)."(struct ndr_pull *ndr, int ndr_flags, $args)") or return;
 
        $self->pidl("{");
        $self->indent;
        $self->ParseTypePull($e, $varname, 1, 1);
-       $self->pidl("return NT_STATUS_OK;");
+       $self->pidl("return NDR_ERR_SUCCESS;");
        $self->deindent;
        $self->pidl("}");
        $self->pidl("");
@@ -2544,14 +2463,12 @@ sub ParseInterface($$$)
 
        $self->pidl_hdr("");
 
-       if ($needed->{"compression"}) {
-               $self->pidl(choose_header("librpc/ndr/ndr_compression.h", "ndr/compression.h"));
-       }
-
-       $self->HeaderInterface($interface);
+       $self->HeaderInterface($interface, $needed);
 
        # Typedefs
        foreach my $d (@{$interface->{TYPES}}) {
+               next unless(typeHasBody($d));
+
                ($needed->{TypeFunctionName("ndr_push", $d)}) && $self->ParseTypePushFunction($d, "r");
                ($needed->{TypeFunctionName("ndr_pull", $d)}) && $self->ParseTypePullFunction($d, "r");
                ($needed->{TypeFunctionName("ndr_print", $d)}) && $self->ParseTypePrintFunction($d, "r");
@@ -2594,12 +2511,6 @@ sub GenerateIncludes($)
                $self->pidl("#include <stdarg.h>");
                $self->pidl("#include <string.h>");
        }
-
-       # Samba3 has everything in include/includes.h
-       if (is_intree() != 3) {
-               $self->pidl(choose_header("libcli/util/nterr.h", "core/nterr.h"));
-               $self->pidl(choose_header("librpc/gen_ndr/ndr_misc.h", "gen_ndr/ndr_misc.h"));
-       }
 }
 
 #####################################################################
@@ -2610,6 +2521,7 @@ sub Parse($$$$)
 
        $self->pidl_hdr("/* header auto-generated by pidl */");
        $self->pidl_hdr("");
+       $self->pidl_hdr(choose_header("librpc/ndr/libndr.h", "ndr.h"));
        $self->pidl_hdr("#include \"$gen_header\"") if ($gen_header);
        $self->pidl_hdr("");
 
@@ -2700,6 +2612,7 @@ sub NeededType($$$)
        NeededType($t->{DATA}, $needed, $req) if ($t->{TYPE} eq "TYPEDEF");
 
        if ($t->{TYPE} eq "STRUCT" or $t->{TYPE} eq "UNION") {
+               return unless defined($t->{ELEMENTS});
                for my $e (@{$t->{ELEMENTS}}) {
                        $e->{PARENT} = $t;
                        if (has_property($e, "compression")) { 
@@ -2737,7 +2650,7 @@ sub TypeFunctionName($$)
        my ($prefix, $t) = @_;
 
        return "$prefix\_$t->{NAME}" if (ref($t) eq "HASH" and 
-                       ($t->{TYPE} eq "TYPEDEF" or $t->{TYPE} eq "DECLARE"));
+                       $t->{TYPE} eq "TYPEDEF");
        return "$prefix\_$t->{TYPE}_$t->{NAME}" if (ref($t) eq "HASH");
        return "$prefix\_$t";
 }