pidl: Use NDR_ZERO_STRUCT(P) macros
[sfrench/samba-autobuild/.git] / pidl / lib / Parse / Pidl / Samba4 / NDR / Parser.pm
index 54b6f132dfc6ef6fe42f93e6e76985e0d88cfe06..432e52f89c4562f7ff32f8dd4fb8a2f12a910469 100644 (file)
@@ -261,7 +261,7 @@ sub check_fully_dereferenced($$)
                                $nump = $_->{POINTER_INDEX}+1;
                        }
                }
-               warning($element->{ORIGINAL}, "Got pointer for `$e->{NAME}', expected fully derefenced variable") if ($nump > length($ptr));
+               warning($element->{ORIGINAL}, "Got pointer for `$e->{NAME}', expected fully dereferenced variable") if ($nump > length($ptr));
                return ($origvar);
        }
 }      
@@ -321,6 +321,25 @@ sub check_null_pointer($$$$)
        }
 }
 
+sub is_deferred_switch_non_empty($)
+{
+       # 1 if there needs to be a deferred branch in an ndr_pull/push,
+       # 0 otherwise.
+       my ($e) = @_;
+       my $have_default = 0;
+       foreach my $el (@{$e->{ELEMENTS}}) {
+               if ($el->{CASE} eq "default") {
+                       $have_default = 1;
+               }
+               if ($el->{TYPE} ne "EMPTY") {
+                       if (ContainsDeferred($el, $el->{LEVELS}[0])) {
+                               return 1;
+                       }
+               }
+       }
+       return ! $have_default;
+}
+
 sub ParseArrayPullGetSize($$$$$$)
 {
        my ($self,$e,$l,$ndr,$var_name,$env) = @_;
@@ -506,11 +525,12 @@ sub ParseCompressionPullStart($$$$$)
        my $comndr = "$ndr\_compressed";
        my $alg = compression_alg($e, $l);
        my $dlen = compression_dlen($e, $l, $env);
+       my $clen = compression_clen($e, $l, $env);
 
        $self->pidl("{");
        $self->indent;
        $self->pidl("struct ndr_pull *$comndr;");
-       $self->pidl("NDR_CHECK(ndr_pull_compression_start($ndr, &$comndr, $alg, $dlen));");
+       $self->pidl("NDR_CHECK(ndr_pull_compression_start($ndr, &$comndr, $alg, $dlen, $clen));");
 
        return $comndr;
 }
@@ -617,7 +637,11 @@ sub ParseElementPushLevel
 
                        # Allow speedups for arrays of scalar types
                        if (is_charset_array($e,$l)) {
-                               $self->pidl("NDR_CHECK(ndr_push_charset($ndr, $ndr_flags, $var_name, $length, sizeof(" . mapTypeName($nl->{DATA_TYPE}) . "), CH_$e->{PROPERTIES}->{charset}));");
+                               if ($l->{IS_TO_NULL}) {
+                                       $self->pidl("NDR_CHECK(ndr_push_charset_to_null($ndr, $ndr_flags, $var_name, $length, sizeof(" . mapTypeName($nl->{DATA_TYPE}) . "), CH_$e->{PROPERTIES}->{charset}));");
+                               } else {
+                                       $self->pidl("NDR_CHECK(ndr_push_charset($ndr, $ndr_flags, $var_name, $length, sizeof(" . mapTypeName($nl->{DATA_TYPE}) . "), CH_$e->{PROPERTIES}->{charset}));");
+                               }
                                return;
                        } elsif (has_fast_array($e,$l)) {
                                $self->pidl("NDR_CHECK(ndr_push_array_$nl->{DATA_TYPE}($ndr, $ndr_flags, $var_name, $length));");
@@ -670,7 +694,7 @@ sub ParseElementPushLevel
                $var_name = get_array_element($var_name, $counter);
 
                if ((($primitives and not $l->{IS_DEFERRED}) or ($deferred and $l->{IS_DEFERRED})) and not $array_pointless) {
-                       $self->pidl("for ($counter = 0; $counter < $length; $counter++) {");
+                       $self->pidl("for ($counter = 0; $counter < ($length); $counter++) {");
                        $self->indent;
                        $self->ParseElementPushLevel($e, GetNextLevel($e, $l), $ndr, $var_name, $env, 1, 0);
                        $self->deindent;
@@ -678,12 +702,12 @@ sub ParseElementPushLevel
                }
 
                if ($deferred and ContainsDeferred($e, $l) and not $array_pointless) {
-                       $self->pidl("for ($counter = 0; $counter < $length; $counter++) {");
+                       $self->pidl("for ($counter = 0; $counter < ($length); $counter++) {");
                        $self->indent;
                        $self->ParseElementPushLevel($e, GetNextLevel($e, $l), $ndr, $var_name, $env, 0, 1);
                        $self->deindent;
                        $self->pidl("}");
-               }       
+               }
        } elsif ($l->{TYPE} eq "SWITCH") {
                $self->ParseElementPushLevel($e, GetNextLevel($e, $l), $ndr, $var_name, $env, $primitives, $deferred);
        }
@@ -698,6 +722,11 @@ sub ParseElementPush($$$$$$)
 
        my $var_name = $env->{$e->{NAME}};
 
+       if (has_property($e, "skip") or has_property($e, "skip_noinit")) {
+               $self->pidl("/* [skip] '$var_name' */");
+               return;
+       }
+
        return if ContainsPipe($e, $e->{LEVELS}[0]);
 
        return unless $primitives or ($deferred and ContainsDeferred($e, $e->{LEVELS}[0]));
@@ -737,13 +766,15 @@ sub ParsePtrPush($$$$$)
        my ($self,$e,$l,$ndr,$var_name) = @_;
 
        if ($l->{POINTER_TYPE} eq "ref") {
-               $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_INDEX} > 0) {
+                       $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));");
+                       $self->pidl("NDR_CHECK(ndr_push_ref_ptr(ndr)); /* $var_name */");
                }
        } elsif ($l->{POINTER_TYPE} eq "relative") {
                $self->pidl("NDR_CHECK(ndr_push_relative_ptr1($ndr, $var_name));");
@@ -818,8 +849,10 @@ sub ParseElementPrint($$$$$)
        my $cur_depth = 0;
        my $ignore_depth = 0xFFFF;
 
+       $self->start_flags($e, $ndr);
        if ($e->{REPRESENTATION_TYPE} ne $e->{TYPE}) {
                $self->pidl("ndr_print_$e->{REPRESENTATION_TYPE}($ndr, \"$e->{NAME}\", $var_name);");
+               $self->end_flags($e, $ndr);
                return;
        }
 
@@ -875,7 +908,7 @@ sub ParseElementPrint($$$$$)
 
                                $self->pidl("$ndr->print($ndr, \"\%s: ARRAY(\%d)\", \"$e->{NAME}\", (int)$length);");
                                $self->pidl("$ndr->depth++;");
-                               $self->pidl("for ($counter=0;$counter<$length;$counter++) {");
+                               $self->pidl("for ($counter = 0; $counter < ($length); $counter++) {");
                                $self->indent;
 
                                $var_name = get_array_element($var_name, $counter);
@@ -914,6 +947,8 @@ sub ParseElementPrint($$$$$)
                        $self->pidl("$ndr->depth--;");
                }
        }
+
+       $self->end_flags($e, $ndr);
 }
 
 #####################################################################
@@ -958,11 +993,7 @@ sub ParseDataPull($$$$$$$)
 
                $var_name = get_pointer_to($var_name);
 
-               if (has_property($e, "skip")) {
-                       $self->pidl("/* [skip] '$var_name' */");
-               } else {
-                       $self->pidl("NDR_CHECK(".TypeFunctionName("ndr_pull", $l->{DATA_TYPE})."($ndr, $ndr_flags, $var_name));");
-               }
+               $self->pidl("NDR_CHECK(".TypeFunctionName("ndr_pull", $l->{DATA_TYPE})."($ndr, $ndr_flags, $var_name));");
 
                my $pl = GetPrevLevel($e, $l);
 
@@ -1000,11 +1031,7 @@ sub ParseDataPush($$$$$$$)
                        $var_name = get_pointer_to($var_name);
                }
 
-               if (has_property($e, "skip")) {
-                       $self->pidl("/* [skip] '$var_name' */");
-               } else {
-                       $self->pidl("NDR_CHECK(".TypeFunctionName("ndr_push", $l->{DATA_TYPE})."($ndr, $ndr_flags, $var_name));");
-               }
+               $self->pidl("NDR_CHECK(".TypeFunctionName("ndr_push", $l->{DATA_TYPE})."($ndr, $ndr_flags, $var_name));");
        } else {
                $self->ParseTypePush($l->{DATA_TYPE}, $ndr, $var_name, $primitives, $deferred);
        }
@@ -1104,6 +1131,14 @@ sub ParseElementPullLevel
        my $ndr_flags = CalcNdrFlags($l, $primitives, $deferred);
        my $array_length = undef;
 
+       if (has_property($e, "skip") or has_property($e, "skip_noinit")) {
+               $self->pidl("/* [skip] '$var_name' */");
+               if (not has_property($e, "skip_noinit")) {
+                       $self->pidl("NDR_ZERO_STRUCT($var_name);");
+               }
+               return;
+       }
+
        if ($l->{TYPE} eq "ARRAY" and ($l->{IS_VARYING} or $l->{IS_CONFORMANT})) {
                $var_name = get_pointer_to($var_name);
        }
@@ -1203,7 +1238,7 @@ sub ParseElementPullLevel
                                $self->CheckStringTerminator($ndr,$e,$l,$length);
                        }
 
-                       $self->pidl("for ($counter = 0; $counter < $length; $counter++) {");
+                       $self->pidl("for ($counter = 0; $counter < ($length); $counter++) {");
                        $self->indent;
                        $self->ParseElementPullLevel($e, $nl, $ndr, $var_name, $env, 1, 0);
                        $self->deindent;
@@ -1211,7 +1246,7 @@ sub ParseElementPullLevel
                }
 
                if ($deferred and ContainsDeferred($e, $l)) {
-                       $self->pidl("for ($counter = 0; $counter < $length; $counter++) {");
+                       $self->pidl("for ($counter = 0; $counter < ($length); $counter++) {");
                        $self->indent;
                        $self->ParseElementPullLevel($e,GetNextLevel($e,$l), $ndr, $var_name, $env, 0, 1);
                        $self->deindent;
@@ -1331,10 +1366,30 @@ sub ParsePtrPull($$$$$)
        $self->pidl("}");
 }
 
+sub CheckRefPtrs($$$$)
+{
+       my ($self,$e,$ndr,$env) = @_;
+
+       return if ContainsPipe($e, $e->{LEVELS}[0]);
+       return if ($e->{LEVELS}[0]->{TYPE} ne "POINTER");
+       return if ($e->{LEVELS}[0]->{POINTER_TYPE} ne "ref");
+
+       my $var_name = $env->{$e->{NAME}};
+       $var_name = append_prefix($e, $var_name);
+
+       $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("}");
+}
+
 sub ParseStructPushPrimitives($$$$$)
 {
        my ($self, $struct, $ndr, $varname, $env) = @_;
 
+       $self->CheckRefPtrs($_, $ndr, $env) foreach (@{$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 push the conformant length early, as it fits on
@@ -1607,6 +1662,11 @@ sub ParseStructPrint($$$$$)
 sub DeclarePtrVariables($$)
 {
        my ($self,$e) = @_;
+
+       if (has_property($e, "skip") or has_property($e, "skip_noinit")) {
+               return;
+       }
+
        foreach my $l (@{$e->{LEVELS}}) {
                my $size = 32;
                if ($l->{TYPE} eq "POINTER" and 
@@ -1624,6 +1684,10 @@ sub DeclareArrayVariables($$;$)
 {
        my ($self,$e,$pull) = @_;
 
+       if (has_property($e, "skip") or has_property($e, "skip_noinit")) {
+               return;
+       }
+
        foreach my $l (@{$e->{LEVELS}}) {
                next if ($l->{TYPE} ne "ARRAY");
                if (defined($pull)) {
@@ -1642,6 +1706,10 @@ sub DeclareArrayVariablesNoZero($$$)
 {
        my ($self,$e,$env) = @_;
 
+       if (has_property($e, "skip") or has_property($e, "skip_noinit")) {
+               return;
+       }
+
        foreach my $l (@{$e->{LEVELS}}) {
                next if ($l->{TYPE} ne "ARRAY");
                next if has_fast_array($e,$l);
@@ -1658,6 +1726,11 @@ sub DeclareArrayVariablesNoZero($$$)
 sub DeclareMemCtxVariables($$)
 {
        my ($self,$e) = @_;
+
+       if (has_property($e, "skip") or has_property($e, "skip_noinit")) {
+               return;
+       }
+
        foreach my $l (@{$e->{LEVELS}}) {
                my $mem_flags = $self->ParseMemCtxPullFlags($e, $l);
 
@@ -1666,7 +1739,7 @@ sub DeclareMemCtxVariables($$)
                }
 
                if (defined($mem_flags)) {
-                       $self->pidl("TALLOC_CTX *_mem_save_$e->{NAME}_$l->{LEVEL_INDEX};");
+                       $self->pidl("TALLOC_CTX *_mem_save_$e->{NAME}_$l->{LEVEL_INDEX} = NULL;");
                }
        }
 }
@@ -1834,7 +1907,9 @@ sub ParseUnionPushPrimitives($$$$)
                                $self->pidl("NDR_CHECK(ndr_push_setup_relative_base_offset1($ndr, $varname, $ndr->offset));");
                        }
                        $self->DeclareArrayVariables($el);
-                       $self->ParseElementPush($el, $ndr, {$el->{NAME} => "$varname->$el->{NAME}"}, 1, 0);
+                       my $el_env = {$el->{NAME} => "$varname->$el->{NAME}"};
+                       $self->CheckRefPtrs($el, $ndr, $el_env);
+                       $self->ParseElementPush($el, $ndr, $el_env, 1, 0);
                        $self->deindent;
                }
                $self->pidl("break; }");
@@ -1899,11 +1974,13 @@ sub ParseUnionPush($$$$)
        $self->ParseUnionPushPrimitives($e, $ndr, $varname);
        $self->deindent;
        $self->pidl("}");
-       $self->pidl("if (ndr_flags & NDR_BUFFERS) {");
-       $self->indent;
-       $self->ParseUnionPushDeferred($e, $ndr, $varname);
-       $self->deindent;
-       $self->pidl("}");
+        if (is_deferred_switch_non_empty($e)) {
+                $self->pidl("if (ndr_flags & NDR_BUFFERS) {");
+                $self->indent;
+                $self->ParseUnionPushDeferred($e, $ndr, $varname);
+                $self->deindent;
+                $self->pidl("}");
+        }
        $self->end_flags($e, $ndr);
 }
 
@@ -2048,7 +2125,7 @@ sub ParseUnionPull($$$$)
 {
        my ($self,$e,$ndr,$varname) = @_;
        my $switch_type = $e->{SWITCH_TYPE};
-
+        my $needs_deferred_switch = is_deferred_switch_non_empty($e);
        $self->pidl("uint32_t level;");
        if (defined($switch_type)) {
                if (Parse::Pidl::Typelist::typeIs($switch_type, "ENUM")) {
@@ -2069,21 +2146,27 @@ sub ParseUnionPull($$$$)
 
        $self->start_flags($e, $ndr);
 
-       $self->pidl("level = ndr_pull_get_switch_value($ndr, $varname);");
-
        $self->pidl("NDR_PULL_CHECK_FLAGS(ndr, ndr_flags);");
        $self->pidl("if (ndr_flags & NDR_SCALARS) {");
        $self->indent;
+       if (! $needs_deferred_switch) {
+               $self->pidl("/* This token is not used again */");
+               $self->pidl("level = ndr_pull_steal_switch_value($ndr, $varname);");
+       } else {
+               $self->pidl("level = ndr_pull_get_switch_value($ndr, $varname);");
+       }
        $self->ParseUnionPullPrimitives($e,$ndr,$varname,$switch_type);
        $self->deindent;
        $self->pidl("}");
-
-       $self->pidl("if (ndr_flags & NDR_BUFFERS) {");
-       $self->indent;
-       $self->ParseUnionPullDeferred($e,$ndr,$varname);
-       $self->deindent;
-       $self->pidl("}");
-
+       if ($needs_deferred_switch) {
+               $self->pidl("if (ndr_flags & NDR_BUFFERS) {");
+               $self->indent;
+               $self->pidl("/* The token is not needed after this. */");
+               $self->pidl("level = ndr_pull_steal_switch_value($ndr, $varname);");
+               $self->ParseUnionPullDeferred($e,$ndr,$varname);
+               $self->deindent;
+               $self->pidl("}");
+       }
        $self->add_deferred();
 
        $self->end_flags($e, $ndr);
@@ -2363,6 +2446,12 @@ sub ParseFunctionPush($$)
 
        EnvSubstituteValue($env, $fn);
 
+       foreach my $e (@{$fn->{ELEMENTS}}) {
+               if (grep(/in/,@{$e->{DIRECTION}})) {
+                       $self->CheckRefPtrs($e, $ndr, $env);
+               }
+       }
+
        foreach my $e (@{$fn->{ELEMENTS}}) {
                if (grep(/in/,@{$e->{DIRECTION}})) {
                        $self->ParseElementPush($e, $ndr, $env, 1, 1);
@@ -2376,6 +2465,14 @@ sub ParseFunctionPush($$)
        $self->indent;
 
        $env = GenerateFunctionOutEnv($fn);
+       EnvSubstituteValue($env, $fn);
+
+       foreach my $e (@{$fn->{ELEMENTS}}) {
+               if (grep(/out/,@{$e->{DIRECTION}})) {
+                       $self->CheckRefPtrs($e, $ndr, $env);
+               }
+       }
+
        foreach my $e (@{$fn->{ELEMENTS}}) {
                if (grep(/out/,@{$e->{DIRECTION}})) {
                        $self->ParseElementPush($e, $ndr, $env, 1, 1);
@@ -2454,7 +2551,7 @@ sub ParseFunctionPull($$)
        # out to be too tricky (tridge)
        foreach my $e (@{$fn->{ELEMENTS}}) {
                next unless grep(/out/, @{$e->{DIRECTION}});
-               $self->pidl("ZERO_STRUCT(r->out);");
+               $self->pidl("NDR_ZERO_STRUCT(r->out);");
                $self->pidl("");
                last;
        }
@@ -2503,7 +2600,7 @@ sub ParseFunctionPull($$)
                        if (grep(/in/, @{$e->{DIRECTION}})) {
                                $self->pidl("*r->out.$e->{NAME} = *r->in.$e->{NAME};");
                        } else {
-                               $self->pidl("ZERO_STRUCTP(r->out.$e->{NAME});");
+                               $self->pidl("NDR_ZERO_STRUCTP(r->out.$e->{NAME});");
                        }
                }
        }
@@ -2579,7 +2676,7 @@ sub ParseGeneratePipeArray($$$)
                $self->deindent;
                $self->pidl("},");
        }
-       $self->pidl("{ NULL, NULL, 0, NULL, NULL, NULL }");
+       $self->pidl("{ .name = NULL }");
        $self->deindent;
        $self->pidl("};");
        $self->pidl("");
@@ -2675,7 +2772,7 @@ sub FunctionTable($$)
        foreach my $d (@{$interface->{INHERITED_FUNCTIONS}},@{$interface->{FUNCTIONS}}) {
                $count += $self->FunctionCallEntry($d);
        }
-       $self->pidl("\t{ NULL, 0, NULL, NULL, NULL }");
+       $self->pidl("\t{ .name = NULL }");
        $self->pidl("};");
        $self->pidl("");