slightly more accurate structure alignment code - I need to do proper
[samba.git] / source / build / pidl / parser.pm
index 99f3fdf4bbde0d490fe051c4191fe8a1e55ac0a8..e227d0d374aa39283f8aff0dbf331f15e3367dc3 100644 (file)
@@ -40,6 +40,10 @@ sub find_size_var($$)
        if (util::is_constant($size)) {
                return $size;
        }
+
+       if ($size =~ /ndr->/) {
+               return $size;
+       }
        
        if ($fn->{TYPE} ne "FUNCTION") {
                return "r->$size";
@@ -59,13 +63,24 @@ sub find_size_var($$)
 }
 
 
+#####################################################################
+# work out is a parse function should be declared static or not
+sub fn_prefix($)
+{
+       my $e = shift;
+       if (util::has_property($e, "public")) {
+               return "static ";
+       }
+       return "";
+}
+
+
 #####################################################################
 # work out the correct alignment for a structure
 sub struct_alignment($)
 {
        my $s = shift;
-       # why do we need a minimum alignment of 4 ?? 
-       my $align = 4;
+       my $align = 1;
        for my $e (@{$s->{ELEMENTS}}) {
                if ($align < util::type_align($e)) {
                        $align = util::type_align($e);
@@ -86,7 +101,7 @@ sub ParseArrayPush($$$)
 
        if (defined $e->{CONFORMANT_SIZE}) {
                # the conformant size has already been pushed
-       } elsif (!util::is_fixed_array($e)) {
+       } elsif (!util::is_inline_array($e)) {
                # we need to emit the array size
                $res .= "\t\tNDR_CHECK(ndr_push_uint32(ndr, $size));\n";
        }
@@ -99,9 +114,9 @@ sub ParseArrayPush($$$)
        }
 
        if (util::is_scalar_type($e->{TYPE})) {
-               $res .= "\t\tNDR_CHECK(ndr_push_array_$e->{TYPE}(ndr, $var_prefix$e->{NAME}, $size));\n";
+               $res .= "\t\tNDR_CHECK(ndr_push_array_$e->{TYPE}(ndr, $ndr_flags, $var_prefix$e->{NAME}, $size));\n";
        } else {
-               $res .= "\t\tNDR_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}));\n";
+               $res .= "\t\tNDR_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}));\n";
        }
 }
 
@@ -144,7 +159,7 @@ sub ParseArrayPull($$$)
                $res .= "\tif ($size > $alloc_size) {\n";
                $res .= "\t\treturn ndr_pull_error(ndr, NDR_ERR_CONFORMANT_SIZE, \"Bad conformant size %u should be %u\", $alloc_size, $size);\n";
                $res .= "\t}\n";
-       } elsif (!util::is_fixed_array($e)) {
+       } elsif (!util::is_inline_array($e)) {
                # non fixed arrays encode the size just before the array
                $res .= "\t{\n";
                $res .= "\t\tuint32 _array_size;\n";
@@ -156,7 +171,9 @@ sub ParseArrayPull($$$)
        }
 
        if (util::need_alloc($e) && !util::is_fixed_array($e)) {
-               $res .= "\t\tNDR_ALLOC_N_SIZE(ndr, $var_prefix$e->{NAME}, $alloc_size, sizeof($var_prefix$e->{NAME}\[0]));\n";
+               if (!util::is_inline_array($e) || $ndr_flags eq "NDR_SCALARS") {
+                       $res .= "\t\tNDR_ALLOC_N_SIZE(ndr, $var_prefix$e->{NAME}, $alloc_size, sizeof($var_prefix$e->{NAME}\[0]));\n";
+               }
        }
 
        if (my $length = util::has_property($e, "length_is")) {
@@ -170,7 +187,7 @@ sub ParseArrayPull($$$)
        }
 
        if (util::is_scalar_type($e->{TYPE})) {
-               $res .= "\t\tNDR_CHECK(ndr_pull_array_$e->{TYPE}(ndr, $var_prefix$e->{NAME}, $size));\n";
+               $res .= "\t\tNDR_CHECK(ndr_pull_array_$e->{TYPE}(ndr, $ndr_flags, $var_prefix$e->{NAME}, $size));\n";
        } else {
                $res .= "\t\tNDR_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}));\n";
        }
@@ -186,7 +203,11 @@ sub ParseElementPushScalar($$$)
        my($ndr_flags) = shift;
        my $cprefix = util::c_push_prefix($e);
 
