r5775: Remove some unused functions (unions are no longer as special as they used...
[samba.git] / source4 / build / pidl / ndr.pm
index 6af3aa852d109570e95783ea9f29e1135301433b..b4f02048a20718a359ccf4452840b5e1ac2b0024 100644 (file)
@@ -117,8 +117,7 @@ sub is_inline_array($)
 sub is_varying_array($)
 {
        my $e = shift;
-       return 1 if (util::has_property($e, "length_is"));
-       return 0;
+       return util::has_property($e, "length_is");
 }
 
 # return 1 if this is a surrounding array (sometimes 
@@ -172,8 +171,7 @@ sub need_wire_pointer($)
 sub need_buffers_section($)
 {
        my $e = shift;
-       if ((is_scalar_type($e->{TYPE}) || util::has_property($e, "subcontext")) &&
-           $e->{POINTERS} == 0 && 
+       if (!can_contain_deferred($e) &&
            !util::array_size($e)) {
                return 0;
        }
@@ -185,7 +183,7 @@ sub need_alloc($)
 {
        my $e = shift;
 
-       return 0 if (util::has_property($e, "ref"));
+       return 0 if (util::has_property($e, "ref") && $e->{PARENT}->{TYPE} eq "FUNCTION");
        return 1 if ($e->{POINTERS} || util::array_size($e));
        return 0;
 }
@@ -210,9 +208,9 @@ sub c_push_prefix($)
 
        if ($e->{TYPE} =~ "string") {
                $ret = "";
-       } elsif (is_scalar_type($e->{TYPE}) &&
-           $e->{POINTERS}) {
-               $ret "*";
+       } elsif (is_scalar_type($e->{TYPE}) and $e->{POINTERS} and 
+               !util::array_size($e)) {
+               $ret .="*";
        } elsif (!is_scalar_type($e->{TYPE}) &&
            !$e->{POINTERS} &&
            !util::array_size($e)) {
@@ -408,6 +406,26 @@ sub align_type
        return $tmp;
 }
 
+#####################################################################
+# see if a type contains any deferred data 
+sub can_contain_deferred
+{
+       my $e = shift;
+
+       return 1 if ($e->{POINTERS});
+       return 0 if (is_scalar_type($e->{TYPE}));
+       return 0 if (util::has_property($e, "subcontext"));
+       return 1 unless (typelist::hasType($e->{TYPE})); # assume the worst
+
+       my $type = typelist::getType($e->{TYPE});
+
+       foreach my $x (@{$type->{DATA}->{ELEMENTS}}) {
+               return 1 if (can_contain_deferred ($x));
+       }
+       
+       return 0;
+}
+
 #####################################################################
 # parse array preceding data - push side
 sub ParseArrayPushPreceding($$$)
@@ -432,6 +450,7 @@ sub ParseArrayPush($$$$)
        my $ndr = shift;
        my $var_prefix = shift;
        my $ndr_flags = shift;
+       my $cprefix = c_push_prefix($e);
 
        my $size = ParseExpr($e, util::array_size($e), $var_prefix);
 
@@ -449,9 +468,9 @@ sub ParseArrayPush($$$$)
        }
 
        if (is_scalar_type($e->{TYPE})) {
-               pidl "NDR_CHECK(ndr_push_array_$e->{TYPE}($ndr, $ndr_flags, $var_prefix$e->{NAME}, $size));";
+               pidl "NDR_CHECK(ndr_push_array_$e->{TYPE}($ndr, $ndr_flags, $cprefix$var_prefix$e->{NAME}, $size));";
        } else {
-               pidl "NDR_CHECK(ndr_push_array($ndr, $ndr_flags, $var_prefix$e->{NAME}, sizeof($var_prefix$e->{NAME}\[0]), $size, (ndr_push_flags_fn_t)ndr_push_$e->{TYPE}));";
+               pidl "NDR_CHECK(ndr_push_array($ndr, $ndr_flags, $cprefix$var_prefix$e->{NAME}, sizeof($cprefix$var_prefix$e->{NAME}\[0]), $size, (ndr_push_flags_fn_t)ndr_push_$e->{TYPE}));";
        }
 }
 
@@ -462,16 +481,16 @@ sub ParseArrayPrint($$)
        my $e = shift;
        my $var_prefix = shift;
        my $size = ParseExpr($e, util::array_size($e), $var_prefix);
-       my $ptr_prefix = c_ptr_prefix($e);
+       my $cprefix = c_push_prefix($e);
 
        if (is_varying_array($e)) {
                $size = ParseExpr($e, util::has_property($e, "length_is"), $var_prefix);
        }
 
        if (is_scalar_type($e->{TYPE})) {
-               pidl "ndr_print_array_$e->{TYPE}(ndr, \"$e->{NAME}\", $var_prefix$e->{NAME}, $size);";
+               pidl "ndr_print_array_$e->{TYPE}(ndr, \"$e->{NAME}\", $cprefix$var_prefix$e->{NAME}, $size);";
        } else {
-               pidl "ndr_print_array(ndr, \"$e->{NAME}\", $var_prefix$e->{NAME}, sizeof($var_prefix$e->{NAME}\[0]), $size, (ndr_print_fn_t)ndr_print_$e->{TYPE});";
+               pidl "ndr_print_array(ndr, \"$e->{NAME}\", $cprefix$var_prefix$e->{NAME}, sizeof($cprefix$var_prefix$e->{NAME}\[0]), $size, (ndr_print_fn_t)ndr_print_$e->{TYPE});";
        }
 }
 
@@ -482,7 +501,7 @@ sub CheckArraySizes($$)
        my $e = shift;
        my $var_prefix = shift;
 
-       if (!is_surrounding_array($e) && is_conformant_array($e)) {
+       if (is_conformant_array($e)) {
                my $size = ParseExpr($e, util::array_size($e), $var_prefix);
                pidl "if ($var_prefix$e->{NAME}) {";
                indent;
@@ -525,56 +544,59 @@ sub ParseArrayPull($$$$)
        my $var_prefix = shift;
        my $ndr_flags = shift;
 
-       my $size = ParseExpr($e, util::array_size($e), $var_prefix);
-       my $alloc_size = $size;
+       my $cprefix = c_pull_prefix($e);
+       my $length = ParseExpr($e, util::array_size($e), $var_prefix);
+       my $size = $length;
+
+       if (is_conformant_array($e)) {
+               $length = $size = "ndr_get_array_size($ndr, &$var_prefix$e->{NAME})";
+       }
 
        # if this is a conformant array then we use that size to allocate, and make sure
        # we allocate enough to pull the elements
-       if (is_conformant_array($e) and is_surrounding_array($e)) {
-               $alloc_size = "ndr_get_array_size($ndr, &$var_prefix$e->{NAME})";
-               check_null_pointer($size);
-               pidl "if ($size > $alloc_size) {";
-               indent;
-               pidl "return ndr_pull_error($ndr, NDR_ERR_CONFORMANT_SIZE, \"Bad conformant size %u should be %u\", $alloc_size, $size);";
-               deindent;
-               pidl "}";
-       } elsif (!is_inline_array($e)) {
-               if ($var_prefix =~ /^r->out/ && $size =~ /^\*r->in/) {
-                       my $size2 = substr($size, 1);
-                       pidl "if (ndr->flags & LIBNDR_FLAG_REF_ALLOC) { NDR_ALLOC($ndr, $size2); }";
+       if (!is_inline_array($e) and not is_surrounding_array($e)) {
+               if ($var_prefix =~ /^r->out/ && $length =~ /^\*r->in/) {
+                       my $length2 = substr($length, 1);
+                       pidl "if (ndr->flags & LIBNDR_FLAG_REF_ALLOC) { NDR_ALLOC($ndr, $length2); }";
                }
 
                ParseArrayPullPreceding($e, $var_prefix, $ndr_flags);
+       }
+
+       if (is_varying_array($e)) {
+               pidl "NDR_CHECK(ndr_pull_array_length($ndr, &$var_prefix$e->{NAME}));";
+               $length = "ndr_get_array_length($ndr, &$var_prefix$e->{NAME})";
+       }
+
+       check_null_pointer($length);
 
-               $alloc_size = "ndr_get_array_size($ndr, &$var_prefix$e->{NAME})";
+       if ($length ne $size) {
+               pidl "if ($length > $size) {";
+               indent;
+               pidl "return ndr_pull_error($ndr, NDR_ERR_CONFORMANT_SIZE, \"Bad conformant size %u should be %u\", $size, $length);";
+               deindent;
+               pidl "}";
        }
 
        if ((need_alloc($e) && !is_fixed_array($e)) ||
            ($var_prefix eq "r->in." && util::has_property($e, "ref"))) {
                if (!is_inline_array($e) || $ndr_flags eq "NDR_SCALARS") {
-                       pidl "NDR_ALLOC_N($ndr, $var_prefix$e->{NAME}, $alloc_size);";
+                       pidl "NDR_ALLOC_N($ndr, $var_prefix$e->{NAME}, $size);";
                }
        }
 
        if (($var_prefix eq "r->out." && util::has_property($e, "ref"))) {
                if (!is_inline_array($e) || $ndr_flags eq "NDR_SCALARS") {
                        pidl "if ($ndr->flags & LIBNDR_FLAG_REF_ALLOC) {";
-                       pidl "\tNDR_ALLOC_N($ndr, $var_prefix$e->{NAME}, $alloc_size);";
+                       pidl "\tNDR_ALLOC_N($ndr, $var_prefix$e->{NAME}, $size);";
                        pidl "}";
                }
        }
 
-       if (is_varying_array($e)) {
-               pidl "NDR_CHECK(ndr_pull_array_length($ndr, &$var_prefix$e->{NAME}));";
-               $size = "ndr_get_array_length($ndr, &$var_prefix$e->{NAME})";
-       }
-
-       check_null_pointer($size);
-
        if (is_scalar_type($e->{TYPE})) {
-               pidl "NDR_CHECK(ndr_pull_array_$e->{TYPE}($ndr, $ndr_flags, $var_prefix$e->{NAME}, $size));";
+               pidl "NDR_CHECK(ndr_pull_array_$e->{TYPE}($ndr, $ndr_flags, $cprefix$var_prefix$e->{NAME}, $length));";
        } else {
-               pidl "NDR_CHECK(ndr_pull_array($ndr, $ndr_flags, (void **)$var_prefix$e->{NAME}, sizeof($var_prefix$e->{NAME}\[0]), $size, (ndr_pull_flags_fn_t)ndr_pull_$e->{TYPE}));";
+               pidl "NDR_CHECK(ndr_pull_array($ndr, $ndr_flags, (void **)$cprefix$var_prefix$e->{NAME}, sizeof($cprefix$var_prefix$e->{NAME}\[0]), $length, (ndr_pull_flags_fn_t)ndr_pull_$e->{TYPE}));";
        }
 }
 
@@ -663,9 +685,11 @@ sub ParseElementPushScalar($$$)
                ParseArrayPush($e, $ndr, "r->", "NDR_SCALARS");
        } elsif (need_alloc($e)) {
                # no scalar component
-       } elsif (my $switch = util::has_property($e, "switch_is")) {
-               ParseSwitchPush($e, $ndr, $var_prefix, $ndr_flags, $switch);
        } else {
+               if (my $switch = util::has_property($e, "switch_is")) {
+                       ParseSwitchPush($e, $ndr, $var_prefix, $ndr_flags, $switch);
+               }
+
                pidl "NDR_CHECK(ndr_push_$e->{TYPE}($ndr, $ndr_flags, $cprefix$var_prefix$e->{NAME}));";
        }
 
@@ -683,7 +707,9 @@ sub ParsePtrPush($$)
        my $e = shift;
        my $var_prefix = shift;
 
-       if (util::has_property($e, "relative")) {
+       if (util::has_property($e, "ref")) {
+               pidl "NDR_CHECK(ndr_push_ref_ptr(ndr, $var_prefix$e->{NAME}));";
+       } elsif (util::has_property($e, "relative")) {
                pidl "NDR_CHECK(ndr_push_relative_ptr1(ndr, $var_prefix$e->{NAME}));";
        } else {
                pidl "NDR_CHECK(ndr_push_unique_ptr(ndr, $var_prefix$e->{NAME}));";
@@ -756,33 +782,8 @@ sub ParseSwitchPull($$$$$)
 
        check_null_pointer($switch_var);
 
-       if (!defined $utype ||
-           !util::has_property($utype, "nodiscriminant")) {
-               my $e2 = util::find_sibling($e, $switch);
-               my $type_decl = typelist::mapType($e2);
-               pidl "if (($ndr_flags) & NDR_SCALARS) {";
-               indent;
-               pidl "$type_decl _level;";
-               pidl "NDR_CHECK(ndr_pull_$e2->{TYPE}($ndr, NDR_SCALARS, &_level));";
-               if ($switch_var =~ /r->in/) {
-                       pidl "if (!($ndr->flags & LIBNDR_FLAG_REF_ALLOC) && _level != $switch_var) {";
-                       indent;
-               } else {
-                       pidl "if (_level != $switch_var) {"; 
-                       indent;
-               }
-               pidl "return ndr_pull_error($ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value %u in $e->{NAME}\", _level);";
-               deindent;
-               if ($switch_var =~ /r->/) {
-                       pidl "} else { $switch_var = _level; }";
-               } else {
-                       pidl "}";
-               }
-               deindent;
-               pidl "}";
-       }
+       pidl "NDR_CHECK(ndr_pull_set_switch_value($ndr, $cprefix$var_prefix$e->{NAME}, $switch_var));";
 
-       pidl "NDR_CHECK(ndr_pull_$e->{TYPE}($ndr, $ndr_flags, $switch_var, $cprefix$var_prefix$e->{NAME}));";
 }
 
 #####################################################################
@@ -799,16 +800,8 @@ sub ParseSwitchPush($$$$$)
 
        check_null_pointer($switch_var);
 
-       my $utype = typelist::getType($e->{TYPE});
-       if (!defined $utype ||
-           !util::has_property($utype, "nodiscriminant")) {
-               my $e2 = util::find_sibling($e, $switch);
-               pidl "if (($ndr_flags) & NDR_SCALARS) {";
-               pidl "\tNDR_CHECK(ndr_push_$e2->{TYPE}($ndr, NDR_SCALARS, $switch_var));";
-               pidl "}";
-       }
+       pidl "NDR_CHECK(ndr_push_set_switch_value($ndr, $cprefix$var_prefix$e->{NAME}, $switch_var));";
 
-       pidl "NDR_CHECK(ndr_push_$e->{TYPE}($ndr, $ndr_flags, $switch_var, $cprefix$var_prefix$e->{NAME}));";
 }
 
 #####################################################################
@@ -835,9 +828,11 @@ sub ParseElementPullScalar($$$)
        } elsif (need_wire_pointer($e)) {
                ParsePtrPull($e, $ptr_prefix.$var_prefix);
        } elsif (is_surrounding_array($e)) {
-       } elsif (my $switch = util::has_property($e, "switch_is")) {
-               ParseSwitchPull($e, $ndr, $var_prefix, $ndr_flags, $switch);
        } else {
+               if (my $switch = util::has_property($e, "switch_is")) {
+                       ParseSwitchPull($e, $ndr, $var_prefix, $ndr_flags, $switch);
+               }
+
                pidl "NDR_CHECK(ndr_pull_$e->{TYPE}($ndr, $ndr_flags, $cprefix$var_prefix$e->{NAME}));";
        }
 
@@ -862,7 +857,11 @@ sub ParsePtrPull($$)
        my($e) = shift;
        my($var_prefix) = shift;
 
-       pidl "NDR_CHECK(ndr_pull_unique_ptr(ndr, &_ptr_$e->{NAME}));";
+       if (util::has_property($e, "ref")) {
+               pidl "NDR_CHECK(ndr_pull_ref_ptr(ndr, &_ptr_$e->{NAME}));";
+       } else {
+               pidl "NDR_CHECK(ndr_pull_unique_ptr(ndr, &_ptr_$e->{NAME}));";
+       }
        pidl "if (_ptr_$e->{NAME}) {";
        indent;
        pidl "NDR_ALLOC(ndr, $var_prefix$e->{NAME});";
@@ -916,9 +915,11 @@ sub ParseElementPushBuffer($$)
            
        if (util::array_size($e)) {
                ParseArrayPush($e, $ndr, "r->", $ndr_flags);
-       } elsif (my $switch = util::has_property($e, "switch_is")) {
-               ParseSwitchPush($e, $ndr, $var_prefix, $ndr_flags, $switch);
        } else {
+               if (my $switch = util::has_property($e, "switch_is")) {
+                       ParseSwitchPush($e, $ndr, $var_prefix, $ndr_flags, $switch);
+               }
+
                pidl "NDR_CHECK(ndr_push_$e->{TYPE}(ndr, $ndr_flags, $cprefix$var_prefix$e->{NAME}));";
        }
 
@@ -977,9 +978,11 @@ sub ParseElementPullBuffer($$)
 
        if (util::array_size($e)) {
                ParseArrayPull($e, $ndr, "r->", $ndr_flags);
-       } elsif (my $switch = util::has_property($e, "switch_is")) {
-               ParseSwitchPull($e, $ndr, $var_prefix, $ndr_flags, $switch);
        } else {
+               if (my $switch = util::has_property($e, "switch_is")) {
+                       ParseSwitchPull($e, $ndr, $var_prefix, $ndr_flags, $switch);
+               }
+
                pidl "NDR_CHECK(ndr_pull_$e->{TYPE}($ndr, $ndr_flags, $cprefix$var_prefix$e->{NAME}));";
        }
 
@@ -1397,10 +1400,20 @@ sub ParseUnionPush($)
        my $e = shift;
        my $have_default = 0;
 
+       pidl "int level;";
+
        start_flags($e);
 
+       pidl "level = ndr_push_get_switch_value(ndr, r);";
+
        pidl "if (!(ndr_flags & NDR_SCALARS)) goto buffers;";
 
+       if (!util::has_property($e, "nodiscriminant")) {
+               my $switch_type = util::has_property($e, "switch_type");
+               $switch_type = "uint32" unless  (defined ($switch_type));
+               pidl "NDR_CHECK(ndr_push_$switch_type(ndr, NDR_SCALARS, level));";
+       }
+
        pidl "NDR_CHECK(ndr_push_struct_start(ndr));";
 
 #      my $align = union_alignment($e);
@@ -1503,11 +1516,30 @@ sub ParseUnionPull($)
 {
        my $e = shift;
        my $have_default = 0;
+       my $switch_type = util::has_property($e, "switch_type");
+       $switch_type = "uint32" unless defined($switch_type);
+
+       pidl "int level;";
+       if (!util::has_property($e, "nodiscriminant")) {
+               if (typelist::typeIs($switch_type, "ENUM")) {
+                       $switch_type = typelist::enum_type_fn(typelist::getType($switch_type));
+               }
+               pidl typelist::mapScalarType($switch_type) . " _level;";
+       }
 
        start_flags($e);
 
+       pidl "level = ndr_pull_get_switch_value(ndr, r);";
+
        pidl "if (!(ndr_flags & NDR_SCALARS)) goto buffers;";
 
+       if (!util::has_property($e, "nodiscriminant")) {
+               pidl "NDR_CHECK(ndr_pull_$switch_type(ndr, NDR_SCALARS, &_level));";
+               pidl "if (_level != level) {"; 
+               pidl "\treturn ndr_pull_error(ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value %u for $e->{PARENT}->{NAME}\", _level);";
+               pidl "}";
+       }
+
        pidl "NDR_CHECK(ndr_pull_struct_start(ndr));";
 
 #      my $align = union_alignment($e);
@@ -1571,7 +1603,7 @@ sub ParseUnionPull($)
 sub ArgsUnionPush($)
 {
        my $e = shift;
-       return "struct ndr_push *ndr, int ndr_flags, int level, union $e->{NAME} *r";
+       return "struct ndr_push *ndr, int ndr_flags, union $e->{NAME} *r";
 }
 
 sub ArgsUnionPrint($)
@@ -1583,7 +1615,7 @@ sub ArgsUnionPrint($)
 sub ArgsUnionPull($)
 {
        my $e = shift;
-       return "struct ndr_pull *ndr, int ndr_flags, int level, union $e->{NAME} *r";
+       return "struct ndr_pull *ndr, int ndr_flags, union $e->{NAME} *r";
 }
 
 sub ArgsUnionNdrSize($)
@@ -1751,7 +1783,7 @@ sub ParseFunctionElementPush($$)
 
        if (util::array_size($e)) {
                if (need_wire_pointer($e)) {
-                       pidl "NDR_CHECK(ndr_push_unique_ptr(ndr, r->$inout.$e->{NAME}));";
+                       ParsePtrPush($e, "r->$inout.");
                        pidl "if (r->$inout.$e->{NAME}) {";
                        indent;
                        ParseArrayPush($e, "ndr", "r->$inout.", "NDR_SCALARS|NDR_BUFFERS");
@@ -1786,6 +1818,9 @@ sub ParseFunctionPush($)
 
        foreach my $e (@{$fn->{ELEMENTS}}) {
                if (util::has_property($e, "in")) {
+                       if (util::has_property($e, "ref")) {
+                               check_null_pointer("*r->in.$e->{NAME}");
+                       } 
                        ParseFunctionElementPush($e, "in");
                }               
        }
@@ -1796,6 +1831,9 @@ sub ParseFunctionPush($)
 
        foreach my $e (@{$fn->{ELEMENTS}}) {
                if (util::has_property($e, "out")) {
+                       if (util::has_property($e, "ref")) {
+                               check_null_pointer("*r->out.$e->{NAME}");
+                       } 
                        ParseFunctionElementPush($e, "out");
                }               
        }