-       if (my $value = util::has_property($e, "value")) {
+       if (util::has_property($e, "relative")) {
+               $res .= "\tNDR_CHECK(ndr_push_relative(ndr, NDR_SCALARS, $var_prefix$e->{NAME}, (ndr_push_const_fn_t) ndr_push_$e->{TYPE}));\n";
+       } elsif (util::is_inline_array($e)) {
+               ParseArrayPush($e, "r->", "NDR_SCALARS");
+       } elsif (my $value = util::has_property($e, "value")) {
                $res .= "\tNDR_CHECK(ndr_push_$e->{TYPE}(ndr, $value));\n";
        } elsif (defined $e->{VALUE}) {
                $res .= "\tNDR_CHECK(ndr_push_$e->{TYPE}(ndr, $e->{VALUE}));\n";
@@ -214,7 +235,7 @@ sub ParseElementPrintScalar($$)
        } elsif (util::has_direct_buffers($e)) {
                $res .= "\tndr_print_ptr(ndr, \"$e->{NAME}\", $var_prefix$e->{NAME});\n";
                $res .= "\tndr->depth++;\n";
-               ParseElementPrintBuffer($e, "r->");
+               ParseElementPrintBuffer($e, $var_prefix);
                $res .= "\tndr->depth--;\n";
        } elsif (my $switch = util::has_property($e, "switch_is")) {
                ParseElementPrintSwitch($e, $var_prefix, $switch);
@@ -235,8 +256,15 @@ sub ParseElementPullSwitch($$$$)
 
        my $cprefix = util::c_pull_prefix($e);
 
-       $res .= "\t{ uint16 _level;\n";
-       $res .= "\tNDR_CHECK(ndr_pull_$e->{TYPE}(ndr, $ndr_flags, &_level, $cprefix$var_prefix$e->{NAME}));\n";
+       $res .= "\t{ uint16 _level = $switch_var;\n";
+
+       if (util::has_property($e, "subcontext")) {
+               $res .= "\tNDR_CHECK(ndr_pull_subcontext_union_fn(ndr, &_level, $cprefix$var_prefix$e->{NAME}, (ndr_pull_union_fn_t) ndr_pull_$e->{TYPE}));\n";
+       } else {
+               $res .= "\tNDR_CHECK(ndr_pull_$e->{TYPE}(ndr, $ndr_flags, &_level, $cprefix$var_prefix$e->{NAME}));\n";
+       }
+
+
        $res .= "\tif ((($ndr_flags) & NDR_SCALARS) && (_level != $switch_var)) return ndr_pull_error(ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value %u in $e->{NAME}\");\n";
        $res .= "\t}\n";
 }
@@ -252,7 +280,11 @@ sub ParseElementPushSwitch($$$$)
        my $switch_var = find_size_var($e, $switch);
        my $cprefix = util::c_push_prefix($e);
 
-       $res .= "\tNDR_CHECK(ndr_push_$e->{TYPE}(ndr, $ndr_flags, $switch_var, $cprefix$var_prefix$e->{NAME}));\n";
+       if (util::has_property($e, "subcontext")) {
+               $res .= "\tNDR_CHECK(ndr_push_subcontext_union_fn(ndr, $switch_var, $cprefix$var_prefix$e->{NAME}, (ndr_push_union_fn_t) ndr_pull_$e->{TYPE}));\n";
+       } else {
+               $res .= "\tNDR_CHECK(ndr_push_$e->{TYPE}(ndr, $ndr_flags, $switch_var, $cprefix$var_prefix$e->{NAME}));\n";
+       }
 }
 
 #####################################################################
@@ -278,8 +310,12 @@ sub ParseElementPullScalar($$$)
        my($ndr_flags) = shift;
        my $cprefix = util::c_pull_prefix($e);
 
-       if (defined $e->{VALUE}) {
+       if (util::has_property($e, "relative")) {
+               $res .= "\tNDR_CHECK(ndr_pull_relative(ndr, (const void **)&$var_prefix$e->{NAME}, sizeof(*$var_prefix$e->{NAME}), (ndr_pull_flags_fn_t)ndr_pull_$e->{TYPE}));\n";
+       } elsif (defined $e->{VALUE}) {
                $res .= "\tNDR_CHECK(ndr_pull_$e->{TYPE}(ndr, $e->{VALUE}));\n";
+       } elsif (util::is_inline_array($e)) {
+               ParseArrayPull($e, "r->", "NDR_SCALARS");
        } elsif (util::need_wire_pointer($e)) {
                $res .= "\tNDR_CHECK(ndr_pull_uint32(ndr, &_ptr_$e->{NAME}));\n";
                $res .= "\tif (_ptr_$e->{NAME}) {\n";
@@ -291,6 +327,12 @@ sub ParseElementPullScalar($$$)
                # no scalar component
        } elsif (my $switch = util::has_property($e, "switch_is")) {
                ParseElementPullSwitch($e, $var_prefix, $ndr_flags, $switch);
+       } elsif (util::has_property($e, "subcontext")) {
+               if (util::is_builtin_type($e->{TYPE})) {
+                       $res .= "\tNDR_CHECK(ndr_pull_subcontext_fn(ndr, $cprefix$var_prefix$e->{NAME}, (ndr_pull_fn_t) ndr_pull_$e->{TYPE}));\n";
+               } else {
+                       $res .= "\tNDR_CHECK(ndr_pull_subcontext_flags_fn(ndr, $cprefix$var_prefix$e->{NAME}, (ndr_pull_flags_fn_t) ndr_pull_$e->{TYPE}));\n";
+               }
        } elsif (util::is_builtin_type($e->{TYPE})) {
                $res .= "\tNDR_CHECK(ndr_pull_$e->{TYPE}(ndr, $cprefix$var_prefix$e->{NAME}));\n";
        } else {
@@ -315,7 +357,11 @@ sub ParseElementPushBuffer($$$)
                $res .= "\tif ($var_prefix$e->{NAME}) {\n";
        }
            
-       if (util::array_size($e)) {
+       if (util::has_property($e, "relative")) {
+               $res .= "\tNDR_CHECK(ndr_push_relative(ndr, NDR_BUFFERS, $cprefix$var_prefix$e->{NAME}, (ndr_push_const_fn_t) ndr_push_$e->{TYPE}));\n";
+       } elsif (util::is_inline_array($e)) {
+               ParseArrayPush($e, "r->", "NDR_BUFFERS");
+       } elsif (util::array_size($e)) {
                ParseArrayPush($e, "r->", "NDR_SCALARS|NDR_BUFFERS");
        } elsif (my $switch = util::has_property($e, "switch_is")) {
                if ($e->{POINTERS}) {
@@ -344,16 +390,12 @@ sub ParseElementPrintBuffer($$)
        my($var_prefix) = shift;
        my $cprefix = util::c_push_prefix($e);
 
-       if (util::is_pure_scalar($e)) {
-               return;
-       }
-
        if (util::need_wire_pointer($e)) {
                $res .= "\tif ($var_prefix$e->{NAME}) {\n";
        }
            
        if (util::array_size($e)) {
-               ParseArrayPrint($e, "r->");
+               ParseArrayPrint($e, $var_prefix);
        } elsif (my $switch = util::has_property($e, "switch_is")) {
                ParseElementPrintSwitch($e, $var_prefix, $switch);
        } else {
@@ -379,11 +421,17 @@ sub ParseElementPullBuffer($$$)
                return;
        }
 
+       if (util::has_property($e, "relative")) {
+               return;
+       }
+
        if (util::need_wire_pointer($e)) {
                $res .= "\tif ($var_prefix$e->{NAME}) {\n";
        }
            
-       if (util::array_size($e)) {
+       if (util::is_inline_array($e)) {
+               ParseArrayPull($e, "r->", "NDR_BUFFERS");
+       } elsif (util::array_size($e)) {
                ParseArrayPull($e, "r->", "NDR_SCALARS|NDR_BUFFERS");
        } elsif (my $switch = util::has_property($e, "switch_is")) {
                if ($e->{POINTERS}) {
@@ -391,6 +439,12 @@ sub ParseElementPullBuffer($$$)
                } else {
                        ParseElementPullSwitch($e, $var_prefix, "NDR_BUFFERS", $switch);
                }
+       } elsif (util::has_property($e, "subcontext")) {
+               if (util::is_builtin_type($e->{TYPE})) {
+                       $res .= "\tNDR_CHECK(ndr_pull_subcontext_fn(ndr, $cprefix$var_prefix$e->{NAME}, (ndr_pull_fn_t) ndr_pull_$e->{TYPE}));\n";
+               } else {
+                       $res .= "\tNDR_CHECK(ndr_pull_subcontext_flags_fn(ndr, $cprefix$var_prefix$e->{NAME}, (ndr_pull_flags_fn_t) ndr_pull_$e->{TYPE}));\n";
+               }
        } elsif (util::is_builtin_type($e->{TYPE})) {
                $res .= "\t\tNDR_CHECK(ndr_pull_$e->{TYPE}(ndr, $cprefix$var_prefix$e->{NAME}));\n";
        } elsif ($e->{POINTERS}) {
@@ -430,6 +484,8 @@ sub ParseStructPush($)
 
        $res .= "\tif (!(ndr_flags & NDR_SCALARS)) goto buffers;\n";
 
+       $res .= "\tNDR_CHECK(ndr_push_struct_start(ndr));\n";
+
        my $align = struct_alignment($struct);
        $res .= "\tNDR_CHECK(ndr_push_align(ndr, $align));\n";
 
@@ -438,6 +494,8 @@ sub ParseStructPush($)
                ParseElementPushScalar($e, "r->", "NDR_SCALARS");
        }       
 
+       $res .= "\tndr_push_struct_end(ndr);\n";
+
        $res .= "buffers:\n";
        $res .= "\tif (!(ndr_flags & NDR_BUFFERS)) goto done;\n";
        foreach my $e (@{$struct->{ELEMENTS}}) {
@@ -495,6 +553,7 @@ sub ParseStructPull($)
                }
        }
 
+       $res .= "\tNDR_CHECK(ndr_pull_struct_start(ndr));\n";
 
        if (defined $conform_e) {
                $res .= "\tNDR_CHECK(ndr_pull_uint32(ndr, &$conform_e->{CONFORMANT_SIZE}));\n";
@@ -509,6 +568,8 @@ sub ParseStructPull($)
                ParseElementPullScalar($e, "r->", "NDR_SCALARS");
        }       
 
+       $res .= "\tndr_pull_struct_end(ndr);\n";
+
        $res .= "buffers:\n";
        $res .= "\tif (!(ndr_flags & NDR_BUFFERS)) goto done;\n";
        foreach my $e (@{$struct->{ELEMENTS}}) {
@@ -524,27 +585,47 @@ sub ParseStructPull($)
 sub ParseUnionPush($)
 {
        my $e = shift;
+       my $have_default = 0;
        $res .= "\tif (!(ndr_flags & NDR_SCALARS)) goto buffers;\n";
-       $res .= "\tNDR_CHECK(ndr_push_uint16(ndr, level));\n";
+
+       $res .= "\tNDR_CHECK(ndr_push_struct_start(ndr));\n";
+
+       if (!util::has_property($e, "nodiscriminant")) {
+               $res .= "\tNDR_CHECK(ndr_push_uint16(ndr, level));\n";
+       }
        $res .= "\tswitch (level) {\n";
        foreach my $el (@{$e->{DATA}}) {
-               $res .= "\tcase $el->{CASE}:\n";
+               if ($el->{CASE} eq "default") {
+                       $res .= "\tdefault:\n";
+                       $have_default = 1;
+               } else {
+                       $res .= "\tcase $el->{CASE}:\n";
+               }
                ParseElementPushScalar($el->{DATA}, "r->", "NDR_SCALARS");              
                $res .= "\tbreak;\n\n";
        }
-       $res .= "\tdefault:\n";
-       $res .= "\t\treturn ndr_push_error(ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value \%u\", level);\n";
+       if (! $have_default) {
+               $res .= "\tdefault:\n";
+               $res .= "\t\treturn ndr_push_error(ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value \%u\", level);\n";
+       }
        $res .= "\t}\n";
+       $res .= "\tndr_push_struct_end(ndr);\n";
        $res .= "buffers:\n";
        $res .= "\tif (!(ndr_flags & NDR_BUFFERS)) goto done;\n";
        $res .= "\tswitch (level) {\n";
        foreach my $el (@{$e->{DATA}}) {
-               $res .= "\tcase $el->{CASE}:\n";
+               if ($el->{CASE} eq "default") {
+                       $res .= "\tdefault:\n";
+               } else {
+                       $res .= "\tcase $el->{CASE}:\n";
+               }
                ParseElementPushBuffer($el->{DATA}, "r->", "ndr_flags");
                $res .= "\tbreak;\n\n";
        }
-       $res .= "\tdefault:\n";
-       $res .= "\t\treturn ndr_push_error(ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value \%u\", level);\n";
+       if (! $have_default) {
+               $res .= "\tdefault:\n";
+               $res .= "\t\treturn ndr_push_error(ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value \%u\", level);\n";
+       }
        $res .= "\t}\n";
        $res .= "done:\n";
 }
@@ -554,14 +635,22 @@ sub ParseUnionPush($)
 sub ParseUnionPrint($)
 {
        my $e = shift;
+       my $have_default = 0;
 
        $res .= "\tswitch (level) {\n";
        foreach my $el (@{$e->{DATA}}) {
-               $res .= "\tcase $el->{CASE}:\n";
+               if ($el->{CASE} eq "default") {
+                       $have_default = 1;
+                       $res .= "\tdefault:\n";
+               } else {
+                       $res .= "\tcase $el->{CASE}:\n";
+               }
                ParseElementPrintScalar($el->{DATA}, "r->");
                $res .= "\tbreak;\n\n";
        }
-       $res .= "\tdefault:\n\t\tndr_print_bad_level(ndr, name, level);\n";
+       if (! $have_default) {
+               $res .= "\tdefault:\n\t\tndr_print_bad_level(ndr, name, level);\n";
+       }
        $res .= "\t}\n";
 }
 
@@ -570,12 +659,23 @@ sub ParseUnionPrint($)
 sub ParseUnionPull($)
 {
        my $e = shift;
+       my $have_default = 0;
 
        $res .= "\tif (!(ndr_flags & NDR_SCALARS)) goto buffers;\n";
-       $res .= "\tNDR_CHECK(ndr_pull_uint16(ndr, level));\n";
+
+       $res .= "\tNDR_CHECK(ndr_pull_struct_start(ndr));\n";
+
+       if (!util::has_property($e, "nodiscriminant")) {
+               $res .= "\tNDR_CHECK(ndr_pull_uint16(ndr, level));\n";
+       }
        $res .= "\tswitch (*level) {\n";
        foreach my $el (@{$e->{DATA}}) {
-               $res .= "\tcase $el->{CASE}: {\n";
+               if ($el->{CASE} eq "default") {
+                       $res .= "\tdefault: {\n";
+                       $have_default = 1;
+               } else {
+                       $res .= "\tcase $el->{CASE}: {\n";
+               }
                my $e2 = $el->{DATA};
                if ($e2->{POINTERS}) {
                        $res .= "\t\tuint32 _ptr_$e2->{NAME};\n";
@@ -583,19 +683,28 @@ sub ParseUnionPull($)
                ParseElementPullScalar($el->{DATA}, "r->", "NDR_SCALARS");              
                $res .= "\tbreak; }\n\n";
        }
-       $res .= "\tdefault:\n";
-       $res .= "\t\treturn ndr_pull_error(ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value \%u\", *level);\n";
+       if (! $have_default) {
+               $res .= "\tdefault:\n";
+               $res .= "\t\treturn ndr_pull_error(ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value \%u\", *level);\n";
+       }
        $res .= "\t}\n";
+       $res .= "\tndr_pull_struct_end(ndr);\n";
        $res .= "buffers:\n";
        $res .= "\tif (!(ndr_flags & NDR_BUFFERS)) goto done;\n";
        $res .= "\tswitch (*level) {\n";
        foreach my $el (@{$e->{DATA}}) {
-               $res .= "\tcase $el->{CASE}:\n";
+               if ($el->{CASE} eq "default") {
+                       $res .= "\tdefault:\n";
+               } else {
+                       $res .= "\tcase $el->{CASE}:\n";
+               }
                ParseElementPullBuffer($el->{DATA}, "r->", "NDR_BUFFERS");
                $res .= "\tbreak;\n\n";
        }
-       $res .= "\tdefault:\n";
-       $res .= "\t\treturn ndr_pull_error(ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value \%u\", *level);\n";
+       if (! $have_default) {
+               $res .= "\tdefault:\n";
+               $res .= "\t\treturn ndr_pull_error(ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value \%u\", *level);\n";
+       }
        $res .= "\t}\n";
        $res .= "done:\n";
 }
@@ -647,6 +756,7 @@ sub ParseTypePull($)
 sub ParseTypedefPush($)
 {
        my($e) = shift;
+       my $static = fn_prefix($e);
 
        if (! $needed{"push_$e->{NAME}"}) {
 #              print "push_$e->{NAME} not needed\n";
@@ -654,7 +764,7 @@ sub ParseTypedefPush($)
        }
 
        if ($e->{DATA}->{TYPE} eq "STRUCT") {
-               $res .= "static NTSTATUS ndr_push_$e->{NAME}(struct ndr_push *ndr, int ndr_flags, struct $e->{NAME} *r)";
+               $res .= "$static" . "NTSTATUS ndr_push_$e->{NAME}(struct ndr_push *ndr, int ndr_flags, struct $e->{NAME} *r)";
                $res .= "\n{\n";
                ParseTypePush($e->{DATA});
                $res .= "\treturn NT_STATUS_OK;\n";
@@ -662,7 +772,7 @@ sub ParseTypedefPush($)
        }
 
        if ($e->{DATA}->{TYPE} eq "UNION") {
-               $res .= "static NTSTATUS ndr_push_$e->{NAME}(struct ndr_push *ndr, int ndr_flags, uint16 level, union $e->{NAME} *r)";
+               $res .= "$static" . "NTSTATUS ndr_push_$e->{NAME}(struct ndr_push *ndr, int ndr_flags, uint16 level, union $e->{NAME} *r)";
                $res .= "\n{\n";
                ParseTypePush($e->{DATA});
                $res .= "\treturn NT_STATUS_OK;\n";
@@ -676,6 +786,7 @@ sub ParseTypedefPush($)
 sub ParseTypedefPull($)
 {
        my($e) = shift;
+       my $static = fn_prefix($e);
 
        if (! $needed{"pull_$e->{NAME}"}) {
 #              print "pull_$e->{NAME} not needed\n";
@@ -683,7 +794,7 @@ sub ParseTypedefPull($)
        }
 
        if ($e->{DATA}->{TYPE} eq "STRUCT") {
-               $res .= "static NTSTATUS ndr_pull_$e->{NAME}(struct ndr_pull *ndr, int ndr_flags, struct $e->{NAME} *r)";
+               $res .= "$static" . "NTSTATUS ndr_pull_$e->{NAME}(struct ndr_pull *ndr, int ndr_flags, struct $e->{NAME} *r)";
                $res .= "\n{\n";
                ParseTypePull($e->{DATA});
                $res .= "\treturn NT_STATUS_OK;\n";
@@ -691,7 +802,7 @@ sub ParseTypedefPull($)
        }
 
        if ($e->{DATA}->{TYPE} eq "UNION") {
-               $res .= "static NTSTATUS ndr_pull_$e->{NAME}(struct ndr_pull *ndr, int ndr_flags, uint16 *level, union $e->{NAME} *r)";
+               $res .= "$static" . "NTSTATUS ndr_pull_$e->{NAME}(struct ndr_pull *ndr, int ndr_flags, uint16 *level, union $e->{NAME} *r)";
                $res .= "\n{\n";
                ParseTypePull($e->{DATA});
                $res .= "\treturn NT_STATUS_OK;\n";
@@ -701,7 +812,7 @@ sub ParseTypedefPull($)
 
 
 #####################################################################
-# parse a typedef - push side
+# parse a typedef - print side
 sub ParseTypedefPrint($)
 {
        my($e) = shift;
@@ -723,6 +834,46 @@ sub ParseTypedefPrint($)
        }
 }
 
+#####################################################################
+# parse a function - print side
+sub ParseFunctionPrint($)
+{
+       my($fn) = shift;
+
+       $res .= "void ndr_print_$fn->{NAME}(struct ndr_print *ndr, const char *name, int flags, struct $fn->{NAME} *r)";
+       $res .= "\n{\n";
+       $res .= "\tndr_print_struct(ndr, name, \"$fn->{NAME}\");\n";
+       $res .= "\tndr->depth++;\n";
+       
+       $res .= "\tif (flags & NDR_IN) {\n";
+       $res .= "\t\tndr_print_struct(ndr, \"in\", \"$fn->{NAME}\");\n";
+       $res .= "\tndr->depth++;\n";
+       foreach my $e (@{$fn->{DATA}}) {
+               if (util::has_property($e, "in")) {
+                       ParseElementPrintScalar($e, "r->in.");
+               }
+       }
+       $res .= "\tndr->depth--;\n";
+       $res .= "\t}\n";
+       
+       $res .= "\tif (flags & NDR_OUT) {\n";
+       $res .= "\t\tndr_print_struct(ndr, \"out\", \"$fn->{NAME}\");\n";
+       $res .= "\tndr->depth++;\n";
+       foreach my $e (@{$fn->{DATA}}) {
+               if (util::has_property($e, "out")) {
+                       ParseElementPrintScalar($e, "r->out.");
+               }
+       }
+       if ($fn->{RETURN_TYPE} && $fn->{RETURN_TYPE} ne "void") {
+               $res .= "\tndr_print_$fn->{RETURN_TYPE}(ndr, \"result\", &r->out.result);\n";
+       }
+       $res .= "\tndr->depth--;\n";
+       $res .= "\t}\n";
+       
+       $res .= "\tndr->depth--;\n";
+       $res .= "}\n\n";
+}
+
 
 #####################################################################
 # parse a function
@@ -737,11 +888,11 @@ sub ParseFunctionPush($)
                if (util::has_property($e, "in")) {
                        $e->{PARENT} = $function;
                        if (util::array_size($e)) {
-                               $res .= "\tif (r->in.$e->{NAME}) {\n";
-                               if (!util::is_scalar_type($e->{TYPE})) {
-                                       $res .= "\t\tint ndr_flags = NDR_SCALARS|NDR_BUFFERS;\n";
+                               if (util::need_wire_pointer($e)) {
+                                       $res .= "\tNDR_CHECK(ndr_push_ptr(ndr, r->in.$e->{NAME}));\n";
                                }
-                               ParseArrayPush($e, "r->in.", "ndr_flags");
+                               $res .= "\tif (r->in.$e->{NAME}) {\n";
+                               ParseArrayPush($e, "r->in.", "NDR_SCALARS|NDR_BUFFERS");
                                $res .= "\t}\n";
                        } else {
                                ParseElementPushScalar($e, "r->in.", "NDR_SCALARS|NDR_BUFFERS");
@@ -777,11 +928,13 @@ sub ParseFunctionPull($)
                if (util::has_property($e, "out")) {
                        $e->{PARENT} = $fn;
                        if (util::array_size($e)) {
-                               $res .= "\tif (r->out.$e->{NAME}) {\n";
-                               if (!util::is_scalar_type($e->{TYPE})) {
-                                       $res .= "\t\tint ndr_flags = NDR_SCALARS|NDR_BUFFERS;\n";
+                               if (util::need_wire_pointer($e)) {
+                                       $res .= "\tNDR_CHECK(ndr_pull_uint32(ndr, _ptr_$e->{NAME}));\n";
+                                       $res .= "\tif (_ptr_$e->{NAME}) {\n";
+                               } else {
+                                       $res .= "\tif (r->out.$e->{NAME}) {\n";
                                }
-                               ParseArrayPull($e, "r->out.", "ndr_flags");
+                               ParseArrayPull($e, "r->out.", "NDR_SCALARS|NDR_BUFFERS");
                                $res .= "\t}\n";
                        } else {
                                ParseElementPullScalar($e, "r->out.", "NDR_SCALARS|NDR_BUFFERS");
@@ -819,8 +972,14 @@ sub ParseInterface($)
                    ParseFunctionPull($d);
        }
        foreach my $d (@{$data}) {
-               ($d->{TYPE} eq "TYPEDEF") &&
-                   ParseTypedefPrint($d);
+               if ($d->{TYPE} eq "TYPEDEF" &&
+                   !util::has_property($d->{DATA}, "noprint")) {
+                       ParseTypedefPrint($d);
+               }
+               if ($d->{TYPE} eq "FUNCTION" &&
+                   !util::has_property($d, "noprint")) {
+                       ParseFunctionPrint($d);
+               }
        }
 }
 
@@ -842,6 +1001,10 @@ sub NeededFunction($)
 sub NeededTypedef($)
 {
        my $t = shift;
+       if (util::has_property($t->{DATA}, "public")) {
+               $needed{"pull_$t->{NAME}"} = 1;
+               $needed{"push_$t->{NAME}"} = 1;         
+       }
        if ($t->{DATA}->{TYPE} eq "STRUCT") {
                for my $e (@{$t->{DATA}->{ELEMENTS}}) {
                                if ($needed{"pull_$t->{NAME}"}) {