r6973: Merge new version of pidl into the main SAMBA_4_0 branch.
authorJelmer Vernooij <jelmer@samba.org>
Wed, 25 May 2005 13:50:27 +0000 (13:50 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 18:17:01 +0000 (13:17 -0500)
The main difference in this new version is the extra data structure generated
between the IDL data structure and the NDR parser:

IDL -> NDR -> { ndr_parser, ndr_header, eparser, etc }

This makes the ndr_parser.pm internals much more sane.

Other changes include:

- Remove unnecessary calls with NDR_BUFFERS (for example, GUID doesn't have any buffers, just scalars) as well as some (unnecessary) nested setting of flags.
- Parse array loops in the C code rather then calling ndr_pull_array(). This allows us to have, for example, arrays of pointers or arrays of pointers to arrays, etc..
- Use if() {} rather then if () goto foo; everywhere
- NDR_IN no longer implies LIBNDR_FLAG_REF_ALLOC
- By default, top level pointers are now "ref" (as is the default in
  most other IDL compilers). This can be overridden using the
  default_pointer_top() property.
- initial work on new ethereal parser generators by Alan DeKok and me
- pidl now writes errors in the standard format used by compilers, which
  is parsable by most editors
- ability to warn about the fact that pidl extension(s) have been used,
  useful for making sure IDL files work with other IDL compilers.

oh, and there's probably some other things I can't think of right now..
(This used to be commit 13cf227615f6b9e0e5fa62e59197024410254f01)

58 files changed:
source4/build/pidl/README
source4/build/pidl/com_header.pm
source4/build/pidl/compat.pm [new file with mode: 0644]
source4/build/pidl/dcom_proxy.pm
source4/build/pidl/eparser.pm [deleted file]
source4/build/pidl/eth_header.pm [new file with mode: 0644]
source4/build/pidl/eth_parser.pm [new file with mode: 0644]
source4/build/pidl/idl.pm
source4/build/pidl/idl.yp
source4/build/pidl/ndr.pm
source4/build/pidl/ndr_client.pm
source4/build/pidl/ndr_header.pm
source4/build/pidl/ndr_parser.pm
source4/build/pidl/needed.pm [deleted file]
source4/build/pidl/odl.pm
source4/build/pidl/pidl.pl
source4/build/pidl/test.pm
source4/build/pidl/typelist.pm
source4/build/pidl/validator.pm
source4/librpc/idl/atsvc.idl
source4/librpc/idl/audiosrv.idl
source4/librpc/idl/browser.idl
source4/librpc/idl/dbgidl.idl
source4/librpc/idl/dcom.idl
source4/librpc/idl/dfs.idl
source4/librpc/idl/drsblobs.idl
source4/librpc/idl/drsuapi.idl
source4/librpc/idl/dsbackup.idl
source4/librpc/idl/dssetup.idl
source4/librpc/idl/echo.idl
source4/librpc/idl/efs.idl
source4/librpc/idl/epmapper.idl
source4/librpc/idl/eventlog.idl
source4/librpc/idl/exchange.idl
source4/librpc/idl/initshutdown.idl
source4/librpc/idl/krb5pac.idl
source4/librpc/idl/lsa.idl
source4/librpc/idl/mgmt.idl
source4/librpc/idl/nbt.idl
source4/librpc/idl/netlogon.idl
source4/librpc/idl/oxidresolver.idl
source4/librpc/idl/policyagent.idl
source4/librpc/idl/remact.idl
source4/librpc/idl/rot.idl
source4/librpc/idl/samr.idl
source4/librpc/idl/spoolss.idl
source4/librpc/idl/srvsvc.idl
source4/librpc/idl/svcctl.idl
source4/librpc/idl/trkwks.idl
source4/librpc/idl/winreg.idl
source4/librpc/idl/winsrepl.idl
source4/librpc/idl/wkssvc.idl
source4/librpc/ndr/libndr.h
source4/librpc/ndr/ndr.c
source4/librpc/ndr/ndr_sec.c
source4/librpc/rpc/dcerpc.c
source4/rpc_server/dcerpc_server.c
source4/utils/ndrdump.c

index e0878888408d16a5ee04cef286e45046afe606fc..eac0674153db7f4bb9db81d45604d1c1b22aa419 100644 (file)
@@ -19,8 +19,8 @@ validator.pm  - Validates the parse tree
 
 -- DCE/RPC+NDR --
 ndr_client.pm - Generates client call functions in C using the NDR parser
-eparser.pm - Generates a parser for the ethereal network sniffer by 
-                               applying regexes to the output of parser.pm
+eth_parser.pm - Generates a parser for the ethereal network sniffer
+eth_header.pm - Generates a header for ethereal
 swig.pm        - Generates SWIG interface files (.i)
 ndr_header.pm - Generates a header file with structures
 ndr.pm - Generates pull/push functions for parsing NDR
index 1c7194d85cb4a6c1644faaa26af72a16073df434..95bbc9c720c9a9d1fbb8c3ec5329386f40bebceb 100644 (file)
@@ -14,7 +14,7 @@ sub GetArgumentProtoList($)
 
        foreach my $a (@{$f->{ELEMENTS}}) {
 
-               $res .= ", " . typelist::mapType($a) . " ";
+               $res .= ", " . typelist::mapType($a->{TYPE}) . " ";
 
                my $l = $a->{POINTERS};
                $l-- if ($a->{TYPE} eq "string");
@@ -61,7 +61,7 @@ sub HeaderVTable($)
 
        my $data = $interface->{DATA};
        foreach my $d (@{$data}) {
-               $res .= "\t" . typelist::mapScalarType($d->{RETURN_TYPE}) . " (*$d->{NAME}) (struct $interface->{NAME} *d, TALLOC_CTX *mem_ctx" . GetArgumentProtoList($d) . ");\\\n" if ($d->{TYPE} eq "FUNCTION");
+               $res .= "\t" . typelist::mapType($d->{RETURN_TYPE}) . " (*$d->{NAME}) (struct $interface->{NAME} *d, TALLOC_CTX *mem_ctx" . GetArgumentProtoList($d) . ");\\\n" if ($d->{TYPE} eq "FUNCTION");
        }
        $res .= "\n";
        $res .= "struct $interface->{NAME}_vtable {\n";
diff --git a/source4/build/pidl/compat.pm b/source4/build/pidl/compat.pm
new file mode 100644 (file)
index 0000000..3ab94b7
--- /dev/null
@@ -0,0 +1,55 @@
+###################################################
+# IDL Compatibility checker
+# Copyright jelmer@samba.org 2005
+# released under the GNU GPL
+
+package IDLCompat;
+
+use strict;
+
+my($res);
+
+sub warning($$)
+{
+       my $l = shift;
+       my $m = shift;
+
+       print "$l->{FILE}:$l->{LINE}:$m\n";
+}
+
+sub CheckInterface($)
+{
+       my $if = shift;
+       if (util::has_property($if, "pointer_default_top")) {
+               warning($if, "pointer_default_top() is pidl-specific");
+       }
+
+       foreach my $x (@{$if->{DATA}}) {
+               if ($x->{TYPE} eq "DECLARE") {
+                       warning($if, "the declare keyword is pidl-specific");
+                       next;
+               }
+
+               if ($x->{TYPE} eq "TYPEDEF") {
+                       if ($x->{DATA}->{TYPE} eq "UNION") {
+                               if (util::has_property($x, "nodiscriminant")) {
+                                       warning($x, "nodiscriminant property is pidl-specific");
+                               }
+                       }
+               }
+       }
+}
+
+sub Check($)
+{
+       my $pidl = shift;
+       my $res = "";
+
+       foreach my $x (@{$pidl}) {
+               CheckInterface($x) if ($x->{TYPE} eq "INTERFACE");
+       }
+
+       return $res;
+}
+
+1;
index 8cc55476802cb716380b86c856beb06abb1b01da..3d460645484a0ae7919621d08252085f9cac1e4e 100644 (file)
@@ -173,7 +173,7 @@ sub RegistrationFunction($$)
                next if $interface->{TYPE} ne "INTERFACE";
                next if not util::has_property($interface, "object");
 
-               my $data = $interface->{INHERITED_DATA};
+               my $data = $interface->{DATA};
                my $count = 0;
                foreach my $d (@{$data}) {
                        if ($d->{TYPE} eq "FUNCTION") { $count++; }
diff --git a/source4/build/pidl/eparser.pm b/source4/build/pidl/eparser.pm
deleted file mode 100644 (file)
index 23ff8e7..0000000
+++ /dev/null
@@ -1,865 +0,0 @@
-###################################################
-# Samba4 parser generator for IDL structures
-# Copyright tridge@samba.org 2000-2003
-# Copyright tpot@samba.org 2001,2004-2005
-# released under the GNU GPL
-
-package IdlEParser;
-
-use ndr_parser;
-use strict;
-
-# the list of needed functions
-my %needed;
-my %bitmaps;
-
-my $module;
-my $if_uuid;
-my $if_version;
-my $if_endpoints;
-
-sub pidl($)
-{
-       print OUT shift;
-}
-
-#####################################################################
-# a list of annotations 
-
-my $nopull_typedefs = {
-#    "policy_handle" => "1",
-};
-
-#####################################################################
-# work out is a parse function should be declared static or not
-sub fn_prefix($)
-{
-       my $fn = shift;
-       if ($fn->{TYPE} eq "TYPEDEF") {
-               if (util::has_property($fn, "public")) {
-                       return "";
-               }
-       }
-
-       if ($fn->{TYPE} eq "FUNCTION") {
-               if (util::has_property($fn, "public")) {
-                       return "";
-               }
-       }
-       return "static ";
-}
-
-
-#####################################################################
-# parse a function
-sub ParseFunctionPull($)
-{ 
-       my($fn) = shift;
-       my $static = fn_prefix($fn);
-
-       # request function
-       pidl "int $fn->{NAME}_rqst(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, guint8 *drep)\n{\n";
-
-       pidl "\tstruct pidl_pull *ndr = pidl_pull_init(tvb, offset, pinfo, drep);\n";
-       pidl "\tstruct $fn->{NAME} *r = talloc(NULL, struct $fn->{NAME});\n";
-       pidl "\tpidl_tree ptree;\n\n";
-
-       pidl "\tptree.proto_tree = tree;\n";
-       pidl "\tptree.subtree_list = NULL;\n\n";
-
-       pidl "\tndr_pull_$fn->{NAME}(ndr, NDR_IN, &ptree, r);\n";
-
-       pidl "\n\treturn ndr->offset;\n";
-       pidl "}\n\n";
-
-       # response function
-       pidl "int $fn->{NAME}_resp(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, guint8 *drep)\n{\n";
-
-       pidl "\tstruct pidl_pull *ndr = pidl_pull_init(tvb, offset, pinfo, drep);\n";
-       pidl "\tstruct $fn->{NAME} *r = talloc(NULL, struct $fn->{NAME});\n";
-       pidl "\tpidl_tree ptree;\n\n";
-
-       pidl "\tptree.proto_tree = tree;\n";
-       pidl "\tptree.subtree_list = NULL;\n\n";
-
-       pidl "\tndr_pull_$fn->{NAME}(ndr, NDR_OUT, &ptree, r);\n";
-
-       pidl "\n\treturn ndr->offset;\n";
-       pidl "}\n\n";
-}
-
-#####################################################################
-# produce a function call table
-sub FunctionTable($)
-{
-       my($interface) = shift;
-       my($data) = $interface->{DATA};
-
-       pidl "static dcerpc_sub_dissector dcerpc_dissectors[] = {\n";
-       my $num = 0;
-       foreach my $d (@{$data}) {
-               if ($d->{TYPE} eq "FUNCTION") {
-                   # Strip module name from function name, if present
-                   my($n) = $d->{NAME};
-                   $n = substr($d->{NAME}, length($module) + 1),
-                       if $module eq substr($d->{NAME}, 0, length($module));
-                   pidl "\t{ $num, \"$n\",\n";
-                   pidl "\t\t$d->{NAME}_rqst,\n";
-                   pidl "\t\t$d->{NAME}_resp },\n";
-                   $num++;
-               }
-       }
-       pidl "};\n\n";
-}
-
-sub type2ft($)
-{
-    my($t) = shift;
-    return "FT_UINT$1" if $t =~ /uint(8|16|32|64)/;
-    return "FT_INT$1" if $t =~ /int(8|16|32|64)/;
-    return "FT_UINT64", if $t eq "HYPER_T" or $t eq "NTTIME"
-       or $t eq "NTTIME_1sec" or $t eq "NTTIME_hyper";
-    
-    # Type is an enum
-
-    return "FT_UINT16";
-}
-
-# Determine the display base for an element
-
-sub elementbase($)
-{
-    my($e) = shift;
-
-    if (my $base = util::has_property($e, "display")) {
-       return "BASE_" . uc($base);
-    }
-    return "BASE_DEC", if $e->{TYPE} eq "ENUM";
-    return "BASE_DEC", if $e->{TYPE} =~ /u?int(8|16|32|64)/;
-    return "BASE_DEC", if $e->{TYPE} eq "NTTIME" or $e->{TYPE} eq "HYPER_T";
-
-    # Probably an enum
-
-    return "BASE_DEC";
-}
-
-# Convert a IDL structure field name (e.g access_mask) to a prettier
-# string like 'Access Mask'.
-
-sub field2name($)
-{
-    my($field) = shift;
-
-    $field =~ s/_/ /g;         # Replace underscores with spaces
-    $field =~ s/(\w+)/\u\L$1/g;        # Capitalise each word
-    
-    return $field;
-}
-
-sub NeededFunction($)
-{
-       my $fn = shift;
-
-       $needed{"pull_$fn->{NAME}"} = 1;
-
-       # Add entries for function arguments
-
-       foreach my $e (@{$fn->{ELEMENTS}}) {
-
-               $e->{PARENT} = $fn;
-               $needed{"pull_$e->{TYPE}"} = 1;
-
-               if (NdrParser::is_scalar_type($e->{TYPE})) {
-
-                   if (defined($e->{ARRAY_LEN}) or 
-                       util::has_property($e, "size_is")) {
-
-                       # Array of scalar types
-
-                       $needed{"hf_$fn->{NAME}_$e->{NAME}_array"} = {
-                           'name' => field2name($e->{NAME}),
-                           'type' => $e->{TYPE},
-                           'ft'   => "FT_BYTES",
-                           'base' => elementbase($e)
-                           };
-
-                   } else {
-
-                       $needed{"hf_$fn->{NAME}_$e->{NAME}"} = {
-                       'name' => field2name($e->{NAME}),
-                       'type' => $e->{TYPE},
-                       'ft'   => type2ft($e->{TYPE}),
-                       'base' => elementbase($e)
-                       };
-
-                   }
-
-                   $e->{PARENT} = $fn;
-
-               } else {
-                   $needed{"ett_$e->{TYPE}"} = 1;
-               }
-       }
-
-       # Add entry for return value
-
-       $needed{"hf_$fn->{NAME}_result"} = {
-           'name' => field2name('result'),
-           'type' => $fn->{RETURN_TYPE},
-           'ft' => type2ft($fn->{RETURN_TYPE}),
-           'base' => elementbase($fn)
-       };
-}
-
-sub bitmapbase($)
-{
-    my $e = shift;
-
-    return "16", if util::has_property($e->{DATA}, "bitmap16bit");
-    return "8", if util::has_property($e->{DATA}, "bitmap8bit");
-
-    return "32";
-}
-
-sub NeededTypedef($)
-{
-       my $t = shift;
-
-       if (util::has_property($t, "public")) {
-               $needed{"pull_$t->{NAME}"} = 1;
-       }
-
-       if ($t->{DATA}->{TYPE} eq "STRUCT") {
-
-               for my $e (@{$t->{DATA}->{ELEMENTS}}) {
-
-                       $e->{PARENT} = $t->{DATA};
-
-                       if ($needed{"pull_$t->{NAME}"}) {
-                               $needed{"pull_$e->{TYPE}"} = 1;
-                       }
-
-                       if (NdrParser::is_scalar_type($e->{TYPE})) {
-
-                               if (defined($e->{ARRAY_LEN}) or 
-                               util::has_property($e, "size_is")) {
-
-                                       # Arrays of scalar types are FT_BYTES
-
-                                       $needed{"hf_$t->{NAME}_$e->{NAME}_array"} = {
-                                               'name' => field2name($e->{NAME}),
-                                               'type' => $e->{TYPE},
-                                               'ft'   => "FT_BYTES",
-                                               'base' => elementbase($e)
-                                       };
-
-                               } else {
-
-                                       $needed{"hf_$t->{NAME}_$e->{NAME}"} = {
-                                               'name' => field2name($e->{NAME}),
-                                               'type' => $e->{TYPE},
-                                               'ft'   => type2ft($e->{TYPE}),
-                                               'base' => elementbase($e)
-                                       };
-                               }
-
-                               $e->{PARENT} = $t->{DATA};
-
-                               if ($needed{"pull_$t->{NAME}"}) {
-                                       $needed{"pull_$e->{TYPE}"} = 1;
-                               }
-
-                       } else {
-                               $needed{"ett_$e->{TYPE}"} = 1;
-                       }
-               }
-       }
-
-       if ($t->{DATA}->{TYPE} eq "UNION") {
-               for my $e (@{$t->{DATA}->{ELEMENTS}}) {
-
-                       $e->{PARENT} = $t->{DATA};
-
-                       if ($needed{"pull_$t->{NAME}"}) {
-                               $needed{"pull_$e->{TYPE}"} = 1;
-                       }
-
-                       $needed{"ett_$e->{TYPE}"} = 1;
-               }
-
-               $needed{"ett_$t->{NAME}"} = 1;
-       }
-
-       if ($t->{DATA}->{TYPE} eq "ENUM") {
-
-               $needed{"hf_$t->{NAME}"} = {
-                       'name' => field2name($t->{NAME}),
-                       'ft' => 'FT_UINT16',
-                       'base' => 'BASE_DEC',
-                       'strings' => "VALS($t->{NAME}_vals)"
-               };
-       }
-
-       if ($t->{DATA}->{TYPE} eq "BITMAP") {
-
-               $bitmaps{$t->{NAME}} = $t;
-
-               foreach my $e (@{$t->{DATA}{ELEMENTS}}) {
-                       $e =~ /^(.*?) \( (.*?) \)$/;
-                       $needed{"hf_$t->{NAME}_$1"} = {
-                               'name' => "$1",
-                               'ft' => "FT_BOOLEAN",
-                               'base' => bitmapbase($t),
-                               'bitmask' => "$2"
-                       };
-               }
-
-               $needed{"ett_$t->{NAME}"} = 1;
-       }
-}
-
-#####################################################################
-# work out what parse functions are needed
-sub BuildNeeded($)
-{
-       my($interface) = shift;
-
-       my($data) = $interface->{DATA};
-
-       foreach my $d (@{$data}) {
-               ($d->{TYPE} eq "FUNCTION") && 
-                   NeededFunction($d);
-       }
-
-       foreach my $d (reverse @{$data}) {
-               ($d->{TYPE} eq "TYPEDEF") &&
-                   NeededTypedef($d);
-       }
-}
-
-#####################################################################
-# parse the interface definitions
-sub ModuleHeader($)
-{
-    my($h) = shift;
-
-    $if_uuid = $h->{PROPERTIES}->{uuid};
-    $if_version = $h->{PROPERTIES}->{version};
-    $if_endpoints = $h->{PROPERTIES}->{endpoints};
-}
-
-#####################################################################
-# Generate a header file that contains function prototypes for 
-# structs and typedefs.
-sub ParseHeader($$)
-{
-       my($idl) = shift;
-       my($filename) = shift;
-
-       open(OUT, ">$filename") || die "can't open $filename";    
-
-       pidl "/* parser auto-generated by pidl */\n\n";
-
-       foreach my $x (@{$idl}) {
-           if ($x->{TYPE} eq "INTERFACE") { 
-               foreach my $d (@{$x->{DATA}}) {
-
-                   # Make prototypes for [public] structures and
-                   # unions.
-
-                   if ($d->{TYPE} eq "TYPEDEF" and 
-                       util::has_property($d, "public")) {
-                       
-                       if ($d->{DATA}{TYPE} eq "STRUCT") { 
-                           pidl "void ndr_pull_$d->{NAME}(struct ndr_pull *ndr, int ndr_flags, proto_tree *tree, struct $d->{NAME} *r);\n\n";
-                       }
-
-                       if ($d->{DATA}{TYPE} eq "UNION") {
-                           pidl "void ndr_pull_$d->{NAME}(struct ndr_pull *ndr, int ndr_flags, proto_tree *tree, union $d->{NAME} *r, uint16 level);\n\n";
-                       }
-                   }
-               }
-           }
-       }
-
-       close(OUT);
-}
-
-#####################################################################
-# generate code to parse an enum
-
-sub ParseEnum($)
-{
-    my ($e) = shift;
-
-    pidl "static const value_string $e->{PARENT}{NAME}_vals[] =\n";
-    pidl "{\n";
-
-    foreach my $x (@{$e->{ELEMENTS}}) {
-       $x =~ /([^=]*)=(.*)/;
-       pidl "\t{ $1, \"$1\" },\n";
-    }
-    
-    pidl "};\n\n";
-}
-
-#####################################################################
-# rewrite autogenerated header file
-sub RewriteHeader($$$)
-{
-    my($idl) = shift;
-    my($input) = shift;
-    my($output) = shift;
-
-       NdrParser::Load($idl);
-
-    %needed = ();
-
-    # Open files
-
-    open(IN, "<$input") || die "can't open $input for reading";
-    open(OUT, ">$output") || die "can't open $output for writing";    
-   
-    # Read through file
-
-    while(<IN>) {
-
-       # Not interested in ndr_push or ndr_print routines as they
-       # define structures we aren't interested in.
-
-       s/^NTSTATUS ndr_push.*?;\n//smg;
-       s/^void ndr_print.*?;\n//smg;
-
-       # Get rid of async send and receive function.
-
-       s/^NTSTATUS dcerpc_.*?;//smg;
-       s/^struct rpc_request.*?;//smg;
-
-       # Rewrite librpc includes
-
-       s/^\#include\ \"librpc\/gen_ndr\/ndr_(.*?).h\"$
-           /\#include \"packet-dcerpc-$1.h\"/smgx;
-
-       # Rename struct ndr_pull to struct pidl_pull
-
-       s/struct ndr_pull \*ndr/struct pidl_pull \*ndr/smg;
-
-       # Change prototypes for public functions
-
-       s/(struct pidl_pull \*ndr, int ndr_flags)/$1, pidl_tree *tree/smg;
-
-       # Bitmaps
-
-       s/int ndr_flags, (pidl_tree \*tree), (uint32_t \*r\);)/$1, int hf, $2/smg;
-
-       pidl $_;
-    }
-
-    close(OUT);   
-}
-
-#####################################################################
-# rewrite autogenerated C file
-sub RewriteC($$$)
-{
-    my($idl) = shift;
-    my($input) = shift;
-    my($output) = shift;
-
-       NdrParser::Load($idl);
-
-    # Open files
-
-    open(IN, "<$input") || die "can't open $input for reading";
-    open(OUT, ">$output") || die "can't open $output for writing";    
-    
-    # Get name of module
-
-    foreach my $x (@{$idl}) {
-       if ($x->{TYPE} eq "INTERFACE") { 
-           ModuleHeader($x);
-           $module = $x->{NAME};
-           BuildNeeded($x);
-       }
-    }
-
-    pidl "#include \"eparser.h\"\n\n";
-
-    pidl "extern const value_string NT_errors[];\n\n";
-
-    # Declarations for hf variables
-
-    pidl "static int hf_opnum = -1;\n";
-    pidl "static int hf_ptr = -1;\n";
-    pidl "static int hf_array_size = -1;\n";
-    pidl "static int hf_result_NTSTATUS = -1;\n";
-
-    pidl "\n";
-
-    foreach my $y (keys(%needed)) {
-       pidl "static int $y = -1;\n", if $y =~ /^hf_/;
-    }
-
-    pidl "\n";
-
-    foreach my $y (keys(%needed)) {
-       pidl "static gint $y = -1;\n", if $y =~ /^ett_/;
-    }
-
-    pidl "\n";
-
-    # Read through file
-
-    my $cur_fn = "";
-
-    while(<IN>) {
-
-       #
-        # Regexps to do a first pass at removing stuff we aren't
-       # interested in for ethereal parsers.
-       #
-
-       next, if /^\#include \"includes.h\"/;
-
-       # Rewrite includes to packet-dcerpc-foo.h instead of ndr_foo.h
-
-       s/^\#include \".*?ndr_(.*?).h\"$/\#include \"packet-dcerpc-$1.h\"/smg;
-
-       if (/\.h\"$/) {
-           pidl $_;
-           foreach my $x (@{$idl}) {
-               if ($x->{TYPE} eq "INTERFACE") { 
-                   foreach my $y (@{$x->{INHERITED_DATA}}) {
-                       if ($y->{TYPE} eq "TYPEDEF") {
-                           ParseEnum($y->{DATA}), if $y->{DATA}{TYPE} eq "ENUM";
-                       }
-                   }
-               }
-           }
-           next;
-       }
-
-       # Remove the NDR_CHECK() macro calls.  Ethereal take care of
-       # this for us as part of the tvbuff_t structure.
-
-       s/NDR_CHECK\((.*)\)/$1/g;
-
-       # We're not interested in ndr_{print,push,size} functions so
-       # just delete them.
-
-       next, if /^(static )?NTSTATUS ndr_push/ .. /^}/;
-        next, if /^void ndr_print/ .. /^}/;
-        next, if /^size_t ndr_size/ .. /^}/;
-
-       # get rid of the init functions
-       next, if /^NTSTATUS dcerpc_ndr_\w+_init/ .. /^}/;
-
-       # Get rid of dcerpc interface structures and functions since
-       # they are also not very interesting.
-
-        next, if /^static const struct dcerpc_interface_call/ .. /^};/;
-        next, if /^static const char \* const [a-z]+_endpoint_strings/ ../^};/;
-        next, if /^static const struct dcerpc_endpoint_list/ .. /^};/;
-        next, if /^const struct dcerpc_interface_table/ .. /^};/;
-        next, if /^static NTSTATUS dcerpc_ndr_[a-z]+_init/ .. /^}/;
-        next, if /^NTSTATUS dcerpc_[a-z]+_init/ .. /^}/;
-
-        #
-        # Remember which structure or function we are processing.
-        #
-
-        $cur_fn = $1, if /NTSTATUS ndr_pull_(.*?)\(struct/;
-
-        # Skip functions we have marked as nopull
-
-        my $skip_fn = 0;
-
-        foreach my $f (keys(%{$nopull_typedefs})) {
-           $skip_fn = 1, if $cur_fn eq $f;
-       }
-
-        $cur_fn = "", if /^}/;
-
-        next, if $skip_fn;
-
-       #
-       # OK start wrapping the ndr_pull functions that actually
-       # implement the NDR decoding routines.  This mainly consists
-       # of adding a couple of parameters to each function call.
-        #
-
-       # Add proto tree and name argument to ndr_pull_unique_ptr() calls.
-
-       s/(ndr_pull_unique_ptr\(ndr,\ (&_ptr_([^\)]*?))\);)
-           /ndr_pull_ptr(ndr, tree, "$3", $2);/smgx;
-
-       # Wrap ndr_pull_array_size() and ndr_pull_array_length()
-       # functions.  Add leading space in front of first parameter so
-       # we won't get caught by later regexps.
-
-       s/(ndr_pull_array_(size|length)\(ndr,\ ([^\)]*?)\);)
-           /ndr_pull_array_$2( ndr, tree, $3);/smgx;
-
-       # Add tree argument to ndr_pull_array() and
-       # ndr_pull_array_foo() calls.
-
-       s/(ndr_pull_array\(
-          ndr,\ 
-          ([^,]*?),\                                # NDR_SCALARS etc
-          (\(void\ \*\*\)r->(in|out|)\.?([^,]*?)),\ # Pointer to array entries
-          ([^\)].*?)\);)                            # All other arguments
-           /ndr_pull_array( ndr, $2, tree, $3, $6);/smgx;
-
-       s/(ndr_pull_array_([^\(]*?)\(
-          ndr,\ 
-          ([^,]*?),\                               # NDR_SCALARS etc
-          (r->((in|out).)?([^,]*?)),\              # Pointer to array elements
-          (.*?)\);)                                # Number of elements
-           /ndr_pull_array_$2( ndr, $3, tree, hf_${cur_fn}_$7_array, $4, $8);/smgx;
-       # Save ndr_pull_relative_ptr{1,2}() calls from being wrapped by the
-       # proceeding regexp by adding a leading space.
-
-       s/ndr_pull_(relative_ptr1|relative_ptr2)\((.*?)\);/
-           ndr_pull_$1( $2);/smgx;
-
-       # Enums
-
-        s/(^static\ NTSTATUS\ ndr_pull_(.+?),\ int\ ndr_flags,\ (enum\ .+?)\))
-           /static NTSTATUS ndr_pull_$2, pidl_tree *tree, int hf, $3)/smgx;
-       s/uint(8|16|32) v;/uint$1_t v;/smg;
-       s/(ndr_pull_([^\(]+?)\(ndr,\ NDR_[^,]*,\ &_level\);)
-           /ndr_pull_$2(ndr, tree, hf_${cur_fn}_level, &_level);/smgx;
-
-       # Bitmaps
-
-        s/(^(static\ )?NTSTATUS\ ndr_pull_(.+?),\ int\ ndr_flags,\ uint(8|16|32)_t\ \*r\))
-           /NTSTATUS ndr_pull_$3, pidl_tree *tree, int hf, uint$4_t *r)/smgx;
-
-        if (/ndr_pull_([^\)]*?)\(ndr,\ NDR_[^,]*,\ &v\);/) {
-
-           s/(ndr_pull_([^\)]*?)\(ndr,\ (NDR_[^,]*?),\ &v\);)
-               /ndr_pull_$2(ndr, tree, hf, &v);/smgx;
-
-           pidl $_;
-
-           if (defined($bitmaps{$cur_fn})) {
-               pidl "\t{\n\t\tproto_tree *subtree = NULL;\n\n";
-               pidl "\t\tif (tree->proto_tree)\n\t\t\tsubtree = proto_item_add_subtree(tree->proto_tree->last_child, ett_$cur_fn);\n\n";
-               foreach my $e (@{$bitmaps{$cur_fn}->{DATA}{ELEMENTS}}) {
-                   $e =~ /^(.*?) \( (.*?) \)$/;
-                   pidl "\t\tproto_tree_add_boolean(subtree, hf_${cur_fn}_$1, ndr->tvb, ndr->offset - sizeof(v), sizeof(v), v);\n";
-               }
-               pidl "\t}\n";
-           }
-
-           next;
-       }
-
-       # Call ethereal wrappers for pull of scalar values in
-       # structures and functions, e.g
-       #
-       # ndr_pull_uint32(ndr, &r->in.access_mask);
-       # ndr_pull_uint32(ndr, &r->idx);
-
-        if (/(ndr_pull_([^\)]*?)\(ndr, NDR_[^,]*?, (&?r->((in|out)\.)?([^\)]*?))\);)/ and NdrParser::is_scalar_type($2)) {
-
-           my $pull_type = "${cur_fn}_$6";
-
-           if (defined($needed{"hf_$2"})) {
-               $pull_type = "$2";
-           }
-
-           s/(ndr_pull_([^\)]*?)\(
-                  ndr,\ 
-                  NDR_[^,]*?,\ 
-                  (&?r->((in|out)\.)?         # Function args contain leading junk
-               ([^\)]*?))                 # Element name
-              \);)          
-               /ndr_pull_$2(ndr, tree, hf_$pull_type, $3);/smgx;
-       }
-
-       # Add tree and hf argument to pulls of "internal" scalars like
-       # array sizes, levels, etc.
-
-       s/(ndr_pull_(uint32|uint16)\(
-          ndr,\  
-          NDR_[^,]*?,\ 
-          (&_([^\)]*?))        # Internal arg names have leading underscore
-          \);)
-           /ndr_pull_$2(ndr, tree, hf_$4, $3);/smgx;
-
-       # Add subtree argument to calls dissecting structures/unions, e.g
-       #
-       # ndr_pull_string(ndr, NDR_SCALARS|NDR_BUFFERS, &r->command);
-       # ndr_pull_atsvc_enum_ctr(ndr, NDR_SCALARS|NDR_BUFFERS, r->in.ctr);
-
-       # Three argument version is for structures
-
-    if (/ndr_pull_([^\)]*?)\(ndr, (NDR_[^,]*?), ([^,]*?)\);/ and 
-                       not NdrParser::is_scalar_type($1)) {
-               s/(ndr_pull_([^\)]*?)\(
-              ndr,\ 
-              (NDR_[^,]*?),\ 
-              (&?r->((in|out)\.)?([^\(].*?))\);)
-               /ndr_pull_$2(ndr, $3, get_subtree(tree, \"$7\", ndr, ett_$2), $4);
-           /smgx;
-       }
-
-    # Four argument version if for unions
-    if (/ndr_pull_([^\)]*?)\(ndr, (NDR_[SB][^,]*?), ([^,]*?), ([^,]*?)\);/ and
-                       not NdrParser::is_scalar_type($1)) {
-           s/(ndr_pull_([^\)]*?)\(
-              ndr,\ 
-              (NDR_[^,]*?),\ 
-              (&?r->((in|out)\.)?([^\(].*?))\);)
-               /ndr_pull_$2(ndr, $3, get_subtree(tree, \"$2\", ndr, ett_$2), $4);
-           /smgx;
-       }
-
-       # Add proto_tree parameter to pull function prototypes, e.g
-       #
-       # static NTSTATUS ndr_pull_atsvc_JobInfo(struct ndr_pull *ndr, 
-       #         int ndr_flags, struct atsvc_JobInfo *r)
-
-       s/^((static\ )?NTSTATUS\ ndr_pull_([^\(]*?)\(
-           struct\ ndr_pull\ \*ndr,\ 
-           int\ (ndr_)?flags)
-           /$1, proto_tree \*tree/smgx;
-
-       # Add proto_tree parameter to ndr_pull_subcontext_flags_fn()
-
-        s/(ndr_pull_subcontext_flags_fn\(ndr)(.*?);/$1, tree$2;/smg;
-
-       # Get rid of ndr_pull_error() calls for the moment. Ethereal
-       # should take care of buffer overruns and inconsistent array
-       # sizes for us but it would be nice to have some error text in
-       # the dissection.
-
-       s/(return ndr_pull_error([^;]*?);)/return NT_STATUS_OK; \/\/ $1/smg;
-
-       # Rename proto_tree args to pidl_tree
-
-       s/(int (ndr_)?flags), proto_tree \*tree/$1, pidl_tree \*tree/smg;
-
-       # Rename struct ndr_pull to struct pidl_pull
-
-       s/struct ndr_pull \*ndr/struct pidl_pull \*ndr/smg;
-
-       # Fix some internal variable declarations
-
-        s/(u?)int(8|16|32) _level;/$1int$2_t _level;/smg;
-        s/ndr_pull_([^\(]*)\(ndr,\ tree,\ hf_level,\ &_level\);
-            /ndr_pull_$1(ndr, tree, hf_level_$1, &_level);/smgx;
-
-        # Set the end of a structure
-       
-        s/(ndr_pull_struct_end.*)/$1\tproto_item_set_end(tree->proto_tree, ndr->tvb, ndr->offset);\n/smg;
-                               
-       pidl $_;
-    }
-
-    # Function call table
-
-    foreach my $x (@{$idl}) {
-       if ($x->{TYPE} eq "INTERFACE") { 
-           foreach my $y (@{$x->{"INHERITED_DATA"}}) {
-               ($y->{TYPE} eq "FUNCTION") && ParseFunctionPull($y);
-           }
-
-           FunctionTable($x);
-       }
-    }
-
-    # Ethereal protocol registration
-
-    pidl "int proto_dcerpc_pidl_$module = -1;\n\n";
-
-    pidl "static gint ett_dcerpc_$module = -1;\n\n";
-
-    if (defined($if_uuid)) {
-
-       pidl "static e_uuid_t uuid_dcerpc_$module = {\n";
-       pidl "\t0x" . substr($if_uuid, 1, 8);
-       pidl ", 0x" . substr($if_uuid, 10, 4);
-       pidl ", 0x" . substr($if_uuid, 15, 4) . ",\n";
-       pidl "\t{ 0x" . substr($if_uuid, 20, 2);
-       pidl ", 0x" . substr($if_uuid, 22, 2);
-       pidl ", 0x" . substr($if_uuid, 25, 2);
-       pidl ", 0x" . substr($if_uuid, 27, 2);
-       pidl ", 0x" . substr($if_uuid, 29, 2);
-       pidl ", 0x" . substr($if_uuid, 31, 2);
-       pidl ", 0x" . substr($if_uuid, 33, 2);
-       pidl ", 0x" . substr($if_uuid, 35, 2) . " }\n";
-       pidl "};\n\n";
-    }
-
-    if (defined($if_version)) {
-       pidl "static guint16 ver_dcerpc_$module = " . $if_version . ";\n\n";
-    }
-
-    pidl "void proto_register_dcerpc_pidl_$module(void)\n";
-    pidl "{\n";
-
-    pidl "\tstatic hf_register_info hf[] = {\n";
-    pidl "\t{ &hf_opnum, { \"Operation\", \"$module.opnum\", FT_UINT16, BASE_DEC, NULL, 0x0, \"Operation\", HFILL }},\n";
-       pidl "\t{ &hf_result_NTSTATUS, { \"Return code\", \"$module.rc\", FT_UINT32, BASE_HEX, VALS(NT_errors), 0x0, \"Return status code\", HFILL }},\n";
-    pidl "\t{ &hf_ptr, { \"Pointer\", \"$module.ptr\", FT_UINT32, BASE_HEX, NULL, 0x0, \"Pointer\", HFILL }},\n";
-
-    foreach my $x (keys(%needed)) {
-       next, if !($x =~ /^hf_/);
-       pidl "\t{ &$x,\n";
-       $needed{$x}{strings} = "NULL", if !defined($needed{$x}{strings});
-       $needed{$x}{bitmask} = "0", if !defined($needed{$x}{bitmask});
-       pidl "\t  { \"$needed{$x}{name}\", \"$x\", $needed{$x}{ft}, $needed{$x}{base}, $needed{$x}{strings}, $needed{$x}{bitmask}, \"$x\", HFILL }},\n";
-    }
-
-    pidl "\t};\n\n";
-
-    pidl "\tstatic gint *ett[] = {\n";
-    pidl "\t\t&ett_dcerpc_$module,\n";
-    foreach my $x (keys(%needed)) {
-       pidl "\t\t&$x,\n", if $x =~ /^ett_/;
-    }
-    pidl "\t};\n\n";
-    
-    if (defined($if_uuid)) {
-
-       # These can be changed to non-pidl names if the old dissectors
-       # in epan/dissctors are deleted.
-
-       my $name = uc($module) . " (pidl)";
-       my $short_name = "pidl_$module";
-       my $filter_name = "pidl_$module";
-
-       pidl "\tproto_dcerpc_pidl_$module = proto_register_protocol(\"$name\", \"$short_name\", \"$filter_name\");\n\n";
-
-       pidl "\tproto_register_field_array(proto_dcerpc_pidl_$module, hf, array_length (hf));\n";
-       pidl "\tproto_register_subtree_array(ett, array_length(ett));\n";
-
-       pidl "}\n\n";
-
-       pidl "void proto_reg_handoff_dcerpc_pidl_$module(void)\n";
-       pidl "{\n";
-       pidl "\tdcerpc_init_uuid(proto_dcerpc_pidl_$module, ett_dcerpc_$module, \n";
-       pidl "\t\t&uuid_dcerpc_$module, ver_dcerpc_$module, \n";
-       pidl "\t\tdcerpc_dissectors, hf_opnum);\n";
-       pidl "}\n";
-
-    } else {
-
-       pidl "\tint proto_dcerpc;\n\n";
-       pidl "\tproto_dcerpc = proto_get_id_by_filter_name(\"dcerpc\");\n";
-       pidl "\tproto_register_field_array(proto_dcerpc, hf, array_length(hf));\n";
-       pidl "\tproto_register_subtree_array(ett, array_length(ett));\n";
-
-       pidl "}\n";
-
-    }
-
-    close(OUT);   
-}
-
-1;
diff --git a/source4/build/pidl/eth_header.pm b/source4/build/pidl/eth_header.pm
new file mode 100644 (file)
index 0000000..f0a5778
--- /dev/null
@@ -0,0 +1,102 @@
+###################################################
+# create C header files for an IDL structure
+# Copyright tridge@samba.org 2000
+# Copyright jelmer@samba.org 2005
+# released under the GNU GPL
+
+package EthHeader;
+
+use strict;
+use typelist;
+
+my($res);
+my($tab_depth);
+
+sub pidl ($)
+{
+       $res .= shift;
+}
+
+sub tabs()
+{
+       for (my($i)=0; $i < $tab_depth; $i++) {
+               pidl "\t";
+       }
+}
+
+#####################################################################
+# prototype a typedef
+sub HeaderTypedefProto($)
+{
+    my($d) = shift;
+
+    my $tf = EthParser::get_typefamily($d->{DATA}{TYPE});
+
+    return unless util::has_property($d, "public");
+
+    unless (util::has_property($d, "nopull")) {
+               pidl "dcerpc_dissect_fnct_t $d->{NAME};\n";
+    }
+}
+
+#####################################################################
+# parse a const
+sub HeaderConst($)
+{
+    my($const) = shift;
+    if (!defined($const->{ARRAY_LEN})) {
+       pidl "#define $const->{NAME}\t( $const->{VALUE} )\n";
+    } else {
+       pidl "#define $const->{NAME}\t $const->{VALUE}\n";
+    }
+}
+
+my %headerstructs = ();
+
+#####################################################################
+# parse the interface definitions
+sub HeaderInterface($)
+{
+    my($interface) = shift;
+
+    my $count = 0;
+
+    pidl "#ifndef _HEADER_NDR_$interface->{NAME}\n";
+    pidl "#define _HEADER_NDR_$interface->{NAME}\n\n";
+
+    if (defined $interface->{PROPERTIES}->{depends}) {
+           my @d = split / /, $interface->{PROPERTIES}->{depends};
+           foreach my $i (@d) {
+                   pidl "#include \"packet-dcerpc-$i\.h\"\n";
+           }
+    }
+
+       foreach my $d (@{$interface->{CONSTS}}) {
+           HeaderConst($d);
+    }
+
+    foreach my $d (@{$interface->{TYPEDEFS}}) {
+           HeaderTypedefProto($d);
+       }
+
+    pidl "#endif /* _HEADER_NDR_$interface->{NAME} */\n";
+}
+
+#####################################################################
+# parse a parsed IDL into a C header
+sub Parse($)
+{
+    my($idl) = shift;
+    $tab_depth = 0;
+
+       $res = "";
+    pidl "/* header auto-generated by pidl */\n\n";
+    foreach my $x (@{$idl}) {
+           if ($x->{TYPE} eq "INTERFACE") {
+                   HeaderInterface($x);
+           }
+    }
+    return $res;
+}
+
+1;
diff --git a/source4/build/pidl/eth_parser.pm b/source4/build/pidl/eth_parser.pm
new file mode 100644 (file)
index 0000000..a2e1bf0
--- /dev/null
@@ -0,0 +1,1410 @@
+##################################################
+# Samba4 NDR parser generator for IDL structures
+# Copyright tridge@samba.org 2000-2003
+# Copyright tpot@samba.org 2001
+# Copyright jelmer@samba.org 2004-2005
+# released under the GNU GPL
+
+package EthParser;
+
+use strict;
+use typelist;
+use ndr;
+
+# the list of needed functions
+
+# list of known types
+my %typefamily;
+
+
+sub NeededFunction($$)
+{
+       my $fn = shift;
+       my $needed = shift;
+       $needed->{"pull_$fn->{NAME}"} = 1;
+       foreach my $e (@{$fn->{ELEMENTS}}) {
+               $e->{PARENT} = $fn;
+               unless(defined($needed->{"pull_$e->{TYPE}"})) {
+                       $needed->{"pull_$e->{TYPE}"} = 1;
+               }
+
+               # for Ethereal
+               if (Ndr::is_scalar_type($e->{TYPE})) {
+                   
+                   if (defined($e->{ARRAY_LEN}) or 
+                       util::has_property($e, "size_is")) {
+                       
+                       # Array of scalar types
+                       
+                       $needed->{"hf_$fn->{NAME}_$e->{NAME}_array"} = {
+                           'name' => field2name($e->{NAME}),
+                           'type' => $e->{TYPE},
+                           'ft'   => "FT_BYTES",
+                           'base' => elementbase($e)
+                           };
+                       
+                   } else {                            
+                       $needed->{"hf_$fn->{NAME}_$e->{NAME}"} = {
+                           'name' => field2name($e->{NAME}),
+                           'type' => $e->{TYPE},
+                           'ft'   => type2ft($e->{TYPE}),
+                           'base' => elementbase($e)
+                           };
+                   }
+               } else {
+                   $needed->{"hf_$fn->{NAME}_$e->{NAME}"} = {
+                       'name' => field2name($e->{NAME}),
+                       'type' => $e->{TYPE},
+                       'ft'   => type2ft($e->{TYPE}),
+                       'base' => elementbase($e)
+                       };
+                   $needed->{"hf_$e->{TYPE}"} = {
+                       'name' => field2name($e->{NAME}),
+                       'type' => $e->{TYPE},
+                       'ft'   => type2ft($e->{TYPE}),
+                       'base' => elementbase($e)
+                       };
+                   $needed->{"ett_$e->{TYPE}"} = 1;
+               }
+       }
+
+       # Add entry for return value
+       if (defined($fn->{RETURN_TYPE})) {
+               $needed->{"hf_$fn->{NAME}_result"} = {
+           'name' => field2name('result'),
+           'type' => $fn->{RETURN_TYPE},
+           'ft' => type2ft($fn->{RETURN_TYPE}),
+           'base' => elementbase($fn)
+           };
+       }
+}
+
+sub NeededTypedef($$)
+{
+       my $t = shift;
+       my $needed = shift;
+
+       if (util::has_property($t, "public")) {
+               $needed->{"pull_$t->{NAME}"} = not util::has_property($t, "nopull");
+       }
+
+       if ($t->{DATA}->{TYPE} eq "STRUCT" or $t->{DATA}->{TYPE} eq "UNION") {
+
+               for my $e (@{$t->{DATA}->{ELEMENTS}}) {
+                       $e->{PARENT} = $t->{DATA};
+                       if ($needed->{"pull_$t->{NAME}"} and
+                               not defined($needed->{"pull_$e->{TYPE}"})) {
+                               $needed->{"pull_$e->{TYPE}"} = 1;
+                       }
+
+                       if (Ndr::is_scalar_type($e->{TYPE})) {
+                               if (defined($e->{ARRAY_LEN}) or 
+                               util::has_property($e, "size_is")) {
+
+                                       # Arrays of scalar types are FT_BYTES
+                                   
+                                   $needed->{"hf_$t->{NAME}_$e->{NAME}_array"} = {
+                                       'name' => field2name($e->{NAME}),
+                                       'type' => $e->{TYPE},
+                                       'ft'   => "FT_BYTES",
+                                       'base' => elementbase($e)
+                                       };
+
+                               } else {
+                                   $needed->{"hf_$t->{NAME}_$e->{NAME}"} = {
+                                       'name' => field2name($e->{NAME}),
+                                       'type' => $e->{TYPE},
+                                       'ft'   => type2ft($e->{TYPE}),
+                                       'base' => elementbase($e)
+                                       };
+                               }
+
+                               $e->{PARENT} = $t->{DATA};
+
+                               if ($needed->{"pull_$t->{NAME}"}) {
+                                       $needed->{"pull_$e->{TYPE}"} = 1;
+                               }
+
+                       } else {
+                               $needed->{"hf_$t->{NAME}_$e->{NAME}"} = {
+                                       'name' => field2name($e->{NAME}),
+                                       'type' => $e->{TYPE},
+                                       'ft'   => type2ft($e->{TYPE}),
+                                       'base' => elementbase($e)
+                                       };
+                               $needed->{"ett_$e->{TYPE}"} = 1;
+                           }
+                }
+       }
+
+       if ($t->{DATA}->{TYPE} eq "ENUM") {
+
+               $needed->{"hf_$t->{NAME}"} = {
+                       'name' => field2name($t->{NAME}),
+                       'ft' => 'FT_UINT16',
+                       'base' => 'BASE_DEC',
+                       'strings' => "VALS($t->{NAME}_vals)"
+               };
+               $needed->{"ett_$t->{NAME}"} = 1;
+       }
+
+       if ($t->{DATA}->{TYPE} eq "BITMAP") {
+       $needed->{BITMAPS}->{$t->{NAME}} = $t;
+
+               foreach my $e (@{$t->{DATA}{ELEMENTS}}) {
+                       $e =~ /^(.*?) \( (.*?) \)$/;
+                       $needed->{"hf_$t->{NAME}_$1"} = {
+                               'name' => "$1",
+                               'ft' => "FT_BOOLEAN",
+                               'base' => bitmapbase($t),
+                               'bitmask' => "$2"
+                       };
+               }
+               $needed->{"ett_$t->{NAME}"} = 1;
+       }
+}
+
+#####################################################################
+# work out what parse functions are needed
+sub NeededInterface($)
+{
+       my($interface) = shift;
+       my %needed = ();
+
+       $needed{"hf_$interface->{NAME}_opnum"} = {
+               'name' => "Operation",
+               'ft'   => "FT_UINT16",
+               'base' => "BASE_DEC"
+       };
+
+       $needed{"ett_dcerpc_$interface->{NAME}"} = 1;
+       
+       foreach my $d (@{$interface->{FUNCTIONS}}) {
+           NeededFunction($d, \%needed);
+       }
+       foreach my $d (reverse @{$interface->{TYPEDEFS}}) {
+           NeededTypedef($d, \%needed);
+       }
+
+       return \%needed;
+}
+
+sub type2ft($)
+{
+    my($t) = shift;
+    return "FT_UINT$1" if $t =~ /uint(8|16|32|64)/;
+    return "FT_INT$1" if $t =~ /int(8|16|32|64)/;
+    return "FT_UINT64", if $t eq "HYPER_T" or $t eq "NTTIME"
+       or $t eq "NTTIME_1sec" or $t eq "NTTIME_hyper" or $t eq "hyper";
+   
+   # Type is an enum
+
+    return "FT_UINT16";
+}
+
+# Determine the display base for an element
+
+sub elementbase($)
+{
+    my($e) = shift;
+
+    if (my $base = util::has_property($e, "display")) {
+       return "BASE_" . uc($base);
+    }
+    return "BASE_DEC", if $e->{TYPE} eq "ENUM";
+    return "BASE_DEC", if $e->{TYPE} =~ /u?int(8|16|32|64)/;
+    return "BASE_DEC", if $e->{TYPE} eq "NTTIME" or $e->{TYPE} eq "HYPER_T";
+
+    # Probably an enum
+
+    return "BASE_DEC";
+}
+
+# Convert a IDL structure field name (e.g access_mask) to a prettier
+# string like 'Access Mask'.
+
+sub field2name($)
+{
+    my($field) = shift;
+
+    $field =~ s/_/ /g;         # Replace underscores with spaces
+    $field =~ s/(\w+)/\u\L$1/g;        # Capitalise each word
+    
+    return $field;
+}
+
+sub bitmapbase($)
+{
+    my $e = shift;
+
+    return "16", if util::has_property($e->{DATA}, "bitmap16bit");
+    return "8", if util::has_property($e->{DATA}, "bitmap8bit");
+
+    return "32";
+}
+
+sub get_typefamily($)
+{
+       my $n = shift;
+       return $typefamily{$n};
+}
+
+sub append_prefix($$)
+{
+       my $e = shift;
+       my $var_name = shift;
+       my $pointers = 0;
+
+       foreach my $l (@{$e->{LEVELS}}) {
+               if ($l->{TYPE} eq "POINTER") {
+                       $pointers++;
+               } elsif ($l->{TYPE} eq "ARRAY") {
+                       if (($pointers == 0) and 
+                           (not $l->{IS_FIXED}) and
+                           (not $l->{IS_INLINE})) {
+                               return get_value_of($var_name) 
+                       }
+               } elsif ($l->{TYPE} eq "DATA") {
+                       if ($l->{DATA_TYPE} eq "string" or
+                           $l->{DATA_TYPE} eq "nbt_string") {
+                               return get_value_of($var_name) unless ($pointers);
+                       }
+               }
+       }
+       
+       return $var_name;
+}
+
+# see if a variable needs to be allocated by the NDR subsystem on pull
+sub need_alloc($)
+{
+       my $e = shift;
+
+       return 0;
+}
+
+sub get_pointer_to($)
+{
+       my $var_name = shift;
+       
+       if ($var_name =~ /^\*(.*)$/) {
+               return $1;
+       } elsif ($var_name =~ /^\&(.*)$/) {
+           return $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";
+       }
+}
+
+my $res;
+my $tabs = "";
+sub pidl($)
+{
+       my $d = shift;
+       if ($d) {
+               $res .= $tabs;
+               $res .= $d;
+       }
+       $res .="\n";
+}
+
+sub indent()
+{
+       $tabs .= "\t";
+}
+
+sub deindent()
+{
+       $tabs = substr($tabs, 0, -1);
+}
+
+####################################################################
+# work out the name of a size_is() variable
+sub ParseExpr($$)
+{
+       my($orig_expr) = shift;
+       my $varlist = shift;
+
+       die("Undefined value in ParseExpr") if not defined($orig_expr);
+
+       my $expr = $orig_expr;
+
+       return $expr if (util::is_constant($expr));
+
+       my $prefix = "";
+       my $postfix = "";
+
+       if ($expr =~ /\*(.*)/) {
+               $expr = $1;
+               $prefix = "*";
+       }
+
+       if ($expr =~ /^(.*)([\&\|\/+])(.*)$/) {
+               $postfix = $2.$3;
+               $expr = $1;
+       }
+
+       if (defined($varlist->{$expr})) {
+               return $prefix.$varlist->{$expr}.$postfix;
+       }
+
+       return $prefix.$expr.$postfix;
+}
+
+#####################################################################
+# check that a variable we get from ParseExpr isn't a null pointer
+sub check_null_pointer($)
+{
+       my $size = shift;
+       if ($size =~ /^\*/) {
+               my $size2 = substr($size, 1);
+               pidl "if ($size2 == NULL) return NT_STATUS_INVALID_PARAMETER_MIX;";
+       }
+}
+
+#####################################################################
+# check that a variable we get from ParseExpr isn't a null pointer
+# void return varient
+sub check_null_pointer_void($)
+{
+       my $size = shift;
+       if ($size =~ /^\*/) {
+               my $size2 = substr($size, 1);
+               pidl "if ($size2 == NULL) return;";
+       }
+}
+
+#####################################################################
+# work out is a parse function should be declared static or not
+sub fn_prefix($)
+{
+       my $fn = shift;
+
+       return "" if (util::has_property($fn, "public"));
+       return "static ";
+}
+
+###################################################################
+# setup any special flags for an element or structure
+sub start_flags($)
+{
+       my $e = shift;
+       my $flags = util::has_property($e, "flag");
+       if (defined $flags) {
+               pidl "{ uint32_t _flags_save_$e->{TYPE} = ndr->flags;";
+               pidl "ndr_set_flags(&ndr->flags, $flags);";
+               indent;
+       }
+}
+
+###################################################################
+# end any special flags for an element or structure
+sub end_flags($)
+{
+       my $e = shift;
+       my $flags = util::has_property($e, "flag");
+       if (defined $flags) {
+               pidl "ndr->flags = _flags_save_$e->{TYPE};\n\t}";
+               deindent;
+       }
+}
+
+sub GenerateStructEnv($)
+{
+       my $x = shift;
+       my %env;
+
+       foreach my $e (@{$x->{ELEMENTS}}) {
+               $env{$e->{NAME}} = "r->$e->{NAME}";
+       }
+
+       $env{"this"} = "r";
+
+       return \%env;
+}
+
+sub GenerateFunctionEnv($)
+{
+       my $fn = shift;
+       my %env;
+
+       foreach my $e (@{$fn->{ELEMENTS}}) {
+               if (grep (/out/, @{$e->{DIRECTION}})) {
+                       $env{$e->{NAME}} = "r->out.$e->{NAME}";
+               }
+               if (grep (/in/, @{$e->{DIRECTION}})) {
+                       $env{$e->{NAME}} = "r->in.$e->{NAME}";
+               }
+       }
+
+       return \%env;
+}
+
+#####################################################################
+sub ParseArrayPreceding($$$)
+{
+       my $e = shift;
+       my $l = shift;
+       my $var_name = shift;
+
+       return if ($l->{NO_METADATA});
+       
+       # non fixed arrays encode the size just before the array
+       pidl "ndr_pull_array_size(ndr, tree, " . get_pointer_to($var_name) . ");";
+}
+
+sub compression_alg($$)
+{
+       my $e = shift;
+       my $l = shift;
+       my $compression = $l->{COMPRESSION};
+       my ($alg, $clen, $dlen) = split(/ /, $compression);
+
+       return $alg;
+}
+
+sub compression_clen($$$)
+{
+       my $e = shift;
+       my $l = shift;
+       my $env = shift;
+       my $compression = $l->{COMPRESSION};
+       my ($alg, $clen, $dlen) = split(/ /, $compression);
+
+       return ParseExpr($clen, $env);
+}
+
+sub compression_dlen($$$)
+{
+       my $e = shift;
+       my $l = shift;
+       my $env = shift;
+       my $compression = $l->{COMPRESSION};
+       my ($alg, $clen, $dlen) = split(/ /, $compression);
+
+       return ParseExpr($dlen, $env);
+}
+
+sub ParseCompressionStart($$$$)
+{
+       my $e = shift;
+       my $l = shift;
+       my $subndr = shift;
+       my $env = shift;
+       my $comndr = $subndr."_compressed";
+       my $alg = compression_alg($e, $l);
+       my $dlen = compression_dlen($e, $l, $env);
+
+       pidl "{";
+       indent;
+       pidl "struct pidl_pull *$comndr;";
+       pidl "NDR_ALLOC($subndr, $comndr);";
+       pidl "ndr_pull_compression($subndr, $comndr, $alg, $dlen);";
+
+       return $comndr;
+}
+
+sub ParseCompressionEnd($$$)
+{
+       my $e = shift;
+       my $l = shift;
+       my $subndr = shift;
+       my $comndr = $subndr."_compressed";
+
+       deindent;
+       pidl "}";
+}
+
+sub ParseObfuscationStart($$)
+{
+       my $e = shift;
+       my $ndr = shift;
+       my $obfuscation = util::has_property($e, "obfuscation");
+
+       pidl "ndr_pull_obfuscation($ndr, $obfuscation);";
+
+       return $ndr;
+}
+
+sub ParseObfuscationEnd($$)
+{
+       my $e = shift;
+       my $ndr = shift;
+
+       # nothing to do here
+}
+
+sub ParseSubcontextStart($$$$$$)
+{
+       my $e = shift;
+       my $l = shift;
+       my $ndr = shift;
+       my $var_name = shift;
+       my $ndr_flags = shift;  
+       my $env = shift;
+       my $retndr = "_ndr_$e->{NAME}";
+
+       pidl "/* NDR_FLAGS $ndr_flags */";
+       pidl "if ((ndr_flags) & NDR_SCALARS) {";
+       indent;
+       pidl "struct pidl_pull *$retndr;";
+       pidl "NDR_ALLOC(ndr, $retndr);";
+       pidl "ndr_pull_subcontext_header($ndr, $l->{HEADER_SIZE}, $l->{SUBCONTEXT_SIZE}, $retndr);"; 
+
+       if (defined $l->{COMPRESSION}) {
+               $retndr = ParseCompressionStart($e, $l, $retndr, $env);
+       }
+
+       if (defined $l->{OBFUSCATION}) {
+               $retndr = ParseObfuscationStart($e, $retndr);
+       }
+       
+       return ($retndr,$var_name);
+}
+
+sub ParseSubcontextEnd($$)
+{
+       my $e = shift;
+       my $l = shift;
+       my $ndr = "_ndr_$e->{NAME}";
+
+       if (defined $l->{COMPRESSION}) {
+               ParseCompressionEnd($e, $l, $ndr);
+       }
+
+       if (defined $l->{OBFUSCATION}) {
+               ParseObfuscationEnd($e, $ndr);
+       }
+
+       my $advance;
+       if (defined($l->{SUBCONTEXT_SIZE}) and ($l->{SUBCONTEXT_SIZE} ne "-1")) {
+               $advance = $l->{SUBCONTEXT_SIZE};
+       } elsif ($l->{HEADER_SIZE}) {
+               $advance = "$ndr->data_size";
+       } else {
+               $advance = "$ndr->offset";
+       }
+       pidl "ndr_pull_advance(ndr, $advance);";
+       deindent;
+       pidl "}";
+}
+
+#####################################################################
+# parse scalars in a structure element - pull size
+sub ParseSwitch($$$$$$)
+{
+       my($e) = shift;
+       my $l = shift;
+       my $ndr = shift;
+       my($var_name) = shift;
+       my($ndr_flags) = shift;
+       my $env = shift;
+       my $switch_var = ParseExpr($l->{SWITCH_IS}, $env);
+
+       check_null_pointer($switch_var);
+
+       $var_name = get_pointer_to($var_name);
+       pidl "ndr_pull_set_switch_value($ndr, $var_name, $switch_var);";
+
+}
+
+sub ParseData($$$$$)
+{
+       my $e = shift;
+       my $l = shift;
+       my $ndr = shift;
+       my $var_name = shift;
+       my $ndr_flags = shift;
+
+       $var_name = get_pointer_to($var_name);
+
+       #
+       #  ALAND! for packet-dcerpc-lsa.c, uncommenting this code
+       #  produces constructs like &(&r->string), to pass to another
+       #  function, which gives compiler errors.
+       #
+       if ($l->{DATA_TYPE} eq "string" or 
+           $l->{DATA_TYPE} eq "nbt_string") {
+               $var_name = get_pointer_to($var_name);
+       }
+
+       pidl "offset += dissect_$l->{DATA_TYPE}(tvb, offset, pinfo, tree, drep, hf_FIXME, NULL);";
+
+       if (my $range = util::has_property($e, "range")) {
+               $var_name = get_value_of($var_name);
+               my ($low, $high) = split(/ /, $range, 2);
+               if (($l->{DATA_TYPE} =~ /^uint/) and ($low eq "0")) {
+                   pidl "if ($var_name > $high) {";
+               } else {
+                   pidl "if ($var_name < $low || $var_name > $high) {";
+               }
+               pidl "\treturn NT_STATUS_OK;";
+               pidl "}";
+       }
+}
+
+sub CalcNdrFlags($$$)
+{
+       my $l = shift;
+       my $primitives = shift;
+       my $deferred = shift;
+
+       my $scalars = 0;
+       my $buffers = 0;
+
+       # Add NDR_SCALARS if this one is deferred 
+       # and deferreds may be pushed
+       $scalars = 1 if ($l->{IS_DEFERRED} and $deferred);
+
+       # Add NDR_SCALARS if this one is not deferred and 
+       # primitives may be pushed
+       $scalars = 1 if (!$l->{IS_DEFERRED} and $primitives);
+       
+       # Add NDR_BUFFERS if this one contains deferred stuff
+       # and deferreds may be pushed
+       $buffers = 1 if ($l->{CONTAINS_DEFERRED} and $deferred);
+
+       return "NDR_SCALARS|NDR_BUFFERS" if ($scalars and $buffers);
+       return "NDR_SCALARS" if ($scalars);
+       return "NDR_BUFFERS" if ($buffers);
+       return undef;
+}
+
+
+sub ParseElementLevel
+{
+       my($e) = shift;
+       my $l = shift;
+       my $ndr = shift;
+       my($var_name) = shift;
+       my $env = shift;
+       my $primitives = shift;
+       my $deferred = shift;
+
+       my $ndr_flags = CalcNdrFlags($l, $primitives, $deferred);
+
+       # Only pull something if there's actually something to be pulled
+       if (defined($ndr_flags)) {
+               if ($l->{TYPE} eq "SUBCONTEXT") {
+                               ($ndr,$var_name) = ParseSubcontextStart($e, $l, $ndr, $var_name, $ndr_flags, $env);
+                               ParseElementLevel($e,Ndr::GetNextLevel($e,$l), $ndr, $var_name, $env, $primitives, $deferred);
+                               ParseSubcontextEnd($e, $l);
+               } elsif ($l->{TYPE} eq "ARRAY") {
+                       my $length = ParseArrayHeader($e, $l, $ndr, $var_name, $env); 
+               } elsif ($l->{TYPE} eq "POINTER") {
+                       ParsePtr($e, $l, $ndr, $var_name);
+               } elsif ($l->{TYPE} eq "SWITCH") {
+                       ParseSwitch($e, $l, $ndr, $var_name, $ndr_flags, $env);
+               } elsif ($l->{TYPE} eq "DATA") {
+                       ParseData($e, $l, $ndr, $var_name, $ndr_flags);
+               }
+       }
+
+       # add additional constructions
+       if ($l->{TYPE} eq "POINTER" and $deferred) {
+               if ($l->{POINTER_TYPE} ne "ref") {
+                       pidl "if ($var_name) {";
+                       indent;
+
+                       if ($l->{POINTER_TYPE} eq "relative") {
+                               pidl "struct ndr_pull_save _relative_save;";
+                               pidl "ndr_pull_save(ndr, &_relative_save);";
+                               pidl "NDR_CHECK(ndr_pull_relative_ptr2(ndr, $var_name));";
+                       }
+               }
+
+               $var_name = get_value_of($var_name);
+               ParseElementLevel($e,Ndr::GetNextLevel($e,$l), $ndr, $var_name, $env, $primitives, $deferred);
+
+               if ($l->{POINTER_TYPE} ne "ref") {
+               if ($l->{POINTER_TYPE} eq "relative") {
+                               pidl "ndr_pull_restore(ndr, &_relative_save);";
+                       }
+                       deindent;
+                       pidl "}";
+               }
+       } elsif ($l->{TYPE} eq "ARRAY") {
+               my $length = ParseExpr($l->{LENGTH_IS}, $env);
+               my $counter = "cntr_$e->{NAME}_$l->{LEVEL_INDEX}";
+
+               $var_name = $var_name . "[$counter]";
+               unless ($l->{NO_METADATA}) {
+                       $var_name = get_pointer_to($var_name);
+               }
+
+               if (($primitives and not $l->{IS_DEFERRED}) or ($deferred and $l->{IS_DEFERRED})) {
+                       pidl "for ($counter = 0; $counter < $length; $counter++) {";
+                       indent;
+                       ParseElementLevel($e,Ndr::GetNextLevel($e,$l), $ndr, $var_name, $env, 1, 0);
+                       deindent;
+                       pidl "}";
+               }
+
+               if ($deferred and Ndr::ContainsDeferred($e, $l)) {
+                       pidl "for ($counter = 0; $counter < $length; $counter++) {";
+                       indent;
+                       ParseElementLevel($e,Ndr::GetNextLevel($e,$l), $ndr, $var_name, $env, 0, 1);
+                       deindent;
+                       pidl "}";
+               }
+       } elsif ($l->{TYPE} eq "SWITCH") {
+               ParseElementLevel($e,Ndr::GetNextLevel($e,$l), $ndr, $var_name, $env, $primitives, $deferred);
+       }
+}
+
+#####################################################################
+# parse scalars in a structure element - pull size
+sub ParseElement($$$$$$)
+{
+       my($e) = shift;
+       my $ndr = shift;
+       my($var_prefix) = shift;
+       my $env = shift;
+       my $primitives = shift;
+       my $deferred = shift;
+
+       my $var_name = $var_prefix.$e->{NAME};
+
+       $var_name = append_prefix($e, $var_name);
+
+       return unless $primitives or ($deferred and Ndr::ContainsDeferred($e, $e->{LEVELS}[0]));
+
+       start_flags($e);
+
+       ParseElementLevel($e,$e->{LEVELS}[0],$ndr,$var_name,$env,$primitives,$deferred);
+
+       end_flags($e);
+}
+
+#####################################################################
+# parse a pointer in a struct element or function
+sub ParsePtr($$$$)
+{
+       my($e) = shift;
+       my $l = shift;
+       my $ndr = shift;
+       my($var_name) = shift;
+
+       my $nl = Ndr::GetNextLevel($e, $l);
+       my $next_is_array = ($nl->{TYPE} eq "ARRAY");
+
+       if ($l->{LEVEL} eq "EMBEDDED") {
+               pidl "dissect_ndr_embedded_pointer(FIXME);";
+       } elsif ($l->{POINTER_TYPE} ne "ref") {
+                       pidl "dissect_ndr_toplevel_pointer(FIXME);";
+       }
+
+       #pidl "memset($var_name, 0, sizeof($var_name));";
+       if ($l->{POINTER_TYPE} eq "relative") {
+               pidl "ndr_pull_relative_ptr1($ndr, $var_name, _ptr_$e->{NAME});";
+       }
+}
+
+$typefamily{ENUM} = {
+       DECL => \&DeclEnum,
+};
+
+#####################################################################
+# generate a pull function for an bitmap
+sub ParseBitmap($$)
+{
+       my($bitmap) = shift;
+       my $name = shift;
+       my $type_fn = $bitmap->{BASE_TYPE};
+       my($type_decl) = typelist::mapType($bitmap->{BASE_TYPE});
+
+       pidl "$type_decl v_bitmap;";
+       start_flags($bitmap);
+       pidl "dissect_$type_fn(ndr, tree, hf, &v_bitmap);";
+       
+       pidl "{\n\tproto_tree *subtree = NULL;";
+       pidl "";
+       pidl "\tif (tree->proto_tree)\n\t\tsubtree = proto_item_add_subtree(tree->proto_tree->last_child, ett_$name);";
+       pidl "";
+       foreach my $e (@{$bitmap->{DATA}{ELEMENTS}}) {
+           $e =~ /^(.*?) \( (.*?) \)$/;
+           pidl "\tproto_tree_add_boolean(subtree, hf_${name}_$1, ndr->tvb, ndr->offset - sizeof(v_bitmap), sizeof(v_bitmap), v_bitmap);";
+       }
+       pidl "}";
+
+       pidl "*r = v_bitmap;";
+
+       end_flags($bitmap);
+}
+
+$typefamily{BITMAP} = {
+       FN_BODY => \&ParseBitmap,
+};
+
+#####################################################################
+# parse a struct - pull side
+sub ParseStruct($$)
+{
+       my($struct) = shift;
+       my $name = shift;
+       my $conform_e;
+
+       return unless defined $struct->{ELEMENTS};
+
+       my $env = GenerateStructEnv($struct);
+
+       # 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 pull the conformant length early, as it fits on
+       # the wire before the structure (and even before the structure
+       # alignment)
+       $conform_e = $struct->{SURROUNDING_ELEMENT};
+
+       # declare any internal pointers we need
+       foreach my $e (@{$struct->{ELEMENTS}}) {
+               foreach my $l (@{$e->{LEVELS}}) {
+                       if ($l->{TYPE} eq "POINTER" and not ($l->{POINTER_TYPE} eq "ref" and $l->{LEVEL} eq "TOP")) {
+                               pidl "uint32_t _ptr_$e->{NAME};";
+                               last;
+                       }
+               }
+       }
+
+       start_flags($struct);
+
+       pidl "if (ndr_flags & NDR_SCALARS) {";
+       indent;
+
+       if (defined $conform_e) {
+               ParseArrayPreceding($conform_e, $conform_e->{LEVELS}[0], "r->$conform_e->{NAME}");
+       }
+
+       pidl "ndr_pull_align(ndr, $struct->{ALIGN});";
+
+       foreach my $e (@{$struct->{ELEMENTS}}) {
+               ParseElement($e, "ndr", "r->", $env, 1, 0);
+       }       
+       deindent;
+       pidl "}";
+
+       pidl "if (ndr_flags & NDR_BUFFERS) {";
+       indent;
+       foreach my $e (@{$struct->{ELEMENTS}}) {
+               ParseElement($e, "ndr", "r->", $env, 0, 0);
+       }
+
+       pidl "proto_item_set_end(tree->proto_tree, ndr->tvb, ndr->offset);";
+       deindent;
+       pidl "}";
+
+       end_flags($struct);
+}
+
+$typefamily{STRUCT} = {
+       FN_BODY => \&ParseStruct,
+};
+
+#####################################################################
+# parse a union - pull side
+sub ParseUnion($$$)
+{
+       my $e = shift;
+       my $name = shift;
+       my $have_default = 0;
+       my $switch_type = $e->{SWITCH_TYPE};
+
+       pidl "int level;";
+       if (defined($switch_type)) {
+               if (typelist::typeIs($switch_type, "ENUM")) {
+                       $switch_type = typelist::enum_type_fn(typelist::getType($switch_type));
+               }
+               pidl typelist::mapType($switch_type) . " _level;";
+       }
+
+       start_flags($e);
+
+       pidl "level = ndr_pull_get_switch_value(ndr, r);";
+
+       pidl "if (ndr_flags & NDR_SCALARS) {";
+       indent;
+
+       if (defined($switch_type)) {
+               pidl "ndr_pull_$switch_type(ndr, tree, hf_${name}, &_level);";
+               pidl "if (_level != level) {"; 
+               pidl "\treturn NT_STATUS_OK;";
+               pidl "}";
+       }
+
+#      my $align = union_alignment($e);
+#      pidl "\tndr_pull_align(ndr, $align);\n";
+
+       pidl "switch (level) {";
+       indent;
+       foreach my $el (@{$e->{ELEMENTS}}) {
+               if ($el->{CASE} eq "default") {
+                       $have_default = 1;
+               } 
+               pidl "$el->{CASE}: {";
+
+               if ($el->{TYPE} ne "EMPTY") {
+                       indent;
+                       foreach my $l (@{$el->{LEVELS}}) {
+                               if ($l->{TYPE} eq "POINTER" and not ($l->{POINTER_TYPE} eq "ref" and $l->{LEVEL} eq "TOP")) {
+                                       pidl "uint32_t _ptr_$el->{NAME};";
+                                       last;
+                               }
+                       }
+                       ParseElement($el, "ndr", "r->", {}, 1, 0);
+                       deindent;
+               }
+               pidl "break; }";
+               pidl "";
+       }
+       if (! $have_default) {
+               pidl "default:";
+               pidl "\treturn NT_STATUS_OK;";
+       }
+       deindent;
+       pidl "}";
+       deindent;
+       pidl "}";
+       pidl "if (ndr_flags & NDR_BUFFERS) {";
+       indent;
+       pidl "switch (level) {";
+       indent;
+       foreach my $el (@{$e->{ELEMENTS}}) {
+               pidl "$el->{CASE}:";
+               if ($el->{TYPE} ne "EMPTY") {
+                       indent;
+                       ParseElement($el, "ndr", "r->", {}, 0, 1);
+                       deindent;
+               }
+               pidl "break;";
+               pidl "";
+       }
+       if (! $have_default) {
+               pidl "default:";
+               pidl "\treturn NT_STATUS_OK;";
+       }
+       deindent;
+       pidl "}";
+       pidl "proto_item_set_end(tree->proto_tree, ndr->tvb, ndr->offset);";
+       deindent;
+       pidl "}";
+       end_flags($e);
+}
+
+$typefamily{UNION} = {
+       FN_BODY => \&ParseUnion,
+};
+
+#####################################################################
+# parse an array
+sub ParseArrayHeader($$$$$)
+{
+       my $e = shift;
+       my $l = shift;
+       my $ndr = shift;
+       my $var_name = shift;
+       my $env = shift;
+
+       unless ($l->{NO_METADATA}) {
+               $var_name = get_pointer_to($var_name);
+       }
+
+       # $var_name contains the name of the first argument here
+
+       my $length = ParseExpr($l->{SIZE_IS}, $env);
+       my $size = $length;
+
+       if ($l->{IS_CONFORMANT}) {
+               $length = $size = "ndr_get_array_size($ndr, " . get_pointer_to($var_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 (!$l->{IS_SURROUNDING}) {
+               ParseArrayPreceding($e, $l, $var_name);
+       }
+
+
+       if ($l->{IS_VARYING}) {
+               pidl "NDR_CHECK(ndr_pull_array_length($ndr, " . get_pointer_to($var_name) . "));";
+               $length = "ndr_get_array_length($ndr, " . get_pointer_to($var_name) .")";
+       }
+
+       check_null_pointer($length);
+
+       if ($length ne $size) {
+               pidl "if ($length > $size) {";
+               indent;
+               pidl "return ndr_pull_error($ndr, NDR_ERR_ARRAY_SIZE, \"Bad array size %u should exceed array length %u\", $size, $length);";
+               deindent;
+               pidl "}";
+       }
+
+       if ($l->{IS_CONFORMANT}) {
+               my $size = ParseExpr($l->{SIZE_IS}, $env);
+               check_null_pointer($size);
+               pidl "NDR_CHECK(ndr_check_array_size(ndr, (void*)" . get_pointer_to($var_name) . ", $size));";
+       }
+
+       if ($l->{IS_VARYING}) {
+               my $length = ParseExpr($l->{LENGTH_IS}, $env);
+               check_null_pointer($length);
+               pidl "NDR_CHECK(ndr_check_array_length(ndr, (void*)" . get_pointer_to($var_name) . ", $length));";
+       }
+
+       return $length;
+}
+       
+#####################################################################
+# parse a typedef - pull side
+sub ParseTypedef($)
+{
+       my($e) = shift;
+
+       return unless (defined ($typefamily{$e->{DATA}->{TYPE}}));
+
+       pidl fn_prefix($e) . "int dissect_$e->{NAME}(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, int hf_index, guint32 param)";
+
+       pidl "{";
+       indent;
+       $typefamily{$e->{DATA}->{TYPE}}->{FN_BODY}->($e->{DATA}, $e->{NAME});
+       pidl "return NT_STATUS_OK;";
+       deindent;
+       pidl "}";
+       pidl "";
+}
+
+#####################################################################
+# parse a function
+sub ParseFunctionRqst($)
+{ 
+       my($fn) = shift;
+
+       my $env = GenerateFunctionEnv($fn);
+
+       # request function
+       pidl "static int dissect_$fn->{NAME}_rqst(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, guint8 *drep)";
+       pidl "{";
+       indent;
+
+       pidl "struct pidl_pull *ndr = pidl_pull_init(tvb, offset, pinfo, drep);";
+
+       # declare any internal pointers we need
+       foreach my $e (@{$fn->{ELEMENTS}}) {
+               next unless (grep (/in/, @{$e->{DIRECTIONS}}));
+               foreach my $l (@{$e->{LEVELS}}) {
+                       if ($l->{TYPE} eq "POINTER" and 
+                               not ($l->{POINTER_TYPE} eq "ref" and 
+                               $l->{LEVEL} eq "TOP")) {
+                               pidl "uint32_t _ptr_$e->{NAME};"; 
+                               last;
+                       }
+               }
+       }
+
+       foreach my $e (@{$fn->{ELEMENTS}}) {
+               next unless (grep(/in/, @{$e->{DIRECTION}}));
+               ParseElement($e, "ndr", "r->in.", $env, 1, 1);
+       }
+
+       pidl "return offset;";
+       deindent;
+       pidl "}";
+       pidl "";
+}
+
+sub ParseFunctionResp($)
+{ 
+       my($fn) = shift;
+
+       my $env = GenerateFunctionEnv($fn);
+
+       # response function
+       pidl "static int dissect_$fn->{NAME}_resp(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, guint8 *drep)";
+       pidl "{";
+       indent;
+
+       pidl "struct pidl_pull *ndr = pidl_pull_init(tvb, offset, pinfo, drep);";
+
+       # declare any internal pointers we need
+       foreach my $e (@{$fn->{ELEMENTS}}) {
+               next unless (grep (/out/, @{$e->{DIRECTIONS}}));
+               foreach my $l (@{$e->{LEVELS}}) {
+                       if ($l->{TYPE} eq "POINTER" and 
+                               not ($l->{POINTER_TYPE} eq "ref" and 
+                               $l->{LEVEL} eq "TOP")) {
+                               pidl "uint32_t _ptr_$e->{NAME};"; 
+                               last;
+                       }
+               }
+       }
+
+       foreach my $e (@{$fn->{ELEMENTS}}) {
+               next unless grep(/out/, @{$e->{DIRECTION}});
+               ParseElement($e, "ndr", "r->out.", $env, 1, 1);
+       }
+
+       if ($fn->{RETURN_TYPE}) {
+               pidl "dissect_$fn->{RETURN_TYPE}(ndr, tree, hf_$fn->{NAME}_result, drep);";
+       }
+
+       pidl "return offset;";
+       deindent;
+       pidl "}";
+       pidl "";
+}
+
+#####################################################################
+# produce a function call table
+sub FunctionTable($)
+{
+       my($interface) = shift;
+
+       pidl "static dcerpc_sub_dissector dcerpc_dissectors[] = {";
+       my $num = 0;
+       foreach my $d (@{$interface->{FUNCTIONS}}) {
+           # Strip interface name from function name, if present
+           my($n) = $d->{NAME};
+           $n = substr($d->{NAME}, length($interface->{NAME}) + 1),
+               if $interface->{NAME} eq substr($d->{NAME}, 0, length($interface->{NAME}));
+           pidl "\t{ $num, \"$n\",";
+           pidl "\t\tdissect_$d->{NAME}_rqst,";
+           pidl "\t\tdissect_$d->{NAME}_resp },";
+           $num++;
+       }
+       pidl "};\n";
+}
+
+#####################################################################
+# parse the interface definitions
+sub ParseInterface($$)
+{
+       my($interface) = shift;
+       my $needed = shift;
+
+       # Typedefs
+       foreach my $d (@{$interface->{TYPEDEFS}}) {
+               ($needed->{"pull_$d->{NAME}"}) && ParseTypedef($d);
+               # Make sure we don't generate a function twice...
+               $needed->{"pull_$d->{NAME}"} = 0;
+       }
+
+       # Functions
+       foreach my $d (@{$interface->{FUNCTIONS}}) {
+               if ($needed->{"pull_$d->{NAME}"}) {
+                       ParseFunctionRqst($d);
+                       ParseFunctionResp($d);
+               }
+
+               # Make sure we don't generate a function twice...
+               $needed->{"pull_$d->{NAME}"} = 0;
+       }
+}
+
+#####################################################################
+# generate code to parse an enum
+sub DeclEnum($$)
+{
+    my ($e) = shift;
+       my $n = shift;
+
+    pidl "static const value_string $n\_vals[] =";
+    pidl "{";
+
+    foreach my $x (@{$e->{ELEMENTS}}) {
+       $x =~ /([^=]*)=(.*)/;
+       pidl "\t{ $1, \"$1\" },";
+    }
+    
+    pidl "};\n";
+}
+
+sub DeclInterface($$)
+{
+       my($interface) = shift;
+       my $needed = shift;
+
+       # Typedefs
+       foreach my $d (@{$interface->{TYPEDEFS}}) {
+               ($needed->{"pull_$d->{NAME}"}) && DeclTypedef($d);
+
+               # Make sure we don't generate a function twice...
+               $needed->{"pull_$d->{NAME}"} = 0;
+       }
+}
+
+sub DeclTypedef($)
+{
+       my $e = shift;
+
+       if (defined($typefamily{$e->{DATA}->{TYPE}}->{DECL})) {
+               $typefamily{$e->{DATA}->{TYPE}}->{DECL}->($e->{DATA}, $e->{NAME});
+       }
+}
+
+sub RegisterInterface($$)
+{
+       my $x = shift;
+       my $needed = shift;
+
+       pidl "void proto_register_dcerpc_pidl_$x->{NAME}(void)";
+       pidl "{";
+       indent;
+       
+       pidl "static hf_register_info hf[] = {";
+       pidl "{ &hf_ptr, { \"Pointer\", \"$x->{NAME}.ptr\", FT_UINT32, BASE_HEX, NULL, 0x0, \"Pointer\", HFILL }},";
+       
+       foreach my $x (sort keys(%{$needed})) {
+           next, if !($x =~ /^hf_/);
+           pidl "{ &$x,";
+           $needed->{$x}->{strings} = "NULL", if !defined($needed->{$x}->{strings});
+           $needed->{$x}->{bitmask} = "0", if !defined($needed->{$x}->{bitmask});
+           pidl "  { \"$needed->{$x}->{name}\", \"$x\", $needed->{$x}->{ft}, $needed->{$x}->{base}, $needed->{$x}->{strings}, $needed->{$x}->{bitmask}, \"$x\", HFILL }},";
+       }
+       
+       pidl "};\n";
+       
+       pidl "static gint *ett[] = {";
+       indent;
+       foreach my $x (sort keys(%{$needed})) {
+           pidl "&$x,", if $x =~ /^ett_/;
+       }
+       deindent;
+
+       pidl "};\n";
+
+       if (defined($x->{UUID})) {
+           # These can be changed to non-pidl names if the old dissectors
+           # in epan/dissctors are deleted.
+    
+           my $name = "\"" . uc($x->{NAME}) . " (pidl)\"";
+               if (util::has_property($x, "helpstring")) {
+                       $name = $x->{PROPERTIES}->{helpstring};
+               }
+           my $short_name = "pidl_$x->{NAME}";
+           my $filter_name = "pidl_$x->{NAME}";
+    
+           pidl "proto_dcerpc_pidl_$x->{NAME} = proto_register_protocol($name, \"$short_name\", \"$filter_name\");";
+           
+           pidl "proto_register_field_array(proto_dcerpc_pidl_$x->{NAME}, hf, array_length (hf));";
+           pidl "proto_register_subtree_array(ett, array_length(ett));";
+       } else {
+           pidl "int proto_dcerpc;";
+           pidl "proto_dcerpc = proto_get_id_by_filter_name(\"dcerpc\");";
+           pidl "proto_register_field_array(proto_dcerpc, hf, array_length(hf));";
+           pidl "proto_register_subtree_array(ett, array_length(ett));";
+       }
+           
+       deindent;
+       pidl "}\n";
+}
+
+sub RegisterInterfaceHandoff($)
+{
+       my $x = shift;
+       pidl "void proto_reg_handoff_dcerpc_pidl_$x->{NAME}(void)";
+       pidl "{";
+       indent;
+       pidl "dcerpc_init_uuid(proto_dcerpc_pidl_$x->{NAME}, ett_dcerpc_$x->{NAME},";
+       pidl "\t&uuid_dcerpc_$x->{NAME}, ver_dcerpc_$x->{NAME},";
+       pidl "\tdcerpc_dissectors, hf_opnum);";
+       deindent;
+       pidl "}";
+}
+
+sub ProcessInterface($)
+{
+       my $x = shift;
+       my $needed = NeededInterface($x);
+
+       # Required global declarations
+       DeclInterface($x, $needed);
+
+       foreach my $y (sort keys(%{$needed})) {
+           pidl "static int $y = -1;", if $y =~ /^hf_/;
+       }
+       pidl "";
+
+       foreach my $y (sort keys(%{$needed})) {
+           pidl "static gint $y = -1;", if $y =~ /^ett_/;
+       }
+       pidl "";
+
+       pidl "int proto_dcerpc_pidl_$x->{NAME} = -1;\n";
+       
+       if (defined($x->{UUID})) {
+               my $if_uuid = $x->{UUID};
+           
+           pidl "static e_uuid_t uuid_dcerpc_$x->{NAME} = {";
+           pidl "\t0x" . substr($if_uuid, 1, 8) 
+               . ", 0x" . substr($if_uuid, 10, 4)
+           . ", 0x" . substr($if_uuid, 15, 4) . ",";
+           pidl "\t{ 0x" . substr($if_uuid, 20, 2) 
+               . ", 0x" . substr($if_uuid, 22, 2)
+           . ", 0x" . substr($if_uuid, 25, 2)
+           . ", 0x" . substr($if_uuid, 27, 2)
+           . ", 0x" . substr($if_uuid, 29, 2)
+           . ", 0x" . substr($if_uuid, 31, 2)
+           . ", 0x" . substr($if_uuid, 33, 2)
+           . ", 0x" . substr($if_uuid, 35, 2) . " }";
+           pidl "};\n";
+       
+           pidl "static guint16 ver_dcerpc_$x->{NAME} = $x->{VERSION};";
+       }
+
+       # dissect_* functions
+       ParseInterface($x, $needed);
+
+       # Function call tables
+       FunctionTable($x);
+
+       RegisterInterface($x, $needed);
+       RegisterInterfaceHandoff($x);
+}
+
+#####################################################################
+# parse a parsed IDL structure back into an IDL file
+sub Parse($$$)
+{
+       my($ndr) = shift;
+       my $module = shift;
+       my($filename) = shift;
+
+       $tabs = "";
+       my $h_filename = $filename;
+       $res = "";
+
+       if ($h_filename =~ /(.*)\.c/) {
+               $h_filename = "$1.h";
+       }
+
+       pidl "/* parser auto-generated by pidl */";
+       pidl "#include \"packet-dcerpc.h\"";
+       pidl "#include \"$h_filename\"";
+       pidl "";
+       pidl "static int hf_ptr = -1;";
+       pidl "static int hf_array_size = -1;";
+       pidl "";
+
+#      print keys %{$needed->{hf_atsvc_JobGetInfo_result}}, "\n";
+
+       # Ethereal protocol registration
+
+       ProcessInterface($_) foreach (@$ndr);
+    
+       return $res;
+}
+
+1;
index 53c06f22d8ddeb16b5aee4d12c66001d524ecc01..d5100812ed6f3cf6b36d58ebd83087e4758580e8 100644 (file)
@@ -1808,6 +1808,8 @@ sub
               "PROPERTIES" => $_[1],
               "NAME" => $_[3],
               "DATA" => $_[5],
+                  "FILE" => $_[0]->YYData->{INPUT_FILENAME},
+                  "LINE" => $_[0]->YYData->{LINE},
           }}
        ],
        [#Rule 5
@@ -1816,19 +1818,21 @@ sub
        [#Rule 6
                 'interface_names', 4,
 sub
-#line 34 "build/pidl/idl.yp"
+#line 36 "build/pidl/idl.yp"
 { push(@{$_[1]}, $_[2]); $_[1] }
        ],
        [#Rule 7
                 'interface', 8,
 sub
-#line 38 "build/pidl/idl.yp"
+#line 40 "build/pidl/idl.yp"
 {$_[3] => {
                "TYPE" => "INTERFACE", 
               "PROPERTIES" => $_[1],
               "NAME" => $_[3],
               "BASE" => $_[4],
               "DATA" => $_[6],
+                  "FILE" => $_[0]->YYData->{INPUT_FILENAME},
+                  "LINE" => $_[0]->YYData->{LINE},
           }}
        ],
        [#Rule 8
@@ -1837,19 +1841,19 @@ sub
        [#Rule 9
                 'base_interface', 2,
 sub
-#line 49 "build/pidl/idl.yp"
+#line 53 "build/pidl/idl.yp"
 { $_[2] }
        ],
        [#Rule 10
                 'definitions', 1,
 sub
-#line 53 "build/pidl/idl.yp"
+#line 57 "build/pidl/idl.yp"
 { [ $_[1] ] }
        ],
        [#Rule 11
                 'definitions', 2,
 sub
-#line 54 "build/pidl/idl.yp"
+#line 58 "build/pidl/idl.yp"
 { push(@{$_[1]}, $_[2]); $_[1] }
        ],
        [#Rule 12
@@ -1867,47 +1871,55 @@ sub
        [#Rule 16
                 'const', 6,
 sub
-#line 62 "build/pidl/idl.yp"
+#line 66 "build/pidl/idl.yp"
 {{
                      "TYPE"  => "CONST", 
                     "DTYPE"  => $_[2],
                     "NAME"  => $_[3],
-                    "VALUE" => $_[5]
+                    "VALUE" => $_[5],
+                    "FILE" => $_[0]->YYData->{INPUT_FILENAME},
+                    "LINE" => $_[0]->YYData->{LINE},
         }}
        ],
        [#Rule 17
                 'const', 7,
 sub
-#line 69 "build/pidl/idl.yp"
+#line 75 "build/pidl/idl.yp"
 {{
                      "TYPE"  => "CONST", 
                     "DTYPE"  => $_[2],
                     "NAME"  => $_[3],
                     "ARRAY_LEN" => $_[4],
                     "VALUE" => $_[6],
+                    "FILE" => $_[0]->YYData->{INPUT_FILENAME},
+                    "LINE" => $_[0]->YYData->{LINE},
         }}
        ],
        [#Rule 18
                 'function', 7,
 sub
-#line 80 "build/pidl/idl.yp"
+#line 88 "build/pidl/idl.yp"
 {{
                "TYPE" => "FUNCTION",
                "NAME" => $_[3],
                "RETURN_TYPE" => $_[2],
                "PROPERTIES" => $_[1],
-               "ELEMENTS" => $_[5]
-        }}
+               "ELEMENTS" => $_[5],
+               "FILE" => $_[0]->YYData->{INPUT_FILENAME},
+               "LINE" => $_[0]->YYData->{LINE},
+         }}
        ],
        [#Rule 19
                 'declare', 5,
 sub
-#line 90 "build/pidl/idl.yp"
+#line 100 "build/pidl/idl.yp"
 {{
                     "TYPE" => "DECLARE", 
                      "PROPERTIES" => $_[2],
                     "NAME" => $_[4],
                     "DATA" => $_[3],
+                    "FILE" => $_[0]->YYData->{INPUT_FILENAME},
+                    "LINE" => $_[0]->YYData->{LINE},
         }}
        ],
        [#Rule 20
@@ -1919,7 +1931,7 @@ sub
        [#Rule 22
                 'decl_enum', 1,
 sub
-#line 102 "build/pidl/idl.yp"
+#line 114 "build/pidl/idl.yp"
 {{
                      "TYPE" => "ENUM"
         }}
@@ -1927,7 +1939,7 @@ sub
        [#Rule 23
                 'decl_bitmap', 1,
 sub
-#line 108 "build/pidl/idl.yp"
+#line 120 "build/pidl/idl.yp"
 {{
                      "TYPE" => "BITMAP"
         }}
@@ -1935,13 +1947,15 @@ sub
        [#Rule 24
                 'typedef', 6,
 sub
-#line 114 "build/pidl/idl.yp"
+#line 126 "build/pidl/idl.yp"
 {{
                     "TYPE" => "TYPEDEF", 
                      "PROPERTIES" => $_[2],
                     "NAME" => $_[4],
                     "DATA" => $_[3],
-                    "ARRAY_LEN" => $_[5]
+                    "ARRAY_LEN" => $_[5],
+                    "FILE" => $_[0]->YYData->{INPUT_FILENAME},
+                    "LINE" => $_[0]->YYData->{LINE},
         }}
        ],
        [#Rule 25
@@ -1962,28 +1976,28 @@ sub
        [#Rule 30
                 'type', 1,
 sub
-#line 124 "build/pidl/idl.yp"
+#line 138 "build/pidl/idl.yp"
 { "void" }
        ],
        [#Rule 31
                 'enum', 4,
 sub
-#line 129 "build/pidl/idl.yp"
+#line 143 "build/pidl/idl.yp"
 {{
-                     "TYPE" => "ENUM", 
+             "TYPE" => "ENUM", 
                     "ELEMENTS" => $_[3]
         }}
        ],
        [#Rule 32
                 'enum_elements', 1,
 sub
-#line 136 "build/pidl/idl.yp"
+#line 150 "build/pidl/idl.yp"
 { [ $_[1] ] }
        ],
        [#Rule 33
                 'enum_elements', 3,
 sub
-#line 137 "build/pidl/idl.yp"
+#line 151 "build/pidl/idl.yp"
 { push(@{$_[1]}, $_[3]); $_[1] }
        ],
        [#Rule 34
@@ -1992,13 +2006,13 @@ sub
        [#Rule 35
                 'enum_element', 3,
 sub
-#line 141 "build/pidl/idl.yp"
+#line 155 "build/pidl/idl.yp"
 { "$_[1]$_[2]$_[3]" }
        ],
        [#Rule 36
                 'bitmap', 4,
 sub
-#line 145 "build/pidl/idl.yp"
+#line 159 "build/pidl/idl.yp"
 {{
                      "TYPE" => "BITMAP", 
                     "ELEMENTS" => $_[3]
@@ -2007,25 +2021,25 @@ sub
        [#Rule 37
                 'bitmap_elements', 1,
 sub
-#line 152 "build/pidl/idl.yp"
+#line 166 "build/pidl/idl.yp"
 { [ $_[1] ] }
        ],
        [#Rule 38
                 'bitmap_elements', 3,
 sub
-#line 153 "build/pidl/idl.yp"
+#line 167 "build/pidl/idl.yp"
 { push(@{$_[1]}, $_[3]); $_[1] }
        ],
        [#Rule 39
                 'bitmap_element', 3,
 sub
-#line 156 "build/pidl/idl.yp"
+#line 170 "build/pidl/idl.yp"
 { "$_[1] ( $_[3] )" }
        ],
        [#Rule 40
                 'struct', 4,
 sub
-#line 160 "build/pidl/idl.yp"
+#line 174 "build/pidl/idl.yp"
 {{
                      "TYPE" => "STRUCT", 
                     "ELEMENTS" => $_[3]
@@ -2034,12 +2048,14 @@ sub
        [#Rule 41
                 'empty_element', 2,
 sub
-#line 167 "build/pidl/idl.yp"
+#line 181 "build/pidl/idl.yp"
 {{
                 "NAME" => "",
                 "TYPE" => "EMPTY",
                 "PROPERTIES" => $_[1],
-                "POINTERS" => 0
+                "POINTERS" => 0,
+                "FILE" => $_[0]->YYData->{INPUT_FILENAME},
+                "LINE" => $_[0]->YYData->{LINE},
         }}
        ],
        [#Rule 42
@@ -2051,7 +2067,7 @@ sub
        [#Rule 44
                 'optional_base_element', 2,
 sub
-#line 178 "build/pidl/idl.yp"
+#line 194 "build/pidl/idl.yp"
 { $_[2]->{PROPERTIES} = util::FlattenHash([$_[1],$_[2]->{PROPERTIES}]); $_[2] }
        ],
        [#Rule 45
@@ -2060,13 +2076,13 @@ sub
        [#Rule 46
                 'union_elements', 2,
 sub
-#line 183 "build/pidl/idl.yp"
+#line 199 "build/pidl/idl.yp"
 { push(@{$_[1]}, $_[2]); $_[1] }
        ],
        [#Rule 47
                 'union', 4,
 sub
-#line 187 "build/pidl/idl.yp"
+#line 203 "build/pidl/idl.yp"
 {{
                      "TYPE" => "UNION", 
                     "ELEMENTS" => $_[3]
@@ -2075,25 +2091,27 @@ sub
        [#Rule 48
                 'base_element', 5,
 sub
-#line 194 "build/pidl/idl.yp"
+#line 210 "build/pidl/idl.yp"
 {{
                           "NAME" => $_[4],
                           "TYPE" => $_[2],
                           "PROPERTIES" => $_[1],
                           "POINTERS" => $_[3],
-                          "ARRAY_LEN" => $_[5]
+                          "ARRAY_LEN" => $_[5],
+                      "FILE" => $_[0]->YYData->{INPUT_FILENAME},
+                      "LINE" => $_[0]->YYData->{LINE},
               }}
        ],
        [#Rule 49
                 'pointers', 0,
 sub
-#line 206 "build/pidl/idl.yp"
+#line 224 "build/pidl/idl.yp"
 { 0 }
        ],
        [#Rule 50
                 'pointers', 2,
 sub
-#line 207 "build/pidl/idl.yp"
+#line 225 "build/pidl/idl.yp"
 { $_[1]+1 }
        ],
        [#Rule 51
@@ -2102,7 +2120,7 @@ sub
        [#Rule 52
                 'element_list1', 3,
 sub
-#line 212 "build/pidl/idl.yp"
+#line 230 "build/pidl/idl.yp"
 { push(@{$_[1]}, $_[2]); $_[1] }
        ],
        [#Rule 53
@@ -2114,13 +2132,13 @@ sub
        [#Rule 55
                 'element_list2', 1,
 sub
-#line 218 "build/pidl/idl.yp"
+#line 236 "build/pidl/idl.yp"
 { [ $_[1] ] }
        ],
        [#Rule 56
                 'element_list2', 3,
 sub
-#line 219 "build/pidl/idl.yp"
+#line 237 "build/pidl/idl.yp"
 { push(@{$_[1]}, $_[3]); $_[1] }
        ],
        [#Rule 57
@@ -2129,13 +2147,13 @@ sub
        [#Rule 58
                 'array_len', 2,
 sub
-#line 224 "build/pidl/idl.yp"
+#line 242 "build/pidl/idl.yp"
 { "*" }
        ],
        [#Rule 59
                 'array_len', 3,
 sub
-#line 225 "build/pidl/idl.yp"
+#line 243 "build/pidl/idl.yp"
 { "$_[2]" }
        ],
        [#Rule 60
@@ -2144,31 +2162,31 @@ sub
        [#Rule 61
                 'property_list', 4,
 sub
-#line 231 "build/pidl/idl.yp"
+#line 249 "build/pidl/idl.yp"
 { util::FlattenHash([$_[1],$_[3]]); }
        ],
        [#Rule 62
                 'properties', 1,
 sub
-#line 234 "build/pidl/idl.yp"
+#line 252 "build/pidl/idl.yp"
 { $_[1] }
        ],
        [#Rule 63
                 'properties', 3,
 sub
-#line 235 "build/pidl/idl.yp"
+#line 253 "build/pidl/idl.yp"
 { util::FlattenHash([$_[1], $_[3]]); }
        ],
        [#Rule 64
                 'property', 1,
 sub
-#line 238 "build/pidl/idl.yp"
+#line 256 "build/pidl/idl.yp"
 {{ "$_[1]" => "1"     }}
        ],
        [#Rule 65
                 'property', 4,
 sub
-#line 239 "build/pidl/idl.yp"
+#line 257 "build/pidl/idl.yp"
 {{ "$_[1]" => "$_[3]" }}
        ],
        [#Rule 66
@@ -2177,7 +2195,7 @@ sub
        [#Rule 67
                 'listtext', 3,
 sub
-#line 244 "build/pidl/idl.yp"
+#line 262 "build/pidl/idl.yp"
 { "$_[1] $_[3]" }
        ],
        [#Rule 68
@@ -2186,13 +2204,13 @@ sub
        [#Rule 69
                 'commalisttext', 3,
 sub
-#line 249 "build/pidl/idl.yp"
+#line 267 "build/pidl/idl.yp"
 { "$_[1],$_[3]" }
        ],
        [#Rule 70
                 'anytext', 0,
 sub
-#line 253 "build/pidl/idl.yp"
+#line 271 "build/pidl/idl.yp"
 { "" }
        ],
        [#Rule 71
@@ -2207,67 +2225,67 @@ sub
        [#Rule 74
                 'anytext', 3,
 sub
-#line 255 "build/pidl/idl.yp"
+#line 273 "build/pidl/idl.yp"
 { "$_[1]$_[2]$_[3]" }
        ],
        [#Rule 75
                 'anytext', 3,
 sub
-#line 256 "build/pidl/idl.yp"
+#line 274 "build/pidl/idl.yp"
 { "$_[1]$_[2]$_[3]" }
        ],
        [#Rule 76
                 'anytext', 3,
 sub
-#line 257 "build/pidl/idl.yp"
+#line 275 "build/pidl/idl.yp"
 { "$_[1]$_[2]$_[3]" }
        ],
        [#Rule 77
                 'anytext', 3,
 sub
-#line 258 "build/pidl/idl.yp"
+#line 276 "build/pidl/idl.yp"
 { "$_[1]$_[2]$_[3]" }
        ],
        [#Rule 78
                 'anytext', 3,
 sub
-#line 259 "build/pidl/idl.yp"
+#line 277 "build/pidl/idl.yp"
 { "$_[1]$_[2]$_[3]" }
        ],
        [#Rule 79
                 'anytext', 3,
 sub
-#line 260 "build/pidl/idl.yp"
+#line 278 "build/pidl/idl.yp"
 { "$_[1]$_[2]$_[3]" }
        ],
        [#Rule 80
                 'anytext', 3,
 sub
-#line 261 "build/pidl/idl.yp"
+#line 279 "build/pidl/idl.yp"
 { "$_[1]$_[2]$_[3]" }
        ],
        [#Rule 81
                 'anytext', 3,
 sub
-#line 262 "build/pidl/idl.yp"
+#line 280 "build/pidl/idl.yp"
 { "$_[1]$_[2]$_[3]" }
        ],
        [#Rule 82
                 'anytext', 3,
 sub
-#line 263 "build/pidl/idl.yp"
+#line 281 "build/pidl/idl.yp"
 { "$_[1]$_[2]$_[3]" }
        ],
        [#Rule 83
                 'anytext', 5,
 sub
-#line 264 "build/pidl/idl.yp"
+#line 282 "build/pidl/idl.yp"
 { "$_[1]$_[2]$_[3]$_[4]$_[5]" }
        ],
        [#Rule 84
                 'anytext', 5,
 sub
-#line 265 "build/pidl/idl.yp"
+#line 283 "build/pidl/idl.yp"
 { "$_[1]$_[2]$_[3]$_[4]$_[5]" }
        ],
        [#Rule 85
@@ -2279,7 +2297,7 @@ sub
        [#Rule 87
                 'text', 1,
 sub
-#line 274 "build/pidl/idl.yp"
+#line 292 "build/pidl/idl.yp"
 { "\"$_[1]\"" }
        ],
        [#Rule 88
@@ -2293,13 +2311,13 @@ sub
     bless($self,$class);
 }
 
-#line 285 "build/pidl/idl.yp"
+#line 303 "build/pidl/idl.yp"
 
 
 use util;
 
 sub _Error {
-        if (exists $_[0]->YYData->{ERRMSG}) {
+    if (exists $_[0]->YYData->{ERRMSG}) {
                print $_[0]->YYData->{ERRMSG};
                delete $_[0]->YYData->{ERRMSG};
                return;
@@ -2385,21 +2403,6 @@ sub parse_idl($$)
 
        my $idl = $self->YYParse( yylex => \&_Lexer, yyerror => \&_Error );
 
-       foreach my $x (@{$idl}) {
-               # Do the inheritance
-               if (defined($x->{BASE}) and $x->{BASE} ne "") {
-                       my $parent = util::get_interface($idl, $x->{BASE});
-
-                       if(not defined($parent)) { 
-                               die("No such parent interface " . $x->{BASE});
-                       }
-                       
-                       @{$x->{INHERITED_DATA}} = (@{$parent->{INHERITED_DATA}}, @{$x->{DATA}});
-               } else {
-                       $x->{INHERITED_DATA} = $x->{DATA};
-               }
-       }
-
        return util::CleanData($idl);
 }
 
index 186f0033962a36613258799658d63b49a9f252f6..d58dc9d0233d27b19b41704c632c6d3d25399696 100644 (file)
@@ -26,6 +26,8 @@ coclass: property_list 'coclass' identifier '{' interface_names '}' optional_sem
               "PROPERTIES" => $_[1],
               "NAME" => $_[3],
               "DATA" => $_[5],
+                  "FILE" => $_[0]->YYData->{INPUT_FILENAME},
+                  "LINE" => $_[0]->YYData->{LINE},
           }}
 ;
 
@@ -41,6 +43,8 @@ interface: property_list 'interface' identifier base_interface '{' definitions '
               "NAME" => $_[3],
               "BASE" => $_[4],
               "DATA" => $_[6],
+                  "FILE" => $_[0]->YYData->{INPUT_FILENAME},
+                  "LINE" => $_[0]->YYData->{LINE},
           }}
 ;
 
@@ -63,7 +67,9 @@ const: 'const' identifier identifier '=' anytext ';'
                      "TYPE"  => "CONST", 
                     "DTYPE"  => $_[2],
                     "NAME"  => $_[3],
-                    "VALUE" => $_[5]
+                    "VALUE" => $_[5],
+                    "FILE" => $_[0]->YYData->{INPUT_FILENAME},
+                    "LINE" => $_[0]->YYData->{LINE},
         }}
        | 'const' identifier identifier array_len '=' anytext ';' 
         {{
@@ -72,6 +78,8 @@ const: 'const' identifier identifier '=' anytext ';'
                     "NAME"  => $_[3],
                     "ARRAY_LEN" => $_[4],
                     "VALUE" => $_[6],
+                    "FILE" => $_[0]->YYData->{INPUT_FILENAME},
+                    "LINE" => $_[0]->YYData->{LINE},
         }}
 ;
 
@@ -82,8 +90,10 @@ function: property_list type identifier '(' element_list2 ')' ';'
                "NAME" => $_[3],
                "RETURN_TYPE" => $_[2],
                "PROPERTIES" => $_[1],
-               "ELEMENTS" => $_[5]
-        }}
+               "ELEMENTS" => $_[5],
+               "FILE" => $_[0]->YYData->{INPUT_FILENAME},
+               "LINE" => $_[0]->YYData->{LINE},
+         }}
 ;
 
 declare: 'declare' property_list decl_type identifier';' 
@@ -92,6 +102,8 @@ declare: 'declare' property_list decl_type identifier';'
                      "PROPERTIES" => $_[2],
                     "NAME" => $_[4],
                     "DATA" => $_[3],
+                    "FILE" => $_[0]->YYData->{INPUT_FILENAME},
+                    "LINE" => $_[0]->YYData->{LINE},
         }}
 ;
 
@@ -116,7 +128,9 @@ typedef: 'typedef' property_list type identifier array_len ';'
                      "PROPERTIES" => $_[2],
                     "NAME" => $_[4],
                     "DATA" => $_[3],
-                    "ARRAY_LEN" => $_[5]
+                    "ARRAY_LEN" => $_[5],
+                    "FILE" => $_[0]->YYData->{INPUT_FILENAME},
+                    "LINE" => $_[0]->YYData->{LINE},
         }}
 ;
 
@@ -127,7 +141,7 @@ type:   struct | union | enum | bitmap | identifier
 
 enum: 'enum' '{' enum_elements '}' 
         {{
-                     "TYPE" => "ENUM", 
+             "TYPE" => "ENUM", 
                     "ELEMENTS" => $_[3]
         }}
 ;
@@ -168,7 +182,9 @@ empty_element: property_list ';'
                 "NAME" => "",
                 "TYPE" => "EMPTY",
                 "PROPERTIES" => $_[1],
-                "POINTERS" => 0
+                "POINTERS" => 0,
+                "FILE" => $_[0]->YYData->{INPUT_FILENAME},
+                "LINE" => $_[0]->YYData->{LINE},
         }}
 ;
 
@@ -196,7 +212,9 @@ base_element: property_list type pointers identifier array_len
                           "TYPE" => $_[2],
                           "PROPERTIES" => $_[1],
                           "POINTERS" => $_[3],
-                          "ARRAY_LEN" => $_[5]
+                          "ARRAY_LEN" => $_[5],
+                      "FILE" => $_[0]->YYData->{INPUT_FILENAME},
+                      "LINE" => $_[0]->YYData->{LINE},
               }}
 ;
 
@@ -287,7 +305,7 @@ optional_semicolon:
 use util;
 
 sub _Error {
-        if (exists $_[0]->YYData->{ERRMSG}) {
+    if (exists $_[0]->YYData->{ERRMSG}) {
                print $_[0]->YYData->{ERRMSG};
                delete $_[0]->YYData->{ERRMSG};
                return;
@@ -373,20 +391,5 @@ sub parse_idl($$)
 
        my $idl = $self->YYParse( yylex => \&_Lexer, yyerror => \&_Error );
 
-       foreach my $x (@{$idl}) {
-               # Do the inheritance
-               if (defined($x->{BASE}) and $x->{BASE} ne "") {
-                       my $parent = util::get_interface($idl, $x->{BASE});
-
-                       if(not defined($parent)) { 
-                               die("No such parent interface " . $x->{BASE});
-                       }
-                       
-                       @{$x->{INHERITED_DATA}} = (@{$parent->{INHERITED_DATA}}, @{$x->{DATA}});
-               } else {
-                       $x->{INHERITED_DATA} = $x->{DATA};
-               }
-       }
-
        return util::CleanData($idl);
 }
index 3c75b29227e2accb45f2581bf7810ea7ac707eb2..5c39578f404c0771e230809f238f2b4ce5fa43e0 100644 (file)
@@ -23,40 +23,73 @@ sub GetElementLevelTable($)
 {
        my $e = shift;
 
-       return ($e->{NDR_ORDER_TABLE}) if (defined $e->{NDR_ORDER_TABLE});
-
        my $order = [];
        my $is_deferred = 0;
        
-       # FIXME: Process {ARRAY_SIZE} kinds of arrays
+       # FIXME: Process {ARRAY_LEN} kinds of arrays
 
        # First, all the pointers
-       foreach my $i (1..need_wire_pointer($e)) {
+       foreach my $i (1..$e->{POINTERS}) {
+               my $pt = pointer_type($e);
+
+               my $level = "EMBEDDED";
+               # Top level "ref" pointers do not have a referrent identifier
+               $level = "TOP" if ( defined($pt) 
+                               and $i == 1
+                               and $e->{PARENT}->{TYPE} eq "FUNCTION");
+
                push (@$order, { 
                        TYPE => "POINTER",
                        # for now, there can only be one pointer type per element
                        POINTER_TYPE => pointer_type($e),
-                       IS_DEFERRED => "$is_deferred"
+                       IS_DEFERRED => "$is_deferred",
+                       LEVEL => $level
                });
                # everything that follows will be deferred
-               $is_deferred = 1;
+               $is_deferred = 1 if ($e->{PARENT}->{TYPE} ne "FUNCTION");
                # FIXME: Process array here possibly (in case of multi-dimensional arrays, etc)
        }
 
-       if (defined($e->{ARRAY_LEN})) {
+       if (defined($e->{ARRAY_LEN}) or util::has_property($e, "size_is")) {
+               my $length = util::has_property($e, "length_is");
+               my $size = util::has_property($e, "size_is");
+
+               if (not defined($size) and defined($e->{ARRAY_LEN})) { 
+                       $size = $e->{ARRAY_LEN};
+               }
+
+               if (not defined($length)) {
+                       $length = $size;
+               }
+
                push (@$order, {
                        TYPE => "ARRAY",
-                       ARRAY_TYPE => array_type($e),
-                       SIZE_IS => util::has_property($e, "size_is"),
-                       LENGTH_IS => util::has_property($e, "length_is"),
-                       IS_DEFERRED => "$is_deferred"
+                       SIZE_IS => $size,
+                       LENGTH_IS => $length,
+                       IS_DEFERRED => "$is_deferred",
+                       # Inline arrays (which are a pidl extension) are never encoded
+                       # as surrounding the struct they're part of
+                       IS_SURROUNDING => (is_surrounding_array($e) and not is_inline_array($e)),
+                       IS_VARYING => is_varying_array($e),
+                       IS_CONFORMANT => is_conformant_array($e),
+                       IS_FIXED => is_fixed_array($e),
+                       NO_METADATA => (is_inline_array($e) or is_fixed_array($e)),
+                       IS_INLINE => is_inline_array($e)
                });
+
+               $is_deferred = 0;
        }
 
-       if (my $sub_size = util::has_property($e, "subcontext")) {
+       if (my $hdr_size = util::has_property($e, "subcontext")) {
+               my $subsize = util::has_property($e, "subcontext_size");
+               if (not defined($subsize)) { 
+                       $subsize = -1; 
+               }
+               
                push (@$order, {
                        TYPE => "SUBCONTEXT",
-                       SUBCONTEXT_SIZE => $sub_size,
+                       HEADER_SIZE => $hdr_size,
+                       SUBCONTEXT_SIZE => $subsize,
                        IS_DEFERRED => $is_deferred,
                        COMPRESSION => util::has_property($e, "compression")
                });
@@ -73,12 +106,13 @@ sub GetElementLevelTable($)
        push (@$order, {
                TYPE => "DATA",
                DATA_TYPE => $e->{TYPE},
-               NAME => $e->{NAME},
                IS_DEFERRED => $is_deferred,
-               CONTAINS_DEFERRED => can_contain_deferred($e)
+               CONTAINS_DEFERRED => can_contain_deferred($e),
+               IS_SURROUNDING => is_surrounding_string($e)
        });
 
-       $e->{NDR_ORDER_TABLE} = $order;
+       my $i = 0;
+       foreach (@$order) { $_->{LEVEL_INDEX} = $i; $i+=1; }
 
        return $order;
 }
@@ -107,7 +141,7 @@ sub is_scalar_type($)
 {
     my $type = shift;
 
-       return 0 unless typelist::hasType($type);
+       return 0 unless(typelist::hasType($type));
 
        if (my $dt = typelist::getType($type)->{DATA}->{TYPE}) {
                return 1 if ($dt eq "SCALAR" or $dt eq "ENUM" or $dt eq "BITMAP");
@@ -152,9 +186,8 @@ sub is_conformant_array($)
 sub is_inline_array($)
 {
        my $e = shift;
-       my $len = $e->{"ARRAY_LEN"};
-       if (is_fixed_array($e) ||
-           defined $len && $len ne "*") {
+       my $len = $e->{ARRAY_LEN};
+       if (defined $len && $len ne "*" && !is_fixed_array($e)) {
                return 1;
        }
        return 0;
@@ -181,17 +214,15 @@ sub is_surrounding_array($)
                and $e->{PARENT}->{TYPE} ne "FUNCTION");
 }
 
-sub array_type($)
+sub is_surrounding_string($)
 {
        my $e = shift;
 
-       return "conformant-varying" if (is_varying_array($e) and is_conformant_array($e));
-       return "conformant" if (is_varying_array($e));
-       return "varying" if (is_varying_array($e));
-       return "inline" if (is_inline_array($e));
-       return "fixed" if (is_fixed_array($e));
+       return 0; #FIXME
 
-       return undef;
+       return ($e->{TYPE} eq "string") and ($e->{POINTERS} == 0) 
+               and util::property_matches($e, "flag", ".*LIBNDR_FLAG_STR_CONFORMANT.*") 
+               and $e->{PARENT}->{TYPE} ne "FUNCTION";
 }
 
 #####################################################################
@@ -216,6 +247,35 @@ sub find_largest_alignment($)
        return $align;
 }
 
+my %scalar_alignments = 
+(
+     "char"           => 1,
+     "int8"           => 1,
+     "uint8"          => 1,
+     "short"          => 2,
+     "wchar_t"        => 2,
+     "int16"          => 2,
+     "uint16"         => 2,
+     "long"           => 4,
+     "int32"          => 4,
+     "uint32"         => 4,
+     "dlong"          => 4,
+     "udlong"         => 4,
+     "udlongr"        => 4,
+     "NTTIME"         => 4,
+     "NTTIME_1sec"    => 4,
+     "time_t"         => 4,
+     "DATA_BLOB"      => 4,
+     "error_status_t" => 4,
+     "WERROR"         => 4,
+        "NTSTATUS"       => 4,
+     "boolean32"      => 4,
+     "unsigned32"     => 4,
+     "ipv4address"    => 4,
+     "hyper"          => 8,
+     "NTTIME_hyper"   => 8
+);
+
 #####################################################################
 # align a type
 sub align_type
@@ -237,10 +297,10 @@ sub align_type
        } elsif (($dt->{TYPE} eq "STRUCT") or ($dt->{TYPE} eq "UNION")) {
                return find_largest_alignment($dt);
        } elsif ($dt->{TYPE} eq "SCALAR") {
-               return typelist::getScalarAlignment($dt->{NAME});
+               return $scalar_alignments{$dt->{NAME}};
+       } else { 
+               die("Unknown data type type $dt->{TYPE}");
        }
-
-       die("Unknown data type type $dt->{TYPE}");
 }
 
 # determine if an element needs a reference pointer on the wire
@@ -269,6 +329,7 @@ sub ParseElement($)
 
        return {
                NAME => $e->{NAME},
+               TYPE => $e->{TYPE},
                PROPERTIES => $e->{PROPERTIES},
                LEVELS => GetElementLevelTable($e)
        };
@@ -276,18 +337,31 @@ sub ParseElement($)
 
 sub ParseStruct($)
 {
-       my $e = shift;
+       my $struct = shift;
        my @elements = ();
+       my $surrounding = undef;
 
-       foreach my $x (@{$e->{ELEMENTS}}) 
+       foreach my $x (@{$struct->{ELEMENTS}}) 
        {
                push @elements, ParseElement($x);
        }
 
+       my $e = $elements[-1];
+       if (defined($e) and defined($e->{LEVELS}[0]->{IS_SURROUNDING}) and
+               $e->{LEVELS}[0]->{IS_SURROUNDING}) {
+               $surrounding = $e;
+       }
+
+       if (defined $e->{TYPE} && $e->{TYPE} eq "string"
+           &&  util::property_matches($e, "flag", ".*LIBNDR_FLAG_STR_CONFORMANT.*")) {
+               $surrounding = $struct->{ELEMENTS}[-1];
+       }
+               
        return {
                TYPE => "STRUCT",
+               SURROUNDING_ELEMENT => $surrounding,
                ELEMENTS => \@elements,
-               PROPERTIES => $e->{PROPERTIES}
+               PROPERTIES => $struct->{PROPERTIES}
        };
 }
 
@@ -295,6 +369,10 @@ sub ParseUnion($)
 {
        my $e = shift;
        my @elements = ();
+       my $switch_type = util::has_property($e, "switch_type");
+       unless (defined($switch_type)) { $switch_type = "uint32"; }
+
+       if (util::has_property($e, "nodiscriminant")) { $switch_type = undef; }
        
        foreach my $x (@{$e->{ELEMENTS}}) 
        {
@@ -303,17 +381,20 @@ sub ParseUnion($)
                        $t = { TYPE => "EMPTY" };
                } else {
                        $t = ParseElement($x);
-                       if (util::has_property($t, "default")) {
-                               $t->{DEFAULT} = "default";
-                       } else {
-                               $t->{CASE} = $t->{PROPERTIES}->{CASE};
-                       }
+               }
+               if (util::has_property($x, "default")) {
+                       $t->{CASE} = "default";
+               } elsif (defined($x->{PROPERTIES}->{case})) {
+                       $t->{CASE} = "case $x->{PROPERTIES}->{case}";
+               } else {
+                       die("Union element $x->{NAME} has neither default nor case property");
                }
                push @elements, $t;
        }
 
        return {
                TYPE => "UNION",
+               SWITCH_TYPE => $switch_type,
                ELEMENTS => \@elements,
                PROPERTIES => $e->{PROPERTIES}
        };
@@ -325,6 +406,7 @@ sub ParseEnum($)
 
        return {
                TYPE => "ENUM",
+               BASE_TYPE => typelist::enum_type_fn($e),
                ELEMENTS => $e->{ELEMENTS},
                PROPERTIES => $e->{PROPERTIES}
        };
@@ -336,11 +418,19 @@ sub ParseBitmap($)
 
        return {
                TYPE => "BITMAP",
+               BASE_TYPE => typelist::bitmap_type_fn($e),
                ELEMENTS => $e->{ELEMENTS},
                PROPERTIES => $e->{PROPERTIES}
        };
 }
 
+sub ParseDeclare($$)
+{
+       my $ndr = shift;
+       my $d = shift;
+
+}
+
 sub ParseTypedef($$)
 {
        my $ndr = shift;
@@ -371,41 +461,56 @@ sub ParseTypedef($$)
 
        return {
                NAME => $d->{NAME},
-               TYPE => "TYPEDEF",
+               TYPE => $d->{TYPE},
                PROPERTIES => $d->{PROPERTIES},
                DATA => $data
        };
 }
 
-sub ParseFunction($$)
+sub ParseConst($$)
 {
        my $ndr = shift;
        my $d = shift;
-       my @in = ();
-       my @out = ();
+
+       return $d;
+}
+
+sub ParseFunction($$$)
+{
+       my $ndr = shift;
+       my $d = shift;
+       my $opnum = shift;
+       my @elements = ();
+       my $rettype = undef;
 
        CheckPointerTypes($d, 
-               $ndr->{PROPERTIES}->{pointer_default}  # MIDL defaults to "ref"
+               $ndr->{PROPERTIES}->{pointer_default_top}
        );
 
        foreach my $x (@{$d->{ELEMENTS}}) {
+               my $e = ParseElement($x);
                if (util::has_property($x, "in")) {
-                       push (@in, ParseElement($x));
+                       push (@{$e->{DIRECTION}}, "in");
                }
+
                if (util::has_property($x, "out")) {
-                       push (@out, ParseElement($x));
+                       push (@{$e->{DIRECTION}}, "out");
                }
+
+               push (@elements, $e);
+       }
+
+       if ($d->{RETURN_TYPE} ne "void") {
+               $rettype = $d->{RETURN_TYPE};
        }
        
        return {
                        NAME => $d->{NAME},
                        TYPE => "FUNCTION",
-                       RETURN_TYPE => $d->{RETURN_TYPE},
+                       OPNUM => $opnum,
+                       RETURN_TYPE => $rettype,
                        PROPERTIES => $d->{PROPERTIES},
-                       ELEMENTS => {
-                               IN => \@in,
-                               OUT => \@out
-                       }
+                       ELEMENTS => \@elements
                };
 }
 
@@ -430,8 +535,12 @@ sub CheckPointerTypes($$)
 sub ParseInterface($)
 {
        my $idl = shift;
-       my @functions = ();
        my @typedefs = ();
+       my @consts = ();
+       my @functions = ();
+       my @endpoints;
+       my @declares = ();
+       my $opnum = 0;
        my $version;
 
        if (not util::has_property($idl, "pointer_default")) {
@@ -440,22 +549,41 @@ sub ParseInterface($)
                $idl->{PROPERTIES}->{pointer_default} = "unique";
        }
 
+       if (not util::has_property($idl, "pointer_default_top")) {
+               $idl->{PROPERTIES}->{pointer_default_top} = "ref";
+       }
+
        foreach my $d (@{$idl->{DATA}}) {
-               if ($d->{TYPE} eq "DECLARE" or $d->{TYPE} eq "TYPEDEF") {
+               if ($d->{TYPE} eq "TYPEDEF") {
                        push (@typedefs, ParseTypedef($idl, $d));
                }
 
+               if ($d->{TYPE} eq "DECLARE") {
+                       push (@declares, ParseDeclare($idl, $d));
+               }
+
                if ($d->{TYPE} eq "FUNCTION") {
-                       push (@functions, ParseFunction($idl, $d));
+                       push (@functions, ParseFunction($idl, $d, $opnum));
+                       $opnum+=1;
+               }
+
+               if ($d->{TYPE} eq "CONST") {
+                       push (@consts, ParseConst($idl, $d));
                }
        }
-       
+
        $version = "0.0";
 
        if(defined $idl->{PROPERTIES}->{version}) { 
                $version = $idl->{PROPERTIES}->{version}; 
        }
-       
+
+       # If no endpoint is set, default to the interface name as a named pipe
+       if (!defined $idl->{PROPERTIES}->{endpoint}) {
+               push @endpoints, "\"ncacn_np:[\\\\pipe\\\\" . $idl->{NAME} . "]\"";
+       } else {
+               @endpoints = split / /, $idl->{PROPERTIES}->{endpoint};
+       }
 
        return { 
                NAME => $idl->{NAME},
@@ -464,7 +592,10 @@ sub ParseInterface($)
                TYPE => "INTERFACE",
                PROPERTIES => $idl->{PROPERTIES},
                FUNCTIONS => \@functions,
-               TYPEDEFS => \@typedefs
+               CONSTS => \@consts,
+               TYPEDEFS => \@typedefs,
+               DECLARES => \@declares,
+               ENDPOINTS => \@endpoints
        };
 }
 
@@ -503,4 +634,47 @@ sub Parse($)
        return \@ndr;
 }
 
+sub GetNextLevel($$)
+{
+       my $e = shift;
+       my $fl = shift;
+
+       my $seen = 0;
+
+       foreach my $l (@{$e->{LEVELS}}) {
+               return $l if ($seen);
+               ($seen = 1) if ($l == $fl);
+       }
+
+       return undef;
+}
+
+sub GetPrevLevel($$)
+{
+       my $e = shift;
+       my $fl = shift;
+       my $prev = undef;
+
+       foreach my $l (@{$e->{LEVELS}}) {
+               (return $prev) if ($l == $fl);
+               $prev = $l;
+       }
+
+       return undef;
+}
+
+sub ContainsDeferred($$)
+{
+       my $e = shift;
+       my $l = shift;
+
+       do {
+               return 1 if ($l->{IS_DEFERRED}); 
+               return 1 if ($l->{CONTAINS_DEFERRED});
+       } while ($l = Ndr::GetNextLevel($e,$l));
+       
+       return 0;
+}
+
+
 1;
index e5d4cc156960abfda9e3afe56bc6066677409a9f..ca6fc22465923d995f26ee7cc175751ac730a22e 100644 (file)
@@ -52,6 +52,7 @@ NTSTATUS dcerpc_$name(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, struct $name *
 ";
 }
 
+my %done;
 
 #####################################################################
 # parse the interface definitions
@@ -60,9 +61,12 @@ sub ParseInterface($)
        my($interface) = shift;
        my($data) = $interface->{DATA};
        $res = "/* Client functions generated by pidl */\n\n";
+       
        foreach my $d (@{$data}) {
-               ($d->{TYPE} eq "FUNCTION") && 
-                   ParseFunction($interface, $d);
+               if (($d->{TYPE} eq "FUNCTION") and not $done{$d->{NAME}}) {
+                       ParseFunction($interface, $d);
+               }
+               $done{$d->{NAME}} = 1;
        }
        return $res;
 }
index 0c6291fca7506fc88ed35240a359164a88989523..bebf6937ae4bd955e6e4b8736c40f4cb400320dc 100644 (file)
@@ -1,12 +1,12 @@
 ###################################################
 # create C header files for an IDL structure
 # Copyright tridge@samba.org 2000
+# Copyright jelmer@samba.org 2005
 # released under the GNU GPL
 
 package NdrHeader;
 
 use strict;
-use needed;
 use typelist;
 
 my($res);
@@ -60,17 +60,23 @@ sub HeaderElement($)
     pidl tabs();
     HeaderType($element, $element->{TYPE}, "");
     pidl " ";
-    if ($element->{POINTERS} && not $element->{TYPE} =~ "string") {
-           for (my($i)=$element->{POINTERS}; $i > 0; $i--) {
+    my $pointers = 0;
+       foreach my $l (@{$element->{LEVELS}}) 
+       {
+               if (($l->{TYPE} eq "POINTER")) {
+                       next if ($element->{TYPE} eq "string");
                    pidl "*";
-           }
-    } elsif (Ndr::is_surrounding_array($element) || 
-               defined $element->{ARRAY_LEN} && !util::is_constant($element->{ARRAY_LEN})) {
-           # surrounding arrays are ugly! I choose to implement them with
-           # pointers instead of the [1] method
-           pidl "*";
-    }
-    pidl "$element->{NAME}";
+                   $pointers+=1;
+           } elsif ($l->{TYPE} eq "ARRAY") {
+               if (!$pointers and !$l->{IS_FIXED}) { pidl "*"; }
+               pidl "$element->{NAME}";
+               if ($l->{IS_FIXED}) { pidl "[$l->{SIZE_IS}]"; }
+               last; #FIXME
+           } elsif ($l->{TYPE} eq "DATA") {
+               pidl "$element->{NAME}";
+               }
+       }
+       
     if (defined $element->{ARRAY_LEN} && util::is_constant($element->{ARRAY_LEN})) {
            pidl "[$element->{ARRAY_LEN}]";
     }
@@ -106,24 +112,17 @@ sub HeaderEnum($$)
 {
     my($enum) = shift;
     my($name) = shift;
+    my $first = 1;
 
     pidl "\nenum $name {\n";
     $tab_depth++;
-    my $els = \@{$enum->{ELEMENTS}};
-    foreach my $i (0 .. $#{$els}-1) {
-           my $e = ${$els}[$i];
+    foreach my $e (@{$enum->{ELEMENTS}}) {
+           unless ($first) { pidl ",\n"; }
+           $first = 0;
            tabs();
-           chomp $e;
-           pidl "$e,\n";
-    }
-
-    my $e = ${$els}[$#{$els}];
-    tabs();
-    chomp $e;
-    if ($e !~ /^(.*?)\s*$/) {
-           die "Bad enum $name\n";
+           pidl $e;
     }
-    pidl "$1\n";
+    pidl "\n";
     $tab_depth--;
     pidl "}";
 }
@@ -137,10 +136,8 @@ sub HeaderBitmap($$)
 
     pidl "\n/* bitmap $name */\n";
 
-    my $els = \@{$bitmap->{ELEMENTS}};
-    foreach my $i (0 .. $#{$els}) {
-           my $e = ${$els}[$i];
-           chomp $e;
+    foreach my $e (@{$bitmap->{ELEMENTS}})
+    {
            pidl "#define $e\n";
     }
 
@@ -180,18 +177,14 @@ sub HeaderType($$$)
        my($data) = shift;
        my($name) = shift;
        if (ref($data) eq "HASH") {
-               ($data->{TYPE} eq "ENUM") &&
-                   HeaderEnum($data, $name);
-               ($data->{TYPE} eq "BITMAP") &&
-                   HeaderBitmap($data, $name);
-               ($data->{TYPE} eq "STRUCT") &&
-                   HeaderStruct($data, $name);
-               ($data->{TYPE} eq "UNION") &&
-                   HeaderUnion($data, $name);
+               ($data->{TYPE} eq "ENUM") && HeaderEnum($data, $name);
+               ($data->{TYPE} eq "BITMAP") && HeaderBitmap($data, $name);
+               ($data->{TYPE} eq "STRUCT") && HeaderStruct($data, $name);
+               ($data->{TYPE} eq "UNION") && HeaderUnion($data, $name);
                return;
        }
 
-       pidl typelist::mapType($e);
+       pidl typelist::mapType($e->{TYPE});
 }
 
 #####################################################################
@@ -211,7 +204,7 @@ sub HeaderTypedefProto($)
 
        my $tf = NdrParser::get_typefamily($d->{DATA}{TYPE});
 
-    if (needed::is_needed("ndr_size_$d->{NAME}")) {
+    if (util::has_property($d, "gensize")) {
                my $size_args = $tf->{SIZE_FN_ARGS}->($d);
                pidl "size_t ndr_size_$d->{NAME}($size_args);\n";
     }
@@ -265,7 +258,7 @@ sub HeaderFunctionInOut_needed($$)
     my($fn) = shift;
     my($prop) = shift;
 
-    if ($prop eq "out" && $fn->{RETURN_TYPE} && $fn->{RETURN_TYPE} ne "void") {
+    if ($prop eq "out" && $fn->{RETURN_TYPE}) {
            return 1;
     }
 
@@ -278,12 +271,18 @@ sub HeaderFunctionInOut_needed($$)
     return undef;
 }
 
+my %headerstructs = ();
+
 #####################################################################
 # parse a function
 sub HeaderFunction($)
 {
     my($fn) = shift;
 
+    return if ($headerstructs{$fn->{NAME}});
+
+    $headerstructs{$fn->{NAME}} = 1;
+
     pidl "\nstruct $fn->{NAME} {\n";
     $tab_depth++;
     my $needed = 0;
@@ -304,9 +303,9 @@ sub HeaderFunction($)
            pidl "struct {\n";
            $tab_depth++;
            HeaderFunctionInOut($fn, "out");
-           if ($fn->{RETURN_TYPE} && $fn->{RETURN_TYPE} ne "void") {
+           if ($fn->{RETURN_TYPE}) {
                    tabs();
-                   pidl typelist::mapScalarType($fn->{RETURN_TYPE}) . " result;\n";
+                   pidl typelist::mapType($fn->{RETURN_TYPE}) . " result;\n";
            }
            $tab_depth--;
            tabs();
@@ -350,7 +349,6 @@ sub HeaderFnProto($$)
 sub HeaderInterface($)
 {
     my($interface) = shift;
-    my($data) = $interface->{DATA};
 
     my $count = 0;
 
@@ -364,11 +362,6 @@ sub HeaderInterface($)
            }
     }
 
-       # Object interfaces use ORPC
-       if (util::has_property($interface, "object")) {
-               pidl "#include \"librpc/gen_ndr/ndr_orpc.h\"\n";
-       }
-
     if (defined $interface->{PROPERTIES}->{uuid}) {
            my $name = uc $interface->{NAME};
            pidl "#define DCERPC_$name\_UUID " . 
@@ -386,18 +379,16 @@ sub HeaderInterface($)
            pidl "NTSTATUS dcerpc_server_$interface->{NAME}_init(void);\n\n";
     }
 
-    foreach my $d (@{$data}) {
-           if ($d->{TYPE} eq "FUNCTION") {
-                   my $u_name = uc $d->{NAME};
-                       pidl "#define DCERPC_$u_name (";
+    foreach my $d (@{$interface->{FUNCTIONS}}) {
+           my $u_name = uc $d->{NAME};
+               pidl "#define DCERPC_$u_name (";
+       
+               if (defined($interface->{BASE})) {
+                       pidl "DCERPC_" . uc $interface->{BASE} . "_CALL_COUNT + ";
+               }
                
-                       if (defined($interface->{BASE})) {
-                               pidl "DCERPC_" . uc $interface->{BASE} . "_CALL_COUNT + ";
-                       }
-                       
-                   pidl sprintf("0x%02x", $count) . ")\n";
-                   $count++;
-           }
+           pidl sprintf("0x%02x", $count) . ")\n";
+           $count++;
     }
 
        pidl "\n#define DCERPC_" . uc $interface->{NAME} . "_CALL_COUNT (";
@@ -408,19 +399,21 @@ sub HeaderInterface($)
        
        pidl "$count)\n\n";
 
-    foreach my $d (@{$data}) {
-       ($d->{TYPE} eq "CONST") &&
+       foreach my $d (@{$interface->{CONSTS}}) {
            HeaderConst($d);
-       ($d->{TYPE} eq "TYPEDEF") &&
+    }
+
+    foreach my $d (@{$interface->{TYPEDEFS}}) {
            HeaderTypedef($d);
-       ($d->{TYPE} eq "TYPEDEF") &&
            HeaderTypedefProto($d);
-       ($d->{TYPE} eq "FUNCTION") &&
+       }
+
+    foreach my $d (@{$interface->{FUNCTIONS}}) {
            HeaderFunction($d);
-       ($d->{TYPE} eq "FUNCTION") &&
            HeaderFnProto($interface, $d);
-    }
-       
+       }
+
+  
     pidl "#endif /* _HEADER_NDR_$interface->{NAME} */\n";
 }
 
@@ -431,13 +424,10 @@ sub Parse($)
     my($idl) = shift;
     $tab_depth = 0;
 
-       NdrParser::Load($idl);
-
        $res = "";
     pidl "/* header auto-generated by pidl */\n\n";
     foreach my $x (@{$idl}) {
            if ($x->{TYPE} eq "INTERFACE") {
-                   needed::BuildNeeded($x);
                    HeaderInterface($x);
            }
     }
index d0eba81beffcab592a0a175442c4ac65e3aa8d4e..1abf8f7006e09d1ed8ce7b253d3cf58fc3a83272 100644 (file)
@@ -8,7 +8,6 @@
 package NdrParser;
 
 use strict;
-use needed;
 use typelist;
 use ndr;
 
@@ -21,15 +20,30 @@ sub get_typefamily($)
        return $typefamily{$n};
 }
 
-# determine if an element needs a "buffers" section in NDR
-sub need_buffers_section($)
+sub append_prefix($$)
 {
        my $e = shift;
-       if (!Ndr::can_contain_deferred($e) &&
-           !util::array_size($e)) {
-               return 0;
+       my $var_name = shift;
+       my $pointers = 0;
+
+       foreach my $l (@{$e->{LEVELS}}) {
+               if ($l->{TYPE} eq "POINTER") {
+                       $pointers++;
+               } elsif ($l->{TYPE} eq "ARRAY") {
+                       if (($pointers == 0) and 
+                           (not $l->{IS_FIXED}) and
+                           (not $l->{IS_INLINE})) {
+                               return get_value_of($var_name) 
+                       }
+               } elsif ($l->{TYPE} eq "DATA") {
+                       if ($l->{DATA_TYPE} eq "string" or
+                           $l->{DATA_TYPE} eq "nbt_string") {
+                               return get_value_of($var_name) unless ($pointers);
+                       }
+               }
        }
-       return 1;
+       
+       return $var_name;
 }
 
 # see if a variable needs to be allocated by the NDR subsystem on pull
@@ -37,63 +51,45 @@ sub need_alloc($)
 {
        my $e = shift;
 
-       return 0 if (util::has_property($e, "ref") && $e->{PARENT}->{TYPE} eq "FUNCTION");
-       return 1 if ($e->{POINTERS} || util::array_size($e));
        return 0;
 }
 
-# Prefix to get the actual value of a variable
-sub c_ptr_prefix($)
-{
-       my $e = shift;
-       my $pointers = "";
-       foreach my $i (Ndr::need_wire_pointer($e)..$e->{POINTERS}-1) { $pointers.="*"; }
-       return $pointers;
-}
-
-# determine the C prefix used to refer to a variable when passing to a push
-# function. This will be '*' for pointers to scalar types, '' for scalar
-# types and normal pointers and '&' for pass-by-reference structures
-sub c_push_prefix($)
+sub is_scalar_array($$)
 {
        my $e = shift;
+       my $l = shift;
 
-       my $ret = "";
+       return 0 if ($l->{TYPE} ne "ARRAY");
 
-       if ($e->{TYPE} =~ "string") {
-               $ret = "";
-       } elsif (Ndr::is_scalar_type($e->{TYPE}) and $e->{POINTERS} and 
-               !util::array_size($e)) {
-               $ret .="*";
-       } elsif (!Ndr::is_scalar_type($e->{TYPE}) &&
-           !$e->{POINTERS} &&
-           !util::array_size($e)) {
-               return "&";
-       }
+       my $nl = Ndr::GetNextLevel($e,$l);
+       return (($nl->{TYPE} eq "DATA") and 
+               (Ndr::is_scalar_type($nl->{DATA_TYPE})));
+}
 
-       foreach my $i (2..$e->{POINTERS}) { $ret.="*"; }
+sub get_pointer_to($)
+{
+       my $var_name = shift;
        
-       return $ret;
+       if ($var_name =~ /^\*(.*)$/) {
+               return $1;
+       } elsif ($var_name =~ /^\&(.*)$/) {
+               return "&($var_name)";
+       } else {
+               return "&$var_name";
+       }
 }
 
-# determine the C prefix used to refer to a variable when passing to a pull
-# return '&' or ''
-sub c_pull_prefix($)
+sub get_value_of($)
 {
-       my $e = shift;
+       my $var_name = shift;
 
-       if (!$e->{POINTERS} && !util::array_size($e)) {
-               return "&";
-       }
-
-       if ($e->{TYPE} =~ "string") {
-               return "&";
+       if ($var_name =~ /^\&(.*)$/) {
+               return $1;
+       } else {
+               return "*$var_name";
        }
-
-       my $ret = "";
-       foreach my $i (2..$e->{POINTERS}) { $ret.="*"; }
-       return $ret;
 }
+
 my $res = "";
 my $tabs = "";
 sub pidl($)
@@ -118,46 +114,35 @@ sub deindent()
 
 ####################################################################
 # work out the name of a size_is() variable
-sub ParseExpr($$$)
+sub ParseExpr($$)
 {
-       my($e) = shift;
-       my($size) = shift;
-       my($var_prefix) = shift;
+       my($orig_expr) = shift;
+       my $varlist = shift;
 
-       my($fn) = $e->{PARENT};
+       die("Undefined value in ParseExpr") if not defined($orig_expr);
 
-       return $size if (util::is_constant($size));
+       my $expr = $orig_expr;
 
-       return $size if ($size =~ /ndr->|\(/);
+       return $expr if (util::is_constant($expr));
 
        my $prefix = "";
+       my $postfix = "";
 
-       if ($size =~ /\*(.*)/) {
-               $size = $1;
+       if ($expr =~ /\*(.*)/) {
+               $expr = $1;
                $prefix = "*";
        }
 
-       if ($fn->{TYPE} ne "FUNCTION") {
-               return $prefix . "r->$size";
+       if ($expr =~ /^(.*)([\&\|\/+])(.*)$/) {
+               $postfix = $2.$3;
+               $expr = $1;
        }
 
-       my $e2 = util::find_sibling($e, $size);
-
-       die("Invalid sibling '$size'") unless defined($e2);
-
-       if (util::has_property($e2, "in") && util::has_property($e2, "out")) {
-               return $prefix . "$var_prefix$size";
-       }
-       
-       if (util::has_property($e2, "in")) {
-               return $prefix . "r->in.$size";
-       }
-       
-       if (util::has_property($e2, "out")) {
-               return $prefix . "r->out.$size";
+       if (defined($varlist->{$expr})) {
+               return $prefix.$varlist->{$expr}.$postfix;
        }
 
-       die "invalid variable in $size for element $e->{NAME} in $fn->{NAME}\n";
+       return $prefix.$expr.$postfix;
 }
 
 #####################################################################
@@ -189,11 +174,7 @@ sub fn_prefix($)
 {
        my $fn = shift;
 
-       if ($fn->{TYPE} eq "TYPEDEF" or 
-           $fn->{TYPE} eq "FUNCTION") {
-               return "" if (util::has_property($fn, "public"));
-       }
-
+       return "" if (util::has_property($fn, "public"));
        return "static ";
 }
 
@@ -204,7 +185,9 @@ sub start_flags($)
        my $e = shift;
        my $flags = util::has_property($e, "flag");
        if (defined $flags) {
-               pidl "{ uint32_t _flags_save_$e->{TYPE} = ndr->flags;";
+               pidl "{";
+               indent;
+               pidl "uint32_t _flags_save_$e->{TYPE} = ndr->flags;";
                pidl "ndr_set_flags(&ndr->flags, $flags);";
        }
 }
@@ -216,150 +199,135 @@ sub end_flags($)
        my $e = shift;
        my $flags = util::has_property($e, "flag");
        if (defined $flags) {
-               pidl "ndr->flags = _flags_save_$e->{TYPE};\n\t}";
+               pidl "ndr->flags = _flags_save_$e->{TYPE};";
+               deindent;
+               pidl "}";
        }
 }
 
-#####################################################################
-# parse array preceding data - push side
-sub ParseArrayPushPreceding($$$)
+sub GenerateStructEnv($)
 {
-       my $e = shift;
-       my $var_prefix = shift;
-       my $ndr_flags = shift;
-
-       my $size = ParseExpr($e, util::array_size($e), $var_prefix);
+       my $x = shift;
+       my %env;
 
-       if (!Ndr::is_inline_array($e)) {
-               # we need to emit the array size
-               pidl "NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, $size));";
+       foreach my $e (@{$x->{ELEMENTS}}) {
+               $env{$e->{NAME}} = "r->$e->{NAME}";
        }
+
+       $env{"this"} = "r";
+
+       return \%env;
 }
 
-#####################################################################
-# parse the data of an array - push side
-sub ParseArrayPush($$$$)
+sub GenerateFunctionEnv($)
 {
-       my $e = shift;
-       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);
+       my $fn = shift;
+       my %env;
 
-       # See whether the array size has been pushed yet
-       if (!Ndr::is_surrounding_array($e)) {
-               ParseArrayPushPreceding($e, $var_prefix, $ndr_flags);
-       }
-       
-       if (Ndr::is_varying_array($e)) {
-               my $length = util::has_property($e, "length_is");
-               $length = ParseExpr($e, $length, $var_prefix);
-               pidl "NDR_CHECK(ndr_push_uint32($ndr, NDR_SCALARS, 0));";
-               pidl "NDR_CHECK(ndr_push_uint32($ndr, NDR_SCALARS, $length));";
-               $size = $length;
+       foreach my $e (@{$fn->{ELEMENTS}}) {
+               if (grep (/out/, @{$e->{DIRECTION}})) {
+                       $env{$e->{NAME}} = "r->out.$e->{NAME}";
+               }
+               if (grep (/in/, @{$e->{DIRECTION}})) {
+                       $env{$e->{NAME}} = "r->in.$e->{NAME}";
+               }
        }
 
-       if (Ndr::is_scalar_type($e->{TYPE})) {
-               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, $cprefix$var_prefix$e->{NAME}, sizeof($cprefix$var_prefix$e->{NAME}\[0]), $size, (ndr_push_flags_fn_t)ndr_push_$e->{TYPE}));";
-       }
+       return \%env;
 }
 
 #####################################################################
-# print an array
-sub ParseArrayPrint($$)
+# parse array preceding data - push side
+sub ParseArrayPushPreceding($$$$)
 {
        my $e = shift;
-       my $var_prefix = shift;
-       my $size = ParseExpr($e, util::array_size($e), $var_prefix);
-       my $cprefix = c_push_prefix($e);
+       my $l = shift;
+       my $var_name = shift;
+       my $env = shift;
 
-       if (Ndr::is_varying_array($e)) {
-               $size = ParseExpr($e, util::has_property($e, "length_is"), $var_prefix);
-       }
+       return if ($l->{NO_METADATA});
 
-       if (Ndr::is_scalar_type($e->{TYPE})) {
-               pidl "ndr_print_array_$e->{TYPE}(ndr, \"$e->{NAME}\", $cprefix$var_prefix$e->{NAME}, $size);";
-       } else {
-               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});";
-       }
+       my $size = ParseExpr($l->{SIZE_IS}, $env);
+
+       # we need to emit the array size
+       pidl "NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, $size));";
 }
 
 #####################################################################
-# check the size_is and length_is constraints
-sub CheckArraySizes($$)
+# parse the data of an array - push side
+sub ParseArrayPushHeader($$$$$)
 {
        my $e = shift;
-       my $var_prefix = shift;
+       my $l = shift;
+       my $ndr = shift;
+       my $var_name = shift;
+       my $env = shift;
 
-       if (Ndr::is_conformant_array($e)) {
-               my $size = ParseExpr($e, util::array_size($e), $var_prefix);
-               pidl "if ($var_prefix$e->{NAME}) {";
-               indent;
-               check_null_pointer($size);
-               pidl "NDR_CHECK(ndr_check_array_size(ndr, (void*)&$var_prefix$e->{NAME}, $size));";
-               deindent;
-               pidl "}";
+       if (!$l->{NO_METADATA}) {
+               $var_name = get_pointer_to($var_name);
        }
 
-       if (Ndr::is_varying_array($e)) {
-               my $length = util::has_property($e, "length_is");
-               $length = ParseExpr($e, $length, $var_prefix);
-               pidl "if ($var_prefix$e->{NAME}) {";
-               indent;
-               check_null_pointer($length);
-               pidl "NDR_CHECK(ndr_check_array_length(ndr, (void*)&$var_prefix$e->{NAME}, $length));";
-               deindent;
-               pidl "}"
+       my $size = ParseExpr($l->{SIZE_IS}, $env);
+       my $length = ParseExpr($l->{LENGTH_IS}, $env);
+
+       # See whether the array size has been pushed yet
+       if (!$l->{IS_SURROUNDING}) {
+               ParseArrayPushPreceding($e, $l, $var_name, $env);
        }
+       
+       if ($l->{IS_VARYING}) {
+               pidl "NDR_CHECK(ndr_push_uint32($ndr, NDR_SCALARS, 0));";
+               pidl "NDR_CHECK(ndr_push_uint32($ndr, NDR_SCALARS, $length));";
+       } 
+
+       return $length;
 }
 
 sub ParseArrayPullPreceding($$$)
 {
        my $e = shift;
-       my $var_prefix = shift;
-       my $ndr_flags = shift;
+       my $l = shift;
+       my $var_name = shift;
 
-       if (!Ndr::is_inline_array($e)) {
-               # non fixed arrays encode the size just before the array
-               pidl "NDR_CHECK(ndr_pull_array_size(ndr, &$var_prefix$e->{NAME}));";
-       }
+       return if ($l->{NO_METADATA});
+       
+       # non fixed arrays encode the size just before the array
+       pidl "NDR_CHECK(ndr_pull_array_size(ndr, " . get_pointer_to($var_name) . "));";
 }
 
 #####################################################################
 # parse an array - pull side
-sub ParseArrayPull($$$$)
+sub ParseArrayPullHeader($$$$$)
 {
        my $e = shift;
+       my $l = shift;
        my $ndr = shift;
-       my $var_prefix = shift;
-       my $ndr_flags = shift;
+       my $var_name = shift;
+       my $env = shift;
+
+       unless ($l->{NO_METADATA}) {
+               $var_name = get_pointer_to($var_name);
+       }
 
-       my $cprefix = c_pull_prefix($e);
-       my $length = ParseExpr($e, util::array_size($e), $var_prefix);
+       # $var_name contains the name of the first argument here
+
+       my $length = ParseExpr($l->{SIZE_IS}, $env);
        my $size = $length;
 
-       if (Ndr::is_conformant_array($e)) {
-               $length = $size = "ndr_get_array_size($ndr, &$var_prefix$e->{NAME})";
+       if ($l->{IS_CONFORMANT}) {
+               $length = $size = "ndr_get_array_size($ndr, " . get_pointer_to($var_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 (!Ndr::is_inline_array($e) and not Ndr::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 (!$l->{IS_SURROUNDING}) {
+               ParseArrayPullPreceding($e, $l, $var_name);
        }
 
-       if (Ndr::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})";
+
+       if ($l->{IS_VARYING}) {
+               pidl "NDR_CHECK(ndr_pull_array_length($ndr, " . get_pointer_to($var_name) . "));";
+               $length = "ndr_get_array_length($ndr, " . get_pointer_to($var_name) .")";
        }
 
        check_null_pointer($length);
@@ -367,63 +335,66 @@ sub ParseArrayPull($$$$)
        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);";
+               pidl "return ndr_pull_error($ndr, NDR_ERR_ARRAY_SIZE, \"Bad array size %u should exceed array length %u\", $size, $length);";
                deindent;
                pidl "}";
        }
 
-       if ((need_alloc($e) && !Ndr::is_fixed_array($e)) ||
-           ($var_prefix eq "r->in." && util::has_property($e, "ref"))) {
-               if (!Ndr::is_inline_array($e) || $ndr_flags eq "NDR_SCALARS") {
-                       pidl "NDR_ALLOC_N($ndr, $var_prefix$e->{NAME}, $size);";
-               }
+       if ($l->{IS_CONFORMANT}) {
+               my $size = ParseExpr($l->{SIZE_IS}, $env);
+               check_null_pointer($size);
+               pidl "NDR_CHECK(ndr_check_array_size(ndr, (void*)" . get_pointer_to($var_name) . ", $size));";
        }
 
-       if (($var_prefix eq "r->out." && util::has_property($e, "ref"))) {
-               if (!Ndr::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}, $size);";
-                       pidl "}";
-               }
+       if ($l->{IS_VARYING}) {
+               my $length = ParseExpr($l->{LENGTH_IS}, $env);
+               check_null_pointer($length);
+               pidl "NDR_CHECK(ndr_check_array_length(ndr, (void*)" . get_pointer_to($var_name) . ", $length));";
        }
 
-       if (Ndr::is_scalar_type($e->{TYPE})) {
-               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 **)$cprefix$var_prefix$e->{NAME}, sizeof($cprefix$var_prefix$e->{NAME}\[0]), $length, (ndr_pull_flags_fn_t)ndr_pull_$e->{TYPE}));";
+       if (!$l->{IS_FIXED}) {
+               AllocateArrayLevel($e,$l,$ndr,$env,$size);
        }
+
+       return $length;
 }
 
-sub compression_alg($)
+sub compression_alg($$)
 {
        my $e = shift;
-       my $compression = util::has_property($e, "compression");
+       my $l = shift;
+       my $compression = $l->{COMPRESSION};
        my ($alg, $clen, $dlen) = split(/ /, $compression);
 
        return $alg;
 }
 
-sub compression_clen($)
+sub compression_clen($$$)
 {
        my $e = shift;
-       my $compression = util::has_property($e, "compression");
+       my $l = shift;
+       my $env = shift;
+       my $compression = $l->{COMPRESSION};
        my ($alg, $clen, $dlen) = split(/ /, $compression);
 
-       return ParseExpr($e, $clen, "r->");
+       return ParseExpr($clen, $env);
 }
 
-sub compression_dlen($)
+sub compression_dlen($$$)
 {
        my $e = shift;
-       my $compression = util::has_property($e, "compression");
+       my $l = shift;
+       my $env = shift;
+       my $compression = $l->{COMPRESSION};
        my ($alg, $clen, $dlen) = split(/ /, $compression);
 
-       return ParseExpr($e, $dlen, "r->");
+       return ParseExpr($dlen, $env);
 }
 
-sub ParseCompressionPushStart($$)
+sub ParseCompressionPushStart($$$)
 {
        my $e = shift;
+       my $l = shift;
        my $subndr = shift;
        my $comndr = $subndr."_compressed";
 
@@ -439,25 +410,28 @@ sub ParseCompressionPushStart($$)
        return $comndr;
 }
 
-sub ParseCompressionPushEnd($$)
+sub ParseCompressionPushEnd($$$)
 {
        my $e = shift;
+       my $l = shift;
        my $subndr = shift;
        my $comndr = $subndr."_compressed";
-       my $alg = compression_alg($e);
+       my $alg = compression_alg($e, $l);
 
        pidl "NDR_CHECK(ndr_push_compression($subndr, $comndr, $alg));";
        deindent;
        pidl "}";
 }
 
-sub ParseCompressionPullStart($$)
+sub ParseCompressionPullStart($$$$)
 {
        my $e = shift;
+       my $l = shift;
        my $subndr = shift;
+       my $env = shift;
        my $comndr = $subndr."_compressed";
-       my $alg = compression_alg($e);
-       my $dlen = compression_dlen($e);
+       my $alg = compression_alg($e, $l);
+       my $dlen = compression_dlen($e, $l, $env);
 
        pidl "{";
        indent;
@@ -468,9 +442,10 @@ sub ParseCompressionPullStart($$)
        return $comndr;
 }
 
-sub ParseCompressionPullEnd($$)
+sub ParseCompressionPullEnd($$$)
 {
        my $e = shift;
+       my $l = shift;
        my $subndr = shift;
        my $comndr = $subndr."_compressed";
 
@@ -516,113 +491,105 @@ sub ParseObfuscationPullEnd($$)
        # nothing to do here
 }
 
-sub ParseSubcontextPushStart($$)
+sub ParseSubcontextPushStart($$$$$)
 {
        my $e = shift;
+       my $l = shift;
+       my $ndr = shift;
+       my $var_name = shift;
        my $ndr_flags = shift;
-       my $compression = util::has_property($e, "compression");
-       my $obfuscation = util::has_property($e, "obfuscation");
        my $retndr = "_ndr_$e->{NAME}";
 
-       pidl "if (($ndr_flags) & NDR_SCALARS) {";
+       return unless ($ndr_flags =~ /NDR_SCALARS/);
+
+       pidl "{";
        indent;
        pidl "struct ndr_push *$retndr;";
        pidl "";
-       pidl "$retndr = ndr_push_init_ctx(ndr);";
+       pidl "$retndr = ndr_push_init_ctx($ndr);";
        pidl "if (!$retndr) return NT_STATUS_NO_MEMORY;";
-       pidl "$retndr->flags = ndr->flags;";
+       pidl "$retndr->flags = $ndr->flags;";
        pidl "";
 
-       if (defined $compression) {
-               $retndr = ParseCompressionPushStart($e, $retndr);
+       if (defined $l->{COMPRESSION}) {
+               $retndr = ParseCompressionPushStart($e, $l, $retndr);
        }
 
-       if (defined $obfuscation) {
+       if (defined $l->{OBFUSCATION}) {
                $retndr = ParseObfuscationPushStart($e, $retndr);
        }
 
-       return $retndr
+       return $retndr;
 }
 
-sub ParseSubcontextPushEnd($)
+sub ParseSubcontextPushEnd($$$)
 {
        my $e = shift;
-       my $header_size = util::has_property($e, "subcontext");
-       my $size_is = util::has_property($e, "subcontext_size");
-       my $compression = util::has_property($e, "compression");
-       my $obfuscation = util::has_property($e, "obfuscation");
+       my $l = shift;
+       my $ndr_flags = shift;
        my $ndr = "_ndr_$e->{NAME}";
 
-       if (defined $obfuscation) {
-               ParseObfuscationPushEnd($e, $ndr);
-       }
+       return unless ($ndr_flags =~ /NDR_SCALARS/);
 
-       if (defined $compression) {
-               ParseCompressionPushEnd($e, $ndr);
+       if (defined $l->{COMPRESSION}) {
+               ParseCompressionPushEnd($e, $l, $ndr);
        }
 
-       if (not defined($size_is)) {
-               $size_is = "-1";
+       if (defined $l->{OBFUSCATION}) {
+               ParseObfuscationPushEnd($e, $ndr);
        }
 
-       pidl "NDR_CHECK(ndr_push_subcontext_header(ndr, $header_size, $size_is, $ndr));";
+       pidl "NDR_CHECK(ndr_push_subcontext_header(ndr, $l->{HEADER_SIZE}, $l->{SUBCONTEXT_SIZE}, $ndr));";
        pidl "NDR_CHECK(ndr_push_bytes(ndr, $ndr->data, $ndr->offset));";
        deindent;
        pidl "}";
 }
 
-sub ParseSubcontextPullStart($$)
+sub ParseSubcontextPullStart($$$$$$)
 {
        my $e = shift;
-       my $ndr_flags = shift;
-       my $header_size = util::has_property($e, "subcontext");
-       my $size_is = util::has_property($e, "subcontext_size");
-       my $compression = util::has_property($e, "compression");
-       my $obfuscation = util::has_property($e, "obfuscation");
+       my $l = shift;
+       my $ndr = shift;
+       my $var_name = shift;
+       my $ndr_flags = shift;  
+       my $env = shift;
        my $retndr = "_ndr_$e->{NAME}";
 
-       if (not defined($size_is)) {
-               $size_is = "-1";
-       }
-
        pidl "if (($ndr_flags) & NDR_SCALARS) {";
        indent;
        pidl "struct ndr_pull *$retndr;";
        pidl "NDR_ALLOC(ndr, $retndr);";
-       pidl "NDR_CHECK(ndr_pull_subcontext_header(ndr, $header_size, $size_is, $retndr));";
+       pidl "NDR_CHECK(ndr_pull_subcontext_header($ndr, $l->{HEADER_SIZE}, $l->{SUBCONTEXT_SIZE}, $retndr));"; 
 
-       if (defined $compression) {
-               $retndr = ParseCompressionPullStart($e, $retndr);
+       if (defined $l->{COMPRESSION}) {
+               $retndr = ParseCompressionPullStart($e, $l, $retndr, $env);
        }
 
-       if (defined $obfuscation) {
+       if (defined $l->{OBFUSCATION}) {
                $retndr = ParseObfuscationPullStart($e, $retndr);
        }
        
-       return $retndr;
+       return ($retndr,$var_name);
 }
 
-sub ParseSubcontextPullEnd($)
+sub ParseSubcontextPullEnd($$)
 {
        my $e = shift;
-       my $header_size = util::has_property($e, "subcontext");
-       my $size_is = util::has_property($e, "subcontext_size");
-       my $compression = util::has_property($e, "compression");
-       my $obfuscation = util::has_property($e, "obfuscation");
+       my $l = shift;
        my $ndr = "_ndr_$e->{NAME}";
 
-       if (defined $obfuscation) {
-               ParseObfuscationPullEnd($e, $ndr);
+       if (defined $l->{COMPRESSION}) {
+               ParseCompressionPullEnd($e, $l, $ndr);
        }
 
-       if (defined $compression) {
-               ParseCompressionPullEnd($e, $ndr);
+       if (defined $l->{OBFUSCATION}) {
+               ParseObfuscationPullEnd($e, $ndr);
        }
 
        my $advance;
-       if (defined ($size_is)) {
-               $advance = "$size_is";
-       } elsif ($header_size) {
+       if (defined($l->{SUBCONTEXT_SIZE}) and ($l->{SUBCONTEXT_SIZE} ne "-1")) {
+               $advance = $l->{SUBCONTEXT_SIZE};
+       } elsif ($l->{HEADER_SIZE}) {
                $advance = "$ndr->data_size";
        } else {
                $advance = "$ndr->offset";
@@ -632,369 +599,506 @@ sub ParseSubcontextPullEnd($)
        pidl "}";
 }
 
+sub ParseElementPushLevel
+{
+       my $e = shift;
+       my $l = shift;
+       my $ndr = shift;
+       my $var_name = shift;
+       my $env = shift;
+       my $primitives = shift;
+       my $deferred = shift;
+
+       my $ndr_flags = CalcNdrFlags($l, $primitives, $deferred);
+
+       if (defined($ndr_flags)) {
+           if ($l->{TYPE} eq "SUBCONTEXT") {
+                       $ndr = ParseSubcontextPushStart($e, $l, $ndr, $var_name, $ndr_flags);
+                       ParseElementPushLevel($e, Ndr::GetNextLevel($e, $l), $ndr, $var_name, $env, $primitives, $deferred);
+                       ParseSubcontextPushEnd($e, $l, $ndr_flags);
+               } elsif ($l->{TYPE} eq "POINTER") {
+                       ParsePtrPush($e, $l, $var_name);
+               } elsif ($l->{TYPE} eq "ARRAY") {
+                       my $length = ParseArrayPushHeader($e, $l, $ndr, $var_name, $env); 
+                       # Allow speedups for arrays of scalar types
+                       if (is_scalar_array($e,$l)) {
+                               unless ($l->{NO_METADATA}) {
+                                       $var_name = get_pointer_to($var_name);
+                               }
+
+                               pidl "NDR_CHECK(ndr_push_array_$e->{TYPE}($ndr, $ndr_flags, $var_name, $length));";
+                               return;
+                       } 
+               } elsif ($l->{TYPE} eq "SWITCH") {
+                       ParseSwitchPush($e, $l, $ndr, $var_name, $ndr_flags, $env);
+               } elsif ($l->{TYPE} eq "DATA") {
+                       ParseDataPush($e, $l, $ndr, $var_name, $ndr_flags);
+               }
+       }
+
+       if ($l->{TYPE} eq "POINTER" and $deferred) {
+               if ($l->{POINTER_TYPE} ne "ref") {
+                       pidl "if ($var_name) {";
+                       indent;
+                       if ($l->{POINTER_TYPE} eq "relative") {
+                               pidl "NDR_CHECK(ndr_push_relative_ptr2(ndr, $var_name));";
+                       }
+               }
+               $var_name = get_value_of($var_name);
+               ParseElementPushLevel($e, Ndr::GetNextLevel($e, $l), $ndr, $var_name, $env, $primitives, $deferred);
+
+               if ($l->{POINTER_TYPE} ne "ref") {
+                       deindent;
+                       pidl "}";
+               }
+       } elsif ($l->{TYPE} eq "ARRAY" and not is_scalar_array($e,$l)) {
+               my $length = ParseExpr($l->{LENGTH_IS}, $env);
+               my $counter = "cntr_$e->{NAME}_$l->{LEVEL_INDEX}";
+
+               $var_name = $var_name . "[$counter]";
+
+               unless ($l->{NO_METADATA}) {
+                       $var_name = get_pointer_to($var_name);
+               }
+               
+               if (($primitives and not $l->{IS_DEFERRED}) or ($deferred and $l->{IS_DEFERRED})) {
+                       pidl "for ($counter = 0; $counter < $length; $counter++) {";
+                       indent;
+                       ParseElementPushLevel($e, Ndr::GetNextLevel($e, $l), $ndr, $var_name, $env, 1, 0);
+                       deindent;
+                       pidl "}";
+               }
+
+               if ($deferred and Ndr::ContainsDeferred($e, $l)) {
+                       pidl "for ($counter = 0; $counter < $length; $counter++) {";
+                       indent;
+                       ParseElementPushLevel($e, Ndr::GetNextLevel($e, $l), $ndr, $var_name, $env, 0, 1);
+                       deindent;
+                       pidl "}";
+               }       
+       } elsif ($l->{TYPE} eq "SWITCH") {
+               ParseElementPushLevel($e, Ndr::GetNextLevel($e, $l), $ndr, $var_name, $env, $primitives, $deferred);
+       }
+}
+
 #####################################################################
 # parse scalars in a structure element
-sub ParseElementPushScalar($$$)
+sub ParseElementPush($$$$$$)
 {
-       my($e) = shift;
-       my($var_prefix) = shift;
-       my($ndr_flags) = shift;
-       my $cprefix = c_push_prefix($e);
-       my $ptr_prefix = c_ptr_prefix($e);
-       my $sub_size = util::has_property($e, "subcontext");
-       my $ndr = "ndr";
+       my $e = shift;
+       my $ndr = shift;
+       my $var_prefix = shift;
+       my $env = shift;
+       my $primitives = shift;
+       my $deferred = shift;
        my $subndr = undef;
 
-       start_flags($e);
+       my $var_name = $var_prefix.$e->{NAME};
 
-       if (my $value = util::has_property($e, "value")) {
-               pidl "$cprefix$var_prefix$e->{NAME} = $value;";
-       }
+       $var_name = append_prefix($e, $var_name);
 
-       if (defined $sub_size and $e->{POINTERS} == 0) {
-               $subndr = ParseSubcontextPushStart($e, "NDR_SCALARS");
-               $ndr = $subndr;
-       }
+       return unless $primitives or ($deferred and Ndr::ContainsDeferred($e, $e->{LEVELS}[0]));
 
-       if (Ndr::need_wire_pointer($e)) {
-               ParsePtrPush($e, $ptr_prefix.$var_prefix);
-       } elsif (Ndr::is_inline_array($e)) {
-               ParseArrayPush($e, $ndr, "r->", "NDR_SCALARS");
-       } elsif (need_alloc($e)) {
-               # no scalar component
-       } else {
-               if (my $switch = util::has_property($e, "switch_is")) {
-                       ParseSwitchPush($e, $ndr, $var_prefix, $ndr_flags, $switch);
-               }
+       start_flags($e);
 
-               pidl "NDR_CHECK(ndr_push_$e->{TYPE}($ndr, $ndr_flags, $cprefix$var_prefix$e->{NAME}));";
+       if (my $value = util::has_property($e, "value")) {
+               pidl "$var_name = $value;";
        }
 
-       if (defined $sub_size and $e->{POINTERS} == 0) {
-               ParseSubcontextPushEnd($e);
-       }
+       ParseElementPushLevel($e, $e->{LEVELS}[0], $ndr, $var_name, $env, $primitives, $deferred);
 
        end_flags($e);
 }
 
 #####################################################################
 # parse a pointer in a struct element or function
-sub ParsePtrPush($$)
+sub ParsePtrPush($$$)
 {
        my $e = shift;
-       my $var_prefix = shift;
+       my $l = shift;
+       my $var_name = shift;
 
-       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}));";
+       if ($l->{POINTER_TYPE} eq "ref") {
+               if ($l->{LEVEL} eq "EMBEDDED") {
+                       pidl "NDR_CHECK(ndr_push_ref_ptr(ndr, $var_name));";
+               } else {
+                       check_null_pointer(get_value_of($var_name));
+               }
+       } elsif ($l->{POINTER_TYPE} eq "relative") {
+               pidl "NDR_CHECK(ndr_push_relative_ptr1(ndr, $var_name));";
+       } elsif ($l->{POINTER_TYPE} eq "unique") {
+               pidl "NDR_CHECK(ndr_push_unique_ptr(ndr, $var_name));";
        } else {
-               pidl "NDR_CHECK(ndr_push_unique_ptr(ndr, $var_prefix$e->{NAME}));";
+               die("Unhandled pointer type $l->{POINTER_TYPE}");
        }
 }
 
 #####################################################################
 # print scalars in a structure element
-sub ParseElementPrint($$)
+sub ParseElementPrint($$$)
 {
        my($e) = shift;
-       my($var_prefix) = shift;
-       my $cprefix = c_push_prefix($e);
-       my $ptr_prefix = c_ptr_prefix($e);
+       my($var_name) = shift;
+       my $env = shift;
 
+       $var_name = append_prefix($e, $var_name);
        return if (util::has_property($e, "noprint"));
 
        if (my $value = util::has_property($e, "value")) {
                pidl "if (ndr->flags & LIBNDR_PRINT_SET_VALUES) {";
-               pidl "\t$cprefix$var_prefix$e->{NAME} = $value;";
+               pidl "\t$var_name = $value;";
                pidl "}";
        }
 
-       my $l = $e->{POINTERS};
-       $l++ if (util::array_size($e) and $l == 0 and !Ndr::is_fixed_array($e));
+       foreach my $l (@{$e->{LEVELS}}) {
+               if ($l->{TYPE} eq "POINTER") {
+                       pidl "ndr_print_ptr(ndr, \"$e->{NAME}\", $var_name);";
+                       pidl "ndr->depth++;";
+                       if ($l->{POINTER_TYPE} ne "ref") {
+                               pidl "if ($var_name) {";
+                               indent;
+                       }
+                       $var_name = get_value_of($var_name);
+               } elsif ($l->{TYPE} eq "ARRAY") {
+                       my $length = ParseExpr($l->{LENGTH_IS}, $env);
+
+                       if (is_scalar_array($e, $l)) {
+                               unless ($l->{NO_METADATA}){ 
+                                       $var_name = get_pointer_to($var_name); 
+                               }
+                               pidl "ndr_print_array_$e->{TYPE}(ndr, \"$e->{NAME}\", $var_name, $length);";
+                               last;
+                       }
 
-       foreach my $i (1..$l) {
-               pidl "ndr_print_ptr(ndr, \"$e->{NAME}\", $var_prefix$e->{NAME});";
-               pidl "ndr->depth++;";
-               if ($i > $l-Ndr::need_wire_pointer($e)) {
-                       pidl "if ($ptr_prefix$var_prefix$e->{NAME}) {";
+                       my $counter = "cntr_$e->{NAME}_$l->{LEVEL_INDEX}";
+
+                       pidl "ndr->print(ndr, \"\%s: ARRAY(\%d)\", \"$e->{NAME}\", $length);";
+                       pidl 'ndr->depth++;';
+                       pidl "for ($counter=0;$counter<$length;$counter++) {";
+                       indent;
+                       pidl "char *idx_$l->{LEVEL_INDEX}=NULL;";
+                       pidl "asprintf(&idx_$l->{LEVEL_INDEX}, \"[\%d]\", $counter);";
+                       pidl "if (idx_$l->{LEVEL_INDEX}) {";
                        indent;
-               }
-       }
 
-       if (util::array_size($e)) {
-               ParseArrayPrint($e, $var_prefix)
-       } else {
-               if (my $switch = util::has_property($e, "switch_is")) {
-                       my $switch_var = ParseExpr($e, $switch, $var_prefix);
-                       check_null_pointer_void($switch_var);
+                       $var_name = $var_name . "[$counter]";
 
-                       pidl "ndr_print_set_switch_value(ndr, $cprefix$var_prefix$e->{NAME}, $switch_var);";
-               }
+                       unless ($l->{NO_METADATA}){ $var_name = get_pointer_to($var_name); }
 
-               pidl "ndr_print_$e->{TYPE}(ndr, \"$e->{NAME}\", $cprefix$var_prefix$e->{NAME});";
+               } elsif ($l->{TYPE} eq "DATA") {
+                       if (not Ndr::is_scalar_type($l->{DATA_TYPE})) {
+                               $var_name = get_pointer_to($var_name);
+                       }
+                       pidl "ndr_print_$l->{DATA_TYPE}(ndr, \"$e->{NAME}\", $var_name);";
+               } elsif ($l->{TYPE} eq "SWITCH") {
+                       my $switch_var = ParseExpr($l->{SWITCH_IS}, $env);
+                       check_null_pointer_void($switch_var);
+                       pidl "ndr_print_set_switch_value(ndr, " . get_pointer_to($var_name) . ", $switch_var);";
+               } 
        }
 
-       foreach my $i (1..$l) {
-               if ($i > $l-Ndr::need_wire_pointer($e)) {
+       foreach my $l (reverse @{$e->{LEVELS}}) {
+               if ($l->{TYPE} eq "POINTER") {
+                       if ($l->{POINTER_TYPE} ne "ref") {
+                               deindent;
+                               pidl "}";
+                       }
+                       pidl "ndr->depth--;";
+               } elsif ($l->{TYPE} eq "ARRAY" and not is_scalar_array($e, $l)) {
+                       pidl "free(idx_$l->{LEVEL_INDEX});";
                        deindent;
                        pidl "}";
+                       deindent;
+                       pidl "}";
+                       pidl "ndr->depth--;";
                }
-               pidl "ndr->depth--;";
        }
 }
 
 #####################################################################
 # parse scalars in a structure element - pull size
-sub ParseSwitchPull($$$$$)
+sub ParseSwitchPull($$$$$$)
 {
        my($e) = shift;
+       my $l = shift;
        my $ndr = shift;
-       my($var_prefix) = shift;
+       my($var_name) = shift;
        my($ndr_flags) = shift;
-       my $switch = shift;
-       my $switch_var = ParseExpr($e, $switch, $var_prefix);
-
-       my $cprefix = c_pull_prefix($e);
-
-       my $utype = typelist::getType($e->{TYPE});
+       my $env = shift;
+       my $switch_var = ParseExpr($l->{SWITCH_IS}, $env);
 
        check_null_pointer($switch_var);
 
-       pidl "NDR_CHECK(ndr_pull_set_switch_value($ndr, $cprefix$var_prefix$e->{NAME}, $switch_var));";
+       $var_name = get_pointer_to($var_name);
+       pidl "NDR_CHECK(ndr_pull_set_switch_value($ndr, $var_name, $switch_var));";
 
 }
 
 #####################################################################
 # push switch element
-sub ParseSwitchPush($$$$$)
+sub ParseSwitchPush($$$$$$)
 {
        my($e) = shift;
+       my $l = shift;
        my $ndr = shift;
-       my($var_prefix) = shift;
+       my($var_name) = shift;
        my($ndr_flags) = shift;
-       my $switch = shift;
-       my $switch_var = ParseExpr($e, $switch, $var_prefix);
-       my $cprefix = c_push_prefix($e);
+       my $env = shift;
+       my $switch_var = ParseExpr($l->{SWITCH_IS}, $env);
 
        check_null_pointer($switch_var);
-
-       pidl "NDR_CHECK(ndr_push_set_switch_value($ndr, $cprefix$var_prefix$e->{NAME}, $switch_var));";
-
+       $var_name = get_pointer_to($var_name);
+       pidl "NDR_CHECK(ndr_push_set_switch_value($ndr, $var_name, $switch_var));";
 }
 
-#####################################################################
-# parse scalars in a structure element - pull size
-sub ParseElementPullScalar($$$)
+sub ParseDataPull($$$$$)
 {
-       my($e) = shift;
-       my($var_prefix) = shift;
-       my($ndr_flags) = shift;
-       my $cprefix = c_pull_prefix($e);
-       my $ptr_prefix = c_ptr_prefix($e);
-       my $sub_size = util::has_property($e, "subcontext");
-       my $ndr = "ndr";
-       my $subndr = undef;
+       my $e = shift;
+       my $l = shift;
+       my $ndr = shift;
+       my $var_name = shift;
+       my $ndr_flags = shift;
 
-       start_flags($e);
+       $var_name = get_pointer_to($var_name);
 
-       if (defined $sub_size && $e->{POINTERS} == 0) {
-               $subndr = ParseSubcontextPullStart($e, $ndr_flags);
-               $ndr = $subndr;
-               $ndr_flags = "NDR_SCALARS|NDR_BUFFERS";
+       if ($l->{DATA_TYPE} eq "string" or 
+           $l->{DATA_TYPE} eq "nbt_string") {
+               $var_name = get_pointer_to($var_name);
        }
 
-       if (Ndr::is_inline_array($e)) {
-               ParseArrayPull($e, $ndr, "r->", "NDR_SCALARS");
-       } elsif (Ndr::need_wire_pointer($e)) {
-               ParsePtrPull($e, $ptr_prefix.$var_prefix);
-       } elsif (Ndr::is_surrounding_array($e)) {
-       } 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}));";
-       }
+       pidl "NDR_CHECK(ndr_pull_$l->{DATA_TYPE}($ndr, $ndr_flags, $var_name));";
 
        if (my $range = util::has_property($e, "range")) {
+               $var_name = get_value_of($var_name);
                my ($low, $high) = split(/ /, $range, 2);
-               pidl "if ($var_prefix$e->{NAME} < $low || $var_prefix$e->{NAME} > $high) {";
+               pidl "if ($var_name < $low || $var_name > $high) {";
                pidl "\treturn ndr_pull_error($ndr, NDR_ERR_RANGE, \"value out of range\");";
                pidl "}";
        }
-
-       if (defined $sub_size && $e->{POINTERS} == 0) {
-               ParseSubcontextPullEnd($e);
-       }
-
-       end_flags($e);
 }
 
-#####################################################################
-# parse a pointer in a struct element or function
-sub ParsePtrPull($$)
+sub ParseDataPush($$$$$)
 {
-       my($e) = shift;
-       my($var_prefix) = shift;
+       my $e = shift;
+       my $l = shift;
+       my $ndr = shift;
+       my $var_name = shift;
+       my $ndr_flags = shift;
 
-       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}));";
+       # strings are passed by value rather then reference
+       if (not Ndr::is_scalar_type($l->{DATA_TYPE})) {
+               $var_name = get_pointer_to($var_name);
        }
-       pidl "if (_ptr_$e->{NAME}) {";
-       indent;
-       pidl "NDR_ALLOC(ndr, $var_prefix$e->{NAME});";
-       if (util::has_property($e, "relative")) {
-               pidl "NDR_CHECK(ndr_pull_relative_ptr1(ndr, $var_prefix$e->{NAME}, _ptr_$e->{NAME}));";
-       }
-       deindent;
-       pidl "} else {";
-       pidl "\t$var_prefix$e->{NAME} = NULL;";
-       pidl "}";
+
+       pidl "NDR_CHECK(ndr_push_$l->{DATA_TYPE}($ndr, $ndr_flags, $var_name));";
 }
 
-#####################################################################
-# parse buffers in a structure element
-sub ParseElementPushBuffer($$)
+sub CalcNdrFlags($$$)
 {
-       my($e) = shift;
-       my($var_prefix) = shift;
-       my $cprefix = c_push_prefix($e);
-       my $sub_size = util::has_property($e, "subcontext");
-       my $ndr = "ndr";
-       my $subndr = undef;
+       my $l = shift;
+       my $primitives = shift;
+       my $deferred = shift;
 
-       return unless (need_buffers_section($e));
+       my $scalars = 0;
+       my $buffers = 0;
 
-       start_flags($e);
+       # Add NDR_SCALARS if this one is deferred 
+       # and deferreds may be pushed
+       $scalars = 1 if ($l->{IS_DEFERRED} and $deferred);
 
-       my $pointers = c_ptr_prefix($e);
-       for my $i (1..Ndr::need_wire_pointer($e)) {
-               if ($i > 1) {
-                       ParsePtrPush($e,$pointers.$var_prefix);
-               }
-               pidl "if ($pointers$var_prefix$e->{NAME}) {";
-               indent;
-               $pointers.="*";
-       }
+       # Add NDR_SCALARS if this one is not deferred and 
+       # primitives may be pushed
+       $scalars = 1 if (!$l->{IS_DEFERRED} and $primitives);
        
-       if (util::has_property($e, "relative")) {
-               pidl "NDR_CHECK(ndr_push_relative_ptr2(ndr, $var_prefix$e->{NAME}));";
-       }
+       # Add NDR_BUFFERS if this one contains deferred stuff
+       # and deferreds may be pushed
+       $buffers = 1 if ($l->{CONTAINS_DEFERRED} and $deferred);
 
-       my $ndr_flags = "NDR_BUFFERS";
-       if ($e->{POINTERS} || (util::array_size($e) && !Ndr::is_inline_array($e)))
-       {
-               $ndr_flags="NDR_SCALARS|$ndr_flags" 
-       }
+       return "NDR_SCALARS|NDR_BUFFERS" if ($scalars and $buffers);
+       return "NDR_SCALARS" if ($scalars);
+       return "NDR_BUFFERS" if ($buffers);
+       return undef;
+}
 
-       if (defined $sub_size) {
-               $subndr = ParseSubcontextPushStart($e, $ndr_flags);
-               $ndr = $subndr;
-               $ndr_flags = "NDR_SCALARS|NDR_BUFFERS";
+sub ParseElementPullLevel
+{
+       my($e) = shift;
+       my $l = shift;
+       my $ndr = shift;
+       my($var_name) = shift;
+       my $env = shift;
+       my $primitives = shift;
+       my $deferred = shift;
+
+       my $ndr_flags = CalcNdrFlags($l, $primitives, $deferred);
+
+       # Only pull something if there's actually something to be pulled
+       if (defined($ndr_flags)) {
+               if ($l->{TYPE} eq "SUBCONTEXT") {
+                               ($ndr,$var_name) = ParseSubcontextPullStart($e, $l, $ndr, $var_name, $ndr_flags, $env);
+                               ParseElementPullLevel($e,Ndr::GetNextLevel($e,$l), $ndr, $var_name, $env, $primitives, $deferred);
+                               ParseSubcontextPullEnd($e, $l);
+               } elsif ($l->{TYPE} eq "ARRAY") {
+                       my $length = ParseArrayPullHeader($e, $l, $ndr, $var_name, $env); 
+
+                       # Speed things up a little - special array pull functions
+                       # for scalars
+                       if (is_scalar_array($e, $l)) {
+                               unless ($l->{NO_METADATA}) {
+                                       $var_name = get_pointer_to($var_name);
+                               }
+
+                               pidl "NDR_CHECK(ndr_pull_array_$e->{TYPE}($ndr, $ndr_flags, $var_name, $length));";
+                               return;
+                       }
+               } elsif ($l->{TYPE} eq "POINTER") {
+                       ParsePtrPull($e, $l, $ndr, $var_name);
+               } elsif ($l->{TYPE} eq "SWITCH") {
+                       ParseSwitchPull($e, $l, $ndr, $var_name, $ndr_flags, $env);
+               } elsif ($l->{TYPE} eq "DATA") {
+                       ParseDataPull($e, $l, $ndr, $var_name, $ndr_flags);
+               }
        }
 
-       if (util::array_size($e)) {
-               ParseArrayPush($e, $ndr, "r->", $ndr_flags);
-       } else {
-               if (my $switch = util::has_property($e, "switch_is")) {
-                       ParseSwitchPush($e, $ndr, $var_prefix, $ndr_flags, $switch);
+       # add additional constructions
+       if ($l->{TYPE} eq "POINTER" and $deferred) {
+               if ($l->{POINTER_TYPE} ne "ref") {
+                       pidl "if ($var_name) {";
+                       indent;
+
+                       if ($l->{POINTER_TYPE} eq "relative") {
+                               pidl "struct ndr_pull_save _relative_save;";
+                               pidl "ndr_pull_save(ndr, &_relative_save);";
+                               pidl "NDR_CHECK(ndr_pull_relative_ptr2(ndr, $var_name));";
+                       }
                }
 
-               pidl "NDR_CHECK(ndr_push_$e->{TYPE}($ndr, $ndr_flags, $cprefix$var_prefix$e->{NAME}));";
-       }
+               $var_name = get_value_of($var_name);
+               ParseElementPullLevel($e,Ndr::GetNextLevel($e,$l), $ndr, $var_name, $env, $primitives, $deferred);
 
-       if (defined $sub_size) {
-               ParseSubcontextPushEnd($e);
-       }
+               if ($l->{POINTER_TYPE} ne "ref") {
+               if ($l->{POINTER_TYPE} eq "relative") {
+                               pidl "ndr_pull_restore(ndr, &_relative_save);";
+                       }
+                       deindent;
+                       pidl "}";
+               }
+       } elsif ($l->{TYPE} eq "ARRAY" and not is_scalar_array($e,$l)) {
+               my $length = ParseExpr($l->{LENGTH_IS}, $env);
+               my $counter = "cntr_$e->{NAME}_$l->{LEVEL_INDEX}";
 
-       for my $i (1..Ndr::need_wire_pointer($e)) {
-               deindent;
-               pidl "}";
-       }
+               $var_name = $var_name . "[$counter]";
+               unless ($l->{NO_METADATA}) {
+                       $var_name = get_pointer_to($var_name);
+               }
 
-       end_flags($e);
+               if (($primitives and not $l->{IS_DEFERRED}) or ($deferred and $l->{IS_DEFERRED})) {
+                       pidl "for ($counter = 0; $counter < $length; $counter++) {";
+                       indent;
+                       ParseElementPullLevel($e,Ndr::GetNextLevel($e,$l), $ndr, $var_name, $env, 1, 0);
+                       deindent;
+                       pidl "}";
+               }
+
+               if ($deferred and Ndr::ContainsDeferred($e, $l)) {
+                       pidl "for ($counter = 0; $counter < $length; $counter++) {";
+                       indent;
+                       ParseElementPullLevel($e,Ndr::GetNextLevel($e,$l), $ndr, $var_name, $env, 0, 1);
+                       deindent;
+                       pidl "}";
+               }
+       } elsif ($l->{TYPE} eq "SWITCH") {
+               ParseElementPullLevel($e,Ndr::GetNextLevel($e,$l), $ndr, $var_name, $env, $primitives, $deferred);
+       }
 }
 
 #####################################################################
-# parse buffers in a structure element - pull side
-sub ParseElementPullBuffer($$)
+# parse scalars in a structure element - pull size
+sub ParseElementPull($$$$$$)
 {
        my($e) = shift;
+       my $ndr = shift;
        my($var_prefix) = shift;
-       my $cprefix = c_pull_prefix($e);
-       my $sub_size = util::has_property($e, "subcontext");
-       my $ndr = "ndr";
-       my $subndr = undef;
+       my $env = shift;
+       my $primitives = shift;
+       my $deferred = shift;
+
+       my $var_name = $var_prefix.$e->{NAME};
 
-       return unless (need_buffers_section($e));
+       $var_name = append_prefix($e, $var_name);
+
+       return unless $primitives or ($deferred and Ndr::ContainsDeferred($e, $e->{LEVELS}[0]));
 
        start_flags($e);
 
-       my $pointers = c_ptr_prefix($e);
-       for my $i (1..Ndr::need_wire_pointer($e)) {
-               if ($i > 1) {
-                       ParsePtrPull($e,$pointers.$var_prefix);
-               }
-               pidl "if ($pointers$var_prefix$e->{NAME}) {";
-               indent;
-               $pointers.="*";
-       }
-       if (util::has_property($e, "relative")) {
-               pidl "struct ndr_pull_save _relative_save;";
-               pidl "ndr_pull_save(ndr, &_relative_save);";
-               pidl "NDR_CHECK(ndr_pull_relative_ptr2(ndr, $var_prefix$e->{NAME}));";
-       }
-
-       my $ndr_flags = "NDR_BUFFERS";
-       if ($e->{POINTERS} || (util::array_size($e) && !Ndr::is_inline_array($e)))
-       {
-               $ndr_flags="NDR_SCALARS|$ndr_flags" 
-       }
-
-       if (defined $sub_size) {
-               $subndr = ParseSubcontextPullStart($e, $ndr_flags);
-               $ndr = $subndr;
-               $ndr_flags = "NDR_SCALARS|NDR_BUFFERS";
-       }
-
-       if (util::array_size($e)) {
-               ParseArrayPull($e, $ndr, "r->", $ndr_flags);
-       } else {
-               if (my $switch = util::has_property($e, "switch_is")) {
-                       ParseSwitchPull($e, $ndr, $var_prefix, $ndr_flags, $switch);
-               }
+       ParseElementPullLevel($e,$e->{LEVELS}[0],$ndr,$var_name,$env,$primitives,$deferred);
 
-               pidl "NDR_CHECK(ndr_pull_$e->{TYPE}($ndr, $ndr_flags, $cprefix$var_prefix$e->{NAME}));";
-       }
+       end_flags($e);
+}
 
-       if (defined $sub_size) {
-               ParseSubcontextPullEnd($e);
-       }
+#####################################################################
+# parse a pointer in a struct element or function
+sub ParsePtrPull($$$$)
+{
+       my($e) = shift;
+       my $l = shift;
+       my $ndr = shift;
+       my($var_name) = shift;
+
+       my $nl = Ndr::GetNextLevel($e, $l);
+       my $next_is_array = ($nl->{TYPE} eq "ARRAY");
 
-       if (util::has_property($e, "relative")) {
-               pidl "ndr_pull_restore(ndr, &_relative_save);";
+       if ($l->{POINTER_TYPE} eq "ref") {
+               unless ($l->{LEVEL} eq "TOP") {
+                       pidl "NDR_CHECK(ndr_pull_ref_ptr($ndr, &_ptr_$e->{NAME}));";
+               }
+
+               unless ($next_is_array) {
+                       pidl "if (ndr->flags & LIBNDR_FLAG_REF_ALLOC) {";
+                       pidl "\tNDR_ALLOC($ndr, $var_name);"; 
+                       pidl "}";
+               }
+               
+               return;
+       } else {
+               pidl "NDR_CHECK(ndr_pull_unique_ptr($ndr, &_ptr_$e->{NAME}));";
+               pidl "if (_ptr_$e->{NAME}) {";
+               indent;
        }
 
-       for my $i (1..Ndr::need_wire_pointer($e)) {
-               deindent;
-               pidl "}";
+       # Don't do this for arrays, they're allocated at the actual level 
+       # of the array
+       unless ($next_is_array) { 
+               pidl "NDR_ALLOC($ndr, $var_name);"; 
+       } else {
+               pidl "NDR_ALLOC_SIZE($ndr, $var_name, 1);"; # FIXME: Yes, this is nasty. We allocate an array twice - once just to indicate that  it's there, then the real allocation...
        }
 
-       end_flags($e);
+       #pidl "memset($var_name, 0, sizeof($var_name));";
+       if ($l->{POINTER_TYPE} eq "relative") {
+               pidl "NDR_CHECK(ndr_pull_relative_ptr1($ndr, $var_name, _ptr_$e->{NAME}));";
+       }
+       deindent;
+       pidl "} else {";
+       pidl "\t$var_name = NULL;";
+       pidl "}";
 }
 
 #####################################################################
 # parse a struct
-sub ParseStructPush($)
+sub ParseStructPush($$)
 {
        my($struct) = shift;
+       my $name = shift;
        
        return unless defined($struct->{ELEMENTS});
 
+       my $env = GenerateStructEnv($struct);
+
+       foreach my $e (@{$struct->{ELEMENTS}}) { 
+               DeclareArrayVariables($e);
+       }
+
        start_flags($struct);
 
        # see if the structure contains a conformant array. If it
@@ -1003,60 +1107,66 @@ sub ParseStructPush($)
        # the wire before the structure (and even before the structure
        # alignment)
        my $e = $struct->{ELEMENTS}[-1];
-       if (Ndr::is_conformant_array($e) and Ndr::is_surrounding_array($e)) {
-               ParseArrayPushPreceding($e, "r->", "NDR_SCALARS");
-       }
+       if (defined($struct->{SURROUNDING_ELEMENT})) {
+               my $e = $struct->{SURROUNDING_ELEMENT};
 
-       if (defined $e->{TYPE} && $e->{TYPE} eq "string" 
-           &&  util::property_matches($e, "flag", ".*LIBNDR_FLAG_STR_CONFORMANT.*")) {
-               pidl "NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_string_array_size(ndr, r->$e->{NAME})));";
+               if (defined($e->{LEVELS}[0]) and 
+                       $e->{LEVELS}[0]->{TYPE} eq "ARRAY") {
+                       ParseArrayPushPreceding($e, $e->{LEVELS}[0], "r->$e->{NAME}", $env);
+               } else {
+                       pidl "NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_string_array_size(ndr, r->$e->{NAME})));";
+               }
        }
 
-       pidl "if (!(ndr_flags & NDR_SCALARS)) goto buffers;";
+       pidl "if (ndr_flags & NDR_SCALARS) {";
+       indent;
 
        pidl "NDR_CHECK(ndr_push_struct_start(ndr));";
 
-       my $align = Ndr::find_largest_alignment($struct);
-       pidl "NDR_CHECK(ndr_push_align(ndr, $align));";
+       pidl "NDR_CHECK(ndr_push_align(ndr, $struct->{ALIGN}));";
 
        foreach my $e (@{$struct->{ELEMENTS}}) {
-               ParseElementPushScalar($e, "r->", "NDR_SCALARS");
+               ParseElementPush($e, "ndr", "r->", $env, 1, 0);
        }       
 
-       pidl "buffers:";
-       pidl "if (!(ndr_flags & NDR_BUFFERS)) goto done;";
+       deindent;
+       pidl "}";
+
+       pidl "if (ndr_flags & NDR_BUFFERS) {";
+       indent;
        foreach my $e (@{$struct->{ELEMENTS}}) {
-               ParseElementPushBuffer($e, "r->");
+               ParseElementPush($e, "ndr", "r->", $env, 0, 1);
        }
 
        pidl "ndr_push_struct_end(ndr);";
 
-       pidl "done:";
+       deindent;
+       pidl "}";
 
        end_flags($struct);
 }
 
 #####################################################################
 # generate a push function for an enum
-sub ParseEnumPush($)
+sub ParseEnumPush($$)
 {
        my($enum) = shift;
-       my($type_fn) = typelist::enum_type_fn($enum);
+       my $name = shift;
+       my($type_fn) = $enum->{BASE_TYPE};
 
        start_flags($enum);
-
        pidl "NDR_CHECK(ndr_push_$type_fn(ndr, NDR_SCALARS, r));";
-
        end_flags($enum);
 }
 
 #####################################################################
 # generate a pull function for an enum
-sub ParseEnumPull($)
+sub ParseEnumPull($$)
 {
        my($enum) = shift;
-       my($type_fn) = typelist::enum_type_fn($enum);
-       my($type_v_decl) = typelist::mapScalarType(typelist::enum_type_fn($enum));
+       my $name = shift;
+       my($type_fn) = $enum->{BASE_TYPE};
+       my($type_v_decl) = typelist::mapType($type_fn);
 
        pidl "$type_v_decl v;";
        start_flags($enum);
@@ -1068,9 +1178,10 @@ sub ParseEnumPull($)
 
 #####################################################################
 # generate a print function for an enum
-sub ParseEnumPrint($)
+sub ParseEnumPrint($$)
 {
        my($enum) = shift;
+       my $name = shift;
 
        pidl "const char *val = NULL;";
        pidl "";
@@ -1126,10 +1237,11 @@ $typefamily{ENUM} = {
 
 #####################################################################
 # generate a push function for a bitmap
-sub ParseBitmapPush($)
+sub ParseBitmapPush($$)
 {
        my($bitmap) = shift;
-       my($type_fn) = typelist::bitmap_type_fn($bitmap);
+       my $name = shift;
+       my($type_fn) = $bitmap->{BASE_TYPE};
 
        start_flags($bitmap);
 
@@ -1140,11 +1252,12 @@ sub ParseBitmapPush($)
 
 #####################################################################
 # generate a pull function for an bitmap
-sub ParseBitmapPull($)
+sub ParseBitmapPull($$)
 {
        my($bitmap) = shift;
-       my($type_fn) = typelist::bitmap_type_fn($bitmap);
-       my($type_decl) = typelist::mapType($bitmap);
+       my $name = shift;
+       my $type_fn = $bitmap->{BASE_TYPE};
+       my($type_decl) = typelist::mapType($bitmap->{BASE_TYPE});
 
        pidl "$type_decl v;";
        start_flags($bitmap);
@@ -1156,13 +1269,13 @@ sub ParseBitmapPull($)
 
 #####################################################################
 # generate a print function for an bitmap
-sub ParseBitmapPrintElement($$)
+sub ParseBitmapPrintElement($$$)
 {
        my($e) = shift;
        my($bitmap) = shift;
-       my($type_decl) = typelist::mapType($bitmap);
-       my($type_fn) = typelist::bitmap_type_fn($bitmap);
-       my($name) = $bitmap->{PARENT}->{NAME};
+       my($name) = shift;
+       my($type_decl) = typelist::mapType($bitmap->{BASE_TYPE});
+       my($type_fn) = $bitmap->{BASE_TYPE};
        my($flag);
 
        if ($e =~ /^(\w+) .*$/) {
@@ -1176,11 +1289,12 @@ sub ParseBitmapPrintElement($$)
 
 #####################################################################
 # generate a print function for an bitmap
-sub ParseBitmapPrint($)
+sub ParseBitmapPrint($$)
 {
        my($bitmap) = shift;
-       my($type_decl) = typelist::mapType($bitmap);
-       my($type_fn) = typelist::bitmap_type_fn($bitmap);
+       my $name = shift;
+       my($type_decl) = typelist::mapType($bitmap->{TYPE});
+       my($type_fn) = $bitmap->{BASE_TYPE};
 
        start_flags($bitmap);
 
@@ -1188,7 +1302,7 @@ sub ParseBitmapPrint($)
 
        pidl "ndr->depth++;";
        foreach my $e (@{$bitmap->{ELEMENTS}}) {
-               ParseBitmapPrintElement($e, $bitmap);
+               ParseBitmapPrintElement($e, $bitmap, $name);
        }
        pidl "ndr->depth--;";
 
@@ -1198,21 +1312,21 @@ sub ParseBitmapPrint($)
 sub ArgsBitmapPush($)
 {
        my $e = shift;
-       my $type_decl = typelist::mapType($e->{DATA});
+       my $type_decl = typelist::mapType($e->{DATA}->{BASE_TYPE});
        return "struct ndr_push *ndr, int ndr_flags, $type_decl r";
 }
 
 sub ArgsBitmapPrint($)
 {
        my $e = shift;
-       my $type_decl = typelist::mapType($e->{DATA});
+       my $type_decl = typelist::mapType($e->{DATA}->{BASE_TYPE});
        return "struct ndr_print *ndr, const char *name, $type_decl r";
 }
 
 sub ArgsBitmapPull($)
 {
        my $e = shift;
-       my $type_decl = typelist::mapType($e->{DATA});
+       my $type_decl = typelist::mapType($e->{DATA}->{BASE_TYPE});
        return "struct ndr_pull *ndr, int ndr_flags, $type_decl *r";
 }
 
@@ -1227,87 +1341,110 @@ $typefamily{BITMAP} = {
 
 #####################################################################
 # generate a struct print function
-sub ParseStructPrint($)
+sub ParseStructPrint($$)
 {
        my($struct) = shift;
-       my($name) = $struct->{PARENT}->{NAME};
+       my($name) = shift;
 
        return unless defined $struct->{ELEMENTS};
 
+       my $env = GenerateStructEnv($struct);
+
+       foreach my $e (@{$struct->{ELEMENTS}}) {
+               DeclareArrayVariables($e);
+       }
+
        pidl "ndr_print_struct(ndr, name, \"$name\");";
 
        start_flags($struct);
 
        pidl "ndr->depth++;";
        foreach my $e (@{$struct->{ELEMENTS}}) {
-               ParseElementPrint($e, "r->");
+               ParseElementPrint($e, "r->$e->{NAME}", $env);
        }
        pidl "ndr->depth--;";
 
        end_flags($struct);
 }
 
+sub DeclarePtrVariables($)
+{
+       my $e = shift;
+       foreach my $l (@{$e->{LEVELS}}) {
+               if ($l->{TYPE} eq "POINTER" and 
+                       not ($l->{POINTER_TYPE} eq "ref" and $l->{LEVEL} eq "TOP")) {
+                       pidl "uint32_t _ptr_$e->{NAME};";
+                       last;
+               }
+       }
+}
+
+sub DeclareArrayVariables($)
+{
+       my $e = shift;
+
+       foreach my $l (@{$e->{LEVELS}}) {
+               next if (is_scalar_array($e,$l));
+               if ($l->{TYPE} eq "ARRAY") {
+                       pidl "uint32_t cntr_$e->{NAME}_$l->{LEVEL_INDEX};";
+               }
+       }
+}
+
 #####################################################################
 # parse a struct - pull side
-sub ParseStructPull($)
+sub ParseStructPull($$)
 {
        my($struct) = shift;
+       my $name = shift;
        my $conform_e;
 
        return unless defined $struct->{ELEMENTS};
 
+       my $env = GenerateStructEnv($struct);
+
        # 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 pull the conformant length early, as it fits on
        # the wire before the structure (and even before the structure
        # alignment)
-       my $e = $struct->{ELEMENTS}[-1];
-       if (Ndr::is_conformant_array($e) and Ndr::is_surrounding_array($e)) {
-               $conform_e = $e;
-       }
-
-       if (defined $e->{TYPE} && $e->{TYPE} eq "string"
-           &&  util::property_matches($e, "flag", ".*LIBNDR_FLAG_STR_CONFORMANT.*")) {
-               $conform_e = $e;
-       }
+       $conform_e = $struct->{SURROUNDING_ELEMENT};
 
        # declare any internal pointers we need
        foreach my $e (@{$struct->{ELEMENTS}}) {
-               if (Ndr::need_wire_pointer($e)) {
-                       pidl "uint32_t _ptr_$e->{NAME};";
-               }
+               DeclarePtrVariables($e);
+               DeclareArrayVariables($e);
        }
 
        start_flags($struct);
 
-       pidl "if (!(ndr_flags & NDR_SCALARS)) goto buffers;";
+       pidl "if (ndr_flags & NDR_SCALARS) {";
+       indent;
 
        pidl "NDR_CHECK(ndr_pull_struct_start(ndr));";
 
        if (defined $conform_e) {
-               ParseArrayPullPreceding($conform_e, "r->", "NDR_SCALARS");
+               ParseArrayPullPreceding($conform_e, $conform_e->{LEVELS}[0], "r->$conform_e->{NAME}");
        }
 
-       my $align = Ndr::find_largest_alignment($struct);
-       pidl "NDR_CHECK(ndr_pull_align(ndr, $align));";
+       pidl "NDR_CHECK(ndr_pull_align(ndr, $struct->{ALIGN}));";
 
        foreach my $e (@{$struct->{ELEMENTS}}) {
-               ParseElementPullScalar($e, "r->", "NDR_SCALARS");
+               ParseElementPull($e, "ndr", "r->", $env, 1, 0);
        }       
 
-       pidl "buffers:\n";
-       pidl "if (!(ndr_flags & NDR_BUFFERS)) goto done;";
-       foreach my $e (@{$struct->{ELEMENTS}}) {
-               ParseElementPullBuffer($e, "r->");
-       }
-
+       deindent;
+       pidl "}";
+       pidl "if (ndr_flags & NDR_BUFFERS) {";
+       indent;
        foreach my $e (@{$struct->{ELEMENTS}}) {
-               CheckArraySizes($e, "r->");
+               ParseElementPull($e, "ndr", "r->", $env, 0, 1);
        }
 
        pidl "ndr_pull_struct_end(ndr);";
 
-       pidl "done:";
+       deindent;
+       pidl "}";
 
        end_flags($struct);
 }
@@ -1317,7 +1454,6 @@ sub ParseStructPull($)
 sub ParseStructNdrSize($)
 {
        my $t = shift;
-       my $static = fn_prefix($t);
        my $sizevar;
 
        if (my $flags = util::has_property($t, "flag")) {
@@ -1366,7 +1502,6 @@ $typefamily{STRUCT} = {
 sub ParseUnionNdrSize($)
 {
        my $t = shift;
-       my $static = fn_prefix($t);
        my $sizevar;
 
        if (my $flags = util::has_property($t, "flag")) {
@@ -1378,23 +1513,24 @@ sub ParseUnionNdrSize($)
 
 #####################################################################
 # parse a union - push side
-sub ParseUnionPush($)
+sub ParseUnionPush($$)
 {
        my $e = shift;
+       my $name = 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;";
+       pidl "if (ndr_flags & NDR_SCALARS) {";
+       indent;
 
-       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));";
+       if (defined($e->{SWITCH_TYPE})) {
+               pidl "NDR_CHECK(ndr_push_$e->{SWITCH_TYPE}(ndr, NDR_SCALARS, level));";
        }
 
        pidl "NDR_CHECK(ndr_push_struct_start(ndr));";
@@ -1405,16 +1541,15 @@ sub ParseUnionPush($)
        pidl "switch (level) {";
        indent;
        foreach my $el (@{$e->{ELEMENTS}}) {
-               if (util::has_property($el, "default")) {
-                       pidl "default:";
+               if ($el->{CASE} eq "default") {
                        $have_default = 1;
-               } else {
-                       pidl "case $el->{PROPERTIES}->{case}:";
-
                }
+               pidl "$el->{CASE}:";
+
                if ($el->{TYPE} ne "EMPTY") {
                        indent;
-                       ParseElementPushScalar($el, "r->", "NDR_SCALARS");
+                       DeclareArrayVariables($el);
+                       ParseElementPush($el, "ndr", "r->", {}, 1, 0);
                        deindent;
                }
                pidl "break;";
@@ -1426,19 +1561,17 @@ sub ParseUnionPush($)
        }
        deindent;
        pidl "}";
-       pidl "buffers:";
-       pidl "if (!(ndr_flags & NDR_BUFFERS)) goto done;";
+       deindent;
+       pidl "}";
+       pidl "if (ndr_flags & NDR_BUFFERS) {";
+       indent;
        pidl "switch (level) {";
        indent;
        foreach my $el (@{$e->{ELEMENTS}}) {
-               if (util::has_property($el, "default")) {
-                       pidl "default:";
-               } else {
-                       pidl "case $el->{PROPERTIES}->{case}:";
-               }
+               pidl "$el->{CASE}:";
                if ($el->{TYPE} ne "EMPTY") {
                        indent;
-                       ParseElementPushBuffer($el, "r->");
+                       ParseElementPush($el, "ndr", "r->", {}, 0, 1);
                        deindent;
                }
                pidl "break;";
@@ -1451,35 +1584,38 @@ sub ParseUnionPush($)
        deindent;
        pidl "}";
        pidl "ndr_push_struct_end(ndr);";
-       pidl "done:";
+       deindent;
+       pidl "}";
        end_flags($e);
 }
 
 #####################################################################
 # print a union
-sub ParseUnionPrint($)
+sub ParseUnionPrint($$)
 {
        my $e = shift;
        my $have_default = 0;
-       my($name) = $e->{PARENT}->{NAME};
+       my $name = shift;
 
        pidl "int level = ndr_print_get_switch_value(ndr, r);";
 
+       foreach my $el (@{$e->{ELEMENTS}}) {
+               DeclareArrayVariables($el);
+       }
+
        pidl "ndr_print_union(ndr, name, level, \"$name\");";
        start_flags($e);
 
        pidl "switch (level) {";
        indent;
        foreach my $el (@{$e->{ELEMENTS}}) {
-               if (util::has_property($el, "default")) {
+               if ($el->{CASE} eq "default") {
                        $have_default = 1;
-                       pidl "default:";
-               } else {
-                       pidl "case $el->{PROPERTIES}->{case}:";
                }
+               pidl "$el->{CASE}:";
                if ($el->{TYPE} ne "EMPTY") {
                        indent;
-                       ParseElementPrint($el, "r->");
+                       ParseElementPrint($el, "r->$el->{NAME}", {});
                        deindent;
                }
                pidl "break;";
@@ -1497,31 +1633,32 @@ sub ParseUnionPrint($)
 
 #####################################################################
 # parse a union - pull side
-sub ParseUnionPull($)
+sub ParseUnionPull($$)
 {
        my $e = shift;
+       my $name = shift;
        my $have_default = 0;
-       my $switch_type = util::has_property($e, "switch_type");
-       $switch_type = "uint32" unless defined($switch_type);
+       my $switch_type = $e->{SWITCH_TYPE};
 
        pidl "int level;";
-       if (!util::has_property($e, "nodiscriminant")) {
+       if (defined($switch_type)) {
                if (typelist::typeIs($switch_type, "ENUM")) {
                        $switch_type = typelist::enum_type_fn(typelist::getType($switch_type));
                }
-               pidl typelist::mapScalarType($switch_type) . " _level;";
+               pidl typelist::mapType($switch_type) . " _level;";
        }
 
        start_flags($e);
 
        pidl "level = ndr_pull_get_switch_value(ndr, r);";
 
-       pidl "if (!(ndr_flags & NDR_SCALARS)) goto buffers;";
+       pidl "if (ndr_flags & NDR_SCALARS) {";
+       indent;
 
-       if (!util::has_property($e, "nodiscriminant")) {
+       if (defined($switch_type)) {
                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 "\treturn ndr_pull_error(ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value %u for $name\", _level);";
                pidl "}";
        }
 
@@ -1533,18 +1670,16 @@ sub ParseUnionPull($)
        pidl "switch (level) {";
        indent;
        foreach my $el (@{$e->{ELEMENTS}}) {
-               if (util::has_property($el, "default")) {
-                       pidl "default: {";
+               if ($el->{CASE} eq "default") {
                        $have_default = 1;
-               } else {
-                       pidl "case $el->{PROPERTIES}->{case}: {";
-               }
+               } 
+               pidl "$el->{CASE}: {";
+
                if ($el->{TYPE} ne "EMPTY") {
                        indent;
-                       if ($el->{POINTERS}) {
-                               pidl "uint32_t _ptr_$el->{NAME};";
-                       }
-                       ParseElementPullScalar($el, "r->", "NDR_SCALARS");
+                       DeclarePtrVariables($el);
+                       DeclareArrayVariables($el);
+                       ParseElementPull($el, "ndr", "r->", {}, 1, 0);
                        deindent;
                }
                pidl "break; }";
@@ -1556,19 +1691,17 @@ sub ParseUnionPull($)
        }
        deindent;
        pidl "}";
-       pidl "buffers:";
-       pidl "if (!(ndr_flags & NDR_BUFFERS)) goto done;";
+       deindent;
+       pidl "}";
+       pidl "if (ndr_flags & NDR_BUFFERS) {";
+       indent;
        pidl "switch (level) {";
        indent;
        foreach my $el (@{$e->{ELEMENTS}}) {
-               if (util::has_property($el, "default")) {
-                       pidl "default:";
-               } else {
-                       pidl "case $el->{PROPERTIES}->{case}:";
-               }
+               pidl "$el->{CASE}:";
                if ($el->{TYPE} ne "EMPTY") {
                        indent;
-                       ParseElementPullBuffer($el, "r->");
+                       ParseElementPull($el, "ndr", "r->", {}, 0, 1);
                        deindent;
                }
                pidl "break;";
@@ -1581,7 +1714,8 @@ sub ParseUnionPull($)
        deindent;
        pidl "}";
        pidl "ndr_pull_struct_end(ndr);";
-       pidl "done:";
+       deindent;
+       pidl "}";
        end_flags($e);
 }
 
@@ -1625,39 +1759,32 @@ $typefamily{UNION} = {
 sub ParseTypedefPush($)
 {
        my($e) = shift;
-       my $static = fn_prefix($e);
-
-       return unless needed::is_needed("push_$e->{NAME}");
 
        my $args = $typefamily{$e->{DATA}->{TYPE}}->{PUSH_FN_ARGS}->($e);
-       pidl $static . "NTSTATUS ndr_push_$e->{NAME}($args)";
+       pidl fn_prefix($e) . "NTSTATUS ndr_push_$e->{NAME}($args)";
 
        pidl "{";
        indent;
-       $typefamily{$e->{DATA}->{TYPE}}->{PUSH_FN_BODY}->($e->{DATA});
+       $typefamily{$e->{DATA}->{TYPE}}->{PUSH_FN_BODY}->($e->{DATA}, $e->{NAME});
        pidl "return NT_STATUS_OK;";
        deindent;
        pidl "}";
        pidl "";;
 }
 
-
 #####################################################################
 # parse a typedef - pull side
 sub ParseTypedefPull($)
 {
        my($e) = shift;
-       my $static = fn_prefix($e);
-
-       return unless needed::is_needed("pull_$e->{NAME}");
 
        my $args = $typefamily{$e->{DATA}->{TYPE}}->{PULL_FN_ARGS}->($e);
 
-       pidl $static . "NTSTATUS ndr_pull_$e->{NAME}($args)";
+       pidl fn_prefix($e) . "NTSTATUS ndr_pull_$e->{NAME}($args)";
 
        pidl "{";
        indent;
-       $typefamily{$e->{DATA}->{TYPE}}->{PULL_FN_BODY}->($e->{DATA});
+       $typefamily{$e->{DATA}->{TYPE}}->{PULL_FN_BODY}->($e->{DATA}, $e->{NAME});
        pidl "return NT_STATUS_OK;";
        deindent;
        pidl "}";
@@ -1672,12 +1799,10 @@ sub ParseTypedefPrint($)
 
        my $args = $typefamily{$e->{DATA}->{TYPE}}->{PRINT_FN_ARGS}->($e);
 
-       return unless !util::has_property($e, "noprint");
-
        pidl "void ndr_print_$e->{NAME}($args)";
        pidl "{";
        indent;
-       $typefamily{$e->{DATA}->{TYPE}}->{PRINT_FN_BODY}->($e->{DATA});
+       $typefamily{$e->{DATA}->{TYPE}}->{PRINT_FN_BODY}->($e->{DATA}, $e->{NAME});
        deindent;
        pidl "}";
        pidl "";
@@ -1689,8 +1814,6 @@ sub ParseTypedefNdrSize($)
 {
        my($t) = shift;
 
-       return unless needed::is_needed("ndr_size_$t->{NAME}");
-
        my $tf = $typefamily{$t->{DATA}->{TYPE}};
        my $args = $tf->{SIZE_FN_ARGS}->($t);
 
@@ -1709,11 +1832,18 @@ sub ParseFunctionPrint($)
 {
        my($fn) = shift;
 
-       return unless !util::has_property($fn, "noprint");
+       return if util::has_property($fn, "noprint");
+
+       my $env = GenerateFunctionEnv($fn);
 
        pidl "void ndr_print_$fn->{NAME}(struct ndr_print *ndr, const char *name, int flags, struct $fn->{NAME} *r)";
        pidl "{";
        indent;
+
+       foreach my $e (@{$fn->{ELEMENTS}}) {
+               DeclareArrayVariables($e);
+       }
+
        pidl "ndr_print_struct(ndr, name, \"$fn->{NAME}\");";
        pidl "ndr->depth++;";
 
@@ -1727,8 +1857,8 @@ sub ParseFunctionPrint($)
        pidl "ndr->depth++;";
 
        foreach my $e (@{$fn->{ELEMENTS}}) {
-               if (util::has_property($e, "in")) {
-                       ParseElementPrint($e, "r->in.");
+               if (grep(/in/,@{$e->{DIRECTION}})) {
+                       ParseElementPrint($e, "r->in.$e->{NAME}", $env);
                }
        }
        pidl "ndr->depth--;";
@@ -1740,14 +1870,12 @@ sub ParseFunctionPrint($)
        pidl "ndr_print_struct(ndr, \"out\", \"$fn->{NAME}\");";
        pidl "ndr->depth++;";
        foreach my $e (@{$fn->{ELEMENTS}}) {
-               if (util::has_property($e, "out")) {
-                       ParseElementPrint($e, "r->out.");
+               if (grep(/out/,@{$e->{DIRECTION}})) {
+                       ParseElementPrint($e, "r->out.$e->{NAME}", $env);
                }
        }
-       if ($fn->{RETURN_TYPE} && $fn->{RETURN_TYPE} ne "void") {
-               my $cprefix = "&";
-               $cprefix = "" if (Ndr::is_scalar_type($fn->{RETURN_TYPE})) ; # FIXME: Should really use util::c_push_prefix here
-               pidl "ndr_print_$fn->{RETURN_TYPE}(ndr, \"result\", $cprefix"."r->out.result);";
+       if ($fn->{RETURN_TYPE}) {
+               pidl "ndr_print_$fn->{RETURN_TYPE}(ndr, \"result\", r->out.result);";
        }
        pidl "ndr->depth--;";
        deindent;
@@ -1759,153 +1887,82 @@ sub ParseFunctionPrint($)
        pidl "";
 }
 
-#####################################################################
-# parse a function element
-sub ParseFunctionElementPush($$)
-{ 
-       my $e = shift;
-       my $inout = shift;
-
-       if (util::array_size($e)) {
-               if (Ndr::need_wire_pointer($e)) {
-                       ParsePtrPush($e, "r->$inout.");
-                       pidl "if (r->$inout.$e->{NAME}) {";
-                       indent;
-                       ParseArrayPush($e, "ndr", "r->$inout.", "NDR_SCALARS|NDR_BUFFERS");
-                       deindent;
-                       pidl "}";
-               } else {
-                       ParseArrayPush($e, "ndr", "r->$inout.", "NDR_SCALARS|NDR_BUFFERS");
-               }
-       } else {
-               ParseElementPushScalar($e, "r->$inout.", "NDR_SCALARS|NDR_BUFFERS");
-               if (Ndr::need_wire_pointer($e)) {
-                       ParseElementPushBuffer($e, "r->$inout.");
-               }
-       }
-}      
-
 #####################################################################
 # parse a function
 sub ParseFunctionPush($)
 { 
        my($fn) = shift;
-       my $static = fn_prefix($fn);
 
-       return unless !util::has_property($fn, "nopush");
+       return if util::has_property($fn, "nopush");
+
+       my $env = GenerateFunctionEnv($fn);
 
-       pidl $static . "NTSTATUS ndr_push_$fn->{NAME}(struct ndr_push *ndr, int flags, struct $fn->{NAME} *r)";
+       pidl fn_prefix($fn) . "NTSTATUS ndr_push_$fn->{NAME}(struct ndr_push *ndr, int flags, struct $fn->{NAME} *r)";
        pidl "{";
        indent;
 
-       pidl "if (!(flags & NDR_IN)) goto ndr_out;";
-       pidl "";
+       foreach my $e (@{$fn->{ELEMENTS}}) { 
+               DeclareArrayVariables($e);
+       }
+
+       pidl "if (flags & NDR_IN) {";
+       indent;
 
        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");
-               }               
+               if (grep(/in/,@{$e->{DIRECTION}})) {
+                       ParseElementPush($e, "ndr", "r->in.", $env, 1, 1);
+               }
        }
 
-       pidl "ndr_out:";
-       pidl "if (!(flags & NDR_OUT)) goto done;";
-       pidl "";
+       deindent;
+       pidl "}";
+
+       pidl "if (flags & NDR_OUT) {";
+       indent;
 
        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");
-               }               
+               if (grep(/out/,@{$e->{DIRECTION}})) {
+                       ParseElementPush($e, "ndr", "r->out.", $env, 1, 1);
+               }
        }
 
-       if ($fn->{RETURN_TYPE} && $fn->{RETURN_TYPE} ne "void") {
+       if ($fn->{RETURN_TYPE}) {
                pidl "NDR_CHECK(ndr_push_$fn->{RETURN_TYPE}(ndr, NDR_SCALARS, r->out.result));";
        }
     
-       pidl "done:";
+       deindent;
+       pidl "}";
        pidl "return NT_STATUS_OK;";
        deindent;
        pidl "}";
        pidl "";
 }
 
-#####################################################################
-# parse a function element
-sub ParseFunctionElementPull($$)
-{ 
-       my $e = shift;
-       my $inout = shift;
-
-       if (util::array_size($e)) {
-               if (Ndr::need_wire_pointer($e)) {
-                       pidl "NDR_CHECK(ndr_pull_unique_ptr(ndr, &_ptr_$e->{NAME}));";
-                       pidl "r->$inout.$e->{NAME} = NULL;";
-                       pidl "if (_ptr_$e->{NAME}) {";
-                       indent;
-               } elsif ($inout eq "out" && util::has_property($e, "ref")) {
-                       pidl "if (r->$inout.$e->{NAME}) {";
-                       indent;
-               }
-
-               ParseArrayPull($e, "ndr", "r->$inout.", "NDR_SCALARS|NDR_BUFFERS");
-
-               if (Ndr::need_wire_pointer($e) or ($inout eq "out" and util::has_property($e, "ref"))) {
-                       deindent;
-                       pidl "}";
-               }
-       } else {
-               if ($inout eq "out" && util::has_property($e, "ref")) {
-                       pidl "if (ndr->flags & LIBNDR_FLAG_REF_ALLOC) {";
-                       pidl "\tNDR_ALLOC(ndr, r->out.$e->{NAME});";
-                       pidl "}";
-               }
-
-               if ($inout eq "in" && util::has_property($e, "ref")) {
-                       pidl "NDR_ALLOC(ndr, r->in.$e->{NAME});";
-               }
-
-               ParseElementPullScalar($e, "r->$inout.", "NDR_SCALARS|NDR_BUFFERS");
-               if (Ndr::need_wire_pointer($e)) {
-                       ParseElementPullBuffer($e, "r->$inout.");
-               }
-       }
-}
-
-############################################################
-# allocate ref variables
-sub AllocateRefVars($)
+sub AllocateArrayLevel($$$$$)
 {
        my $e = shift;
-       my $asize = util::array_size($e);
-
-       # note that if the variable is also an "in"
-       # variable then we copy the initial value from
-       # the in side
+       my $l = shift;
+       my $ndr = shift;
+       my $env = shift;
+       my $size = shift;
 
-       if (!defined $asize) {
-               # its a simple variable
-               pidl "NDR_ALLOC(ndr, r->out.$e->{NAME});";
-               if (util::has_property($e, "in")) {
-                       pidl "*r->out.$e->{NAME} = *r->in.$e->{NAME};";
-               } else {
-                       pidl "ZERO_STRUCTP(r->out.$e->{NAME});";
-               }
-               return;
-       }
+       my $var = ParseExpr($e->{NAME}, $env);
 
-       # its an array
-       my $size = ParseExpr($e, $asize, "r->out.");
        check_null_pointer($size);
-       pidl "NDR_ALLOC_N(ndr, r->out.$e->{NAME}, $size);";
-       if (util::has_property($e, "in")) {
-               pidl "memcpy(r->out.$e->{NAME},r->in.$e->{NAME},$size * sizeof(*r->in.$e->{NAME}));";
+       my $pl = Ndr::GetPrevLevel($e, $l);
+       if (defined($pl) and 
+           $pl->{TYPE} eq "POINTER" and 
+           $pl->{POINTER_TYPE} eq "ref") {
+           pidl "if (ndr->flags & LIBNDR_FLAG_REF_ALLOC) {";
+           pidl "\tNDR_ALLOC_N($ndr, $var, $size);";
+           pidl "}";
        } else {
-               pidl "memset(r->out.$e->{NAME}, 0, $size * sizeof(*r->out.$e->{NAME}));";
+               pidl "NDR_ALLOC_N($ndr, $var, $size);";
+       }
+       #pidl "memset($var, 0, $size * sizeof(" . $var . "[0]));";
+       if (grep(/in/,@{$e->{DIRECTION}}) and
+           grep(/out/,@{$e->{DIRECTION}})) {
+               pidl "memcpy(r->out.$e->{NAME},r->in.$e->{NAME},$size * sizeof(*r->in.$e->{NAME}));";
        }
 }
 
@@ -1914,76 +1971,89 @@ sub AllocateRefVars($)
 sub ParseFunctionPull($)
 { 
        my($fn) = shift;
-       my $static = fn_prefix($fn);
 
-       return unless !util::has_property($fn, "nopull");
+       return if util::has_property($fn, "nopull");
+
+       my $env = GenerateFunctionEnv($fn);
 
        # pull function args
-       pidl $static . "NTSTATUS ndr_pull_$fn->{NAME}(struct ndr_pull *ndr, int flags, struct $fn->{NAME} *r)";
+       pidl fn_prefix($fn) . "NTSTATUS ndr_pull_$fn->{NAME}(struct ndr_pull *ndr, int flags, struct $fn->{NAME} *r)";
        pidl "{";
        indent;
 
        # declare any internal pointers we need
-       foreach my $e (@{$fn->{ELEMENTS}}) {
-               if (Ndr::need_wire_pointer($e)) {
-                       pidl "uint32_t _ptr_$e->{NAME};";
-               }
+       foreach my $e (@{$fn->{ELEMENTS}}) { 
+               DeclarePtrVariables($e); 
+               DeclareArrayVariables($e);
        }
 
-       pidl "if (!(flags & NDR_IN)) goto ndr_out;";
-       pidl "";
+       pidl "if (flags & NDR_IN) {";
+       indent;
 
        # auto-init the out section of a structure. I originally argued that
        # this was a bad idea as it hides bugs, but coping correctly
        # with initialisation and not wiping ref vars is turning
        # out to be too tricky (tridge)
        foreach my $e (@{$fn->{ELEMENTS}}) {
-               if (util::has_property($e, "out")) {
-                       pidl "ZERO_STRUCT(r->out);";
-                       pidl "";
-                       last;
-               }
+               next unless grep(/out/, @{$e->{DIRECTION}});
+               pidl "ZERO_STRUCT(r->out);";
+               pidl "";
+               last;
        }
 
        foreach my $e (@{$fn->{ELEMENTS}}) {
-               if (util::has_property($e, "in")) {
-                       ParseFunctionElementPull($e, "in");
-               }
-               # we need to allocate any reference output variables, so that
-               # a dcerpc backend can be sure they are non-null
-               if (util::has_property($e, "out") && util::has_property($e, "ref")) {
-                       AllocateRefVars($e);
-               }
+               next unless (grep(/in/, @{$e->{DIRECTION}}));
+               ParseElementPull($e, "ndr", "r->in.", $env, 1, 1);
        }
 
+       # allocate the "simple" out ref variables. FIXME: Shouldn't this have it's
+       # own flag rather then be in NDR_IN ?
+
        foreach my $e (@{$fn->{ELEMENTS}}) {
-               if (util::has_property($e, "in")) {
-                       CheckArraySizes($e, "r->in.");
-               }
-       }
+               next unless (grep(/out/, @{$e->{DIRECTION}}));
+               next unless ($e->{LEVELS}[0]->{TYPE} eq "POINTER" and 
+                            $e->{LEVELS}[0]->{POINTER_TYPE} eq "ref");
 
-       pidl "ndr_out:";
-       pidl "if (!(flags & NDR_OUT)) goto done;";
-       pidl "";
 
-       foreach my $e (@{$fn->{ELEMENTS}}) {
-               if (util::has_property($e, "out")) {
-                       ParseFunctionElementPull($e, "out");
+               if ($e->{LEVELS}[1]->{TYPE} eq "ARRAY") {
+                       my $size = ParseExpr($e->{LEVELS}[1]->{SIZE_IS}, $env);
+                       check_null_pointer($size);
+                       
+                       pidl "NDR_ALLOC_N(ndr, r->out.$e->{NAME}, $size);";
+
+                       if (grep(/in/, @{$e->{DIRECTION}})) {
+                               pidl "memcpy(r->out.$e->{NAME}, r->in.$e->{NAME}, $size * sizeof(*r->in.$e->{NAME}));";
+                       } else {
+                               pidl "memset(r->out.$e->{NAME}, 0, $size * sizeof(*r->out.$e->{NAME}));";
+                       }
+               } else {
+                       pidl "NDR_ALLOC(ndr, r->out.$e->{NAME});";
+               
+                       if (grep(/in/, @{$e->{DIRECTION}})) {
+                               pidl "*r->out.$e->{NAME} = *r->in.$e->{NAME};";
+                       } else {
+                               pidl "ZERO_STRUCTP(r->out.$e->{NAME});";
+                       }
                }
        }
 
+       deindent;
+       pidl "}";
+       
+       pidl "if (flags & NDR_OUT) {";
+       indent;
+
        foreach my $e (@{$fn->{ELEMENTS}}) {
-               if (util::has_property($e, "out")) {
-                       CheckArraySizes($e, "r->out.");
-               }
+               next unless grep(/out/, @{$e->{DIRECTION}});
+               ParseElementPull($e, "ndr", "r->out.", $env, 1, 1);
        }
 
-       if ($fn->{RETURN_TYPE} && $fn->{RETURN_TYPE} ne "void") {
+       if ($fn->{RETURN_TYPE}) {
                pidl "NDR_CHECK(ndr_pull_$fn->{RETURN_TYPE}(ndr, NDR_SCALARS, &r->out.result));";
        }
 
-       pidl "done:";
-       pidl "";
+       deindent;
+       pidl "}";
        pidl "return NT_STATUS_OK;";
        deindent;
        pidl "}";
@@ -1995,44 +2065,33 @@ sub ParseFunctionPull($)
 sub FunctionTable($)
 {
        my($interface) = shift;
-       my($data) = $interface->{INHERITED_DATA};
        my $count = 0;
        my $uname = uc $interface->{NAME};
 
-       foreach my $d (@{$data}) {
-               if ($d->{TYPE} eq "FUNCTION") { $count++; }
-       }
+       $count = $#{$interface->{FUNCTIONS}}+1;
 
        return if ($count == 0);
 
        pidl "static const struct dcerpc_interface_call $interface->{NAME}\_calls[] = {";
-       foreach my $d (@{$data}) {
-               if ($d->{TYPE} eq "FUNCTION") {
-                       pidl "\t{";
-                       pidl "\t\t\"$d->{NAME}\",";
-                       pidl "\t\tsizeof(struct $d->{NAME}),";
-                       pidl "\t\t(ndr_push_flags_fn_t) ndr_push_$d->{NAME},";
-                       pidl "\t\t(ndr_pull_flags_fn_t) ndr_pull_$d->{NAME},";
-                       pidl "\t\t(ndr_print_function_t) ndr_print_$d->{NAME}";
-                       pidl "\t},";
-               }
+       foreach my $d (@{$interface->{FUNCTIONS}}) {
+               pidl "\t{";
+               pidl "\t\t\"$d->{NAME}\",";
+               pidl "\t\tsizeof(struct $d->{NAME}),";
+               pidl "\t\t(ndr_push_flags_fn_t) ndr_push_$d->{NAME},";
+               pidl "\t\t(ndr_pull_flags_fn_t) ndr_pull_$d->{NAME},";
+               pidl "\t\t(ndr_print_function_t) ndr_print_$d->{NAME}";
+               pidl "\t},";
        }
        pidl "\t{ NULL, 0, NULL, NULL, NULL }";
        pidl "};";
        pidl "";
 
-       # If no endpoint is set, default to the interface name as a named pipe
-       if (! defined $interface->{PROPERTIES}->{endpoint}) {
-               $interface->{PROPERTIES}->{endpoint} = "\"ncacn_np:[\\\\pipe\\\\" . $interface->{NAME} . "]\"";
-       }
-
-       my @e = split / /, $interface->{PROPERTIES}->{endpoint};
-       my $endpoint_count = $#e + 1;
-
        pidl "static const char * const $interface->{NAME}\_endpoint_strings[] = {";
-       foreach my $ep (@e) {
+       foreach my $ep (@{$interface->{ENDPOINTS}}) {
                pidl "\t$ep, ";
        }
+       my $endpoint_count = $#{$interface->{ENDPOINTS}}+1;
+       
        pidl "};";
        pidl "";
 
@@ -2083,27 +2142,33 @@ sub FunctionTable($)
 
 #####################################################################
 # parse the interface definitions
-sub ParseInterface($)
+sub ParseInterface($$)
 {
        my($interface) = shift;
-       my($data) = $interface->{DATA};
-
-       # Push functions
-       foreach my $d (@{$data}) {
-               if ($d->{TYPE} eq "TYPEDEF") {
-                   ParseTypedefPush($d);
-                   ParseTypedefPull($d);
-                       ParseTypedefPrint($d);
-                       ParseTypedefNdrSize($d);
-               }
+       my $needed = shift;
+
+       # Typedefs
+       foreach my $d (@{$interface->{TYPEDEFS}}) {
+               ($needed->{"push_$d->{NAME}"}) && ParseTypedefPush($d);
+               ($needed->{"pull_$d->{NAME}"}) && ParseTypedefPull($d);
+               ($needed->{"print_$d->{NAME}"}) && ParseTypedefPrint($d);
+
+               # Make sure we don't generate a function twice...
+               $needed->{"push_$d->{NAME}"} = $needed->{"pull_$d->{NAME}"} = 
+                       $needed->{"print_$d->{NAME}"} = 0;
+
+               ($needed->{"ndr_size_$d->{NAME}"}) && ParseTypedefNdrSize($d);
        }
 
-       foreach my $d (@{$data}) {
-               if ($d->{TYPE} eq "FUNCTION") {
-                   ParseFunctionPush($d);
-                   ParseFunctionPull($d);
-                       ParseFunctionPrint($d);
-               }
+       # Functions
+       foreach my $d (@{$interface->{FUNCTIONS}}) {
+               ($needed->{"push_$d->{NAME}"}) && ParseFunctionPush($d);
+               ($needed->{"pull_$d->{NAME}"}) && ParseFunctionPull($d);
+               ($needed->{"print_$d->{NAME}"}) && ParseFunctionPrint($d);
+
+               # Make sure we don't generate a function twice...
+               $needed->{"push_$d->{NAME}"} = $needed->{"pull_$d->{NAME}"} = 
+                       $needed->{"print_$d->{NAME}"} = 0;
        }
 
        FunctionTable($interface);
@@ -2123,11 +2188,7 @@ sub RegistrationFunction($$)
        foreach my $interface (@{$idl}) {
                next if $interface->{TYPE} ne "INTERFACE";
 
-               my $data = $interface->{INHERITED_DATA};
-               my $count = 0;
-               foreach my $d (@{$data}) {
-                       if ($d->{TYPE} eq "FUNCTION") { $count++; }
-               }
+               my $count = ($#{$interface->{FUNCTIONS}}+1);
 
                next if ($count == 0);
 
@@ -2143,92 +2204,108 @@ sub RegistrationFunction($$)
        pidl "";
 }
 
-sub CheckPointerTypes($$)
+#####################################################################
+# parse a parsed IDL structure back into an IDL file
+sub Parse($$)
 {
-       my $s = shift;
-       my $default = shift;
+       my($ndr) = shift;
+       my($filename) = shift;
 
-       foreach my $e (@{$s->{ELEMENTS}}) {
-               if ($e->{POINTERS}) {
-                       if (not defined(Ndr::pointer_type($e))) {
-                               $e->{PROPERTIES}->{$default} = 1;
-                       }
+       $tabs = "";
+       my $h_filename = $filename;
+       $res = "";
 
-                       if (Ndr::pointer_type($e) eq "ptr") {
-                               print "Warning: ptr is not supported by pidl yet\n";
-                       }
-               }
+       if ($h_filename =~ /(.*)\.c/) {
+               $h_filename = "$1.h";
        }
-}
 
-sub LoadInterface($)
-{
-       my $x = shift;
+       pidl "/* parser auto-generated by pidl */";
+       pidl "";
+       pidl "#include \"includes.h\"";
+       pidl "#include \"$h_filename\"";
+       pidl "";
+
+       my %needed = ();
 
-       if (not util::has_property($x, "pointer_default")) {
-               # MIDL defaults to "ptr" in DCE compatible mode (/osf)
-               # and "unique" in Microsoft Extensions mode (default)
-               $x->{PROPERTIES}->{pointer_default} = "unique";
+       foreach my $x (@{$ndr}) {
+               ($x->{TYPE} eq "INTERFACE") && NeededInterface($x, \%needed);
        }
 
-       foreach my $d (@{$x->{DATA}}) {
-               if (($d->{TYPE} eq "DECLARE") or ($d->{TYPE} eq "TYPEDEF")) {
-                       if ($d->{DATA}->{TYPE} eq "STRUCT" or $d->{DATA}->{TYPE} eq "UNION") {
-                               CheckPointerTypes($d->{DATA}, $x->{PROPERTIES}->{pointer_default});
-                       }
+       foreach my $x (@{$ndr}) {
+               ($x->{TYPE} eq "INTERFACE") && ParseInterface($x, \%needed);
+       }
 
-                       if (defined($d->{PROPERTIES}) && !defined($d->{DATA}->{PROPERTIES})) {
-                               $d->{DATA}->{PROPERTIES} = $d->{PROPERTIES};
-                       }
+       RegistrationFunction($ndr, $filename);
+
+       return $res;
+}
+
+sub NeededFunction($$)
+{
+       my $fn = shift;
+       my $needed = shift;
+       $needed->{"pull_$fn->{NAME}"} = 1;
+       $needed->{"push_$fn->{NAME}"} = 1;
+       $needed->{"print_$fn->{NAME}"} = 1;
+       foreach my $e (@{$fn->{ELEMENTS}}) {
+               $e->{PARENT} = $fn;
+               unless(defined($needed->{"pull_$e->{TYPE}"})) {
+                       $needed->{"pull_$e->{TYPE}"} = 1;
                }
-               if ($d->{TYPE} eq "FUNCTION") {
-                       CheckPointerTypes($d, 
-                               $x->{PROPERTIES}->{pointer_default}  # MIDL defaults to "ref"
-                       );
+               unless(defined($needed->{"push_$e->{TYPE}"})) {
+                       $needed->{"push_$e->{TYPE}"} = 1;
+               }
+               unless(defined($needed->{"print_$e->{TYPE}"})) {
+                       $needed->{"print_$e->{TYPE}"} = 1;
                }
        }
 }
 
-sub Load($)
+sub NeededTypedef($$)
 {
-       my $idl = shift;
+       my $t = shift;
+       my $needed = shift;
+       if (util::has_property($t, "public")) {
+               $needed->{"pull_$t->{NAME}"} = not util::has_property($t, "nopull");
+               $needed->{"push_$t->{NAME}"} = not util::has_property($t, "nopush");
+               $needed->{"print_$t->{NAME}"} = not util::has_property($t, "noprint");
+       }
+
+       if ($t->{DATA}->{TYPE} eq "STRUCT" or $t->{DATA}->{TYPE} eq "UNION") {
+               if (util::has_property($t, "gensize")) {
+                       $needed->{"ndr_size_$t->{NAME}"} = 1;
+               }
 
-       foreach my $x (@{$idl}) {
-               LoadInterface($x);
+               for my $e (@{$t->{DATA}->{ELEMENTS}}) {
+                       $e->{PARENT} = $t->{DATA};
+                       if ($needed->{"pull_$t->{NAME}"} and
+                               not defined($needed->{"pull_$e->{TYPE}"})) {
+                               $needed->{"pull_$e->{TYPE}"} = 1;
+                       }
+                       if ($needed->{"push_$t->{NAME}"} and
+                               not defined($needed->{"push_$e->{TYPE}"})) {
+                               $needed->{"push_$e->{TYPE}"} = 1;
+                       }
+                       if ($needed->{"print_$t->{NAME}"} and 
+                               not defined($needed->{"print_$e->{TYPE}"})) {
+                               $needed->{"print_$e->{TYPE}"} = 1;
+                       }
+               }
        }
 }
 
 #####################################################################
-# parse a parsed IDL structure back into an IDL file
-sub Parse($$)
+# work out what parse functions are needed
+sub NeededInterface($$)
 {
-       my($idl) = shift;
-       my($filename) = shift;
-       my $h_filename = $filename;
-       $res = "";
-
-       Load($idl);
-
-       if ($h_filename =~ /(.*)\.c/) {
-               $h_filename = "$1.h";
+       my ($interface) = shift;
+       my $needed = shift;
+       foreach my $d (@{$interface->{FUNCTIONS}}) {
+           NeededFunction($d, $needed);
        }
-
-       pidl "/* parser auto-generated by pidl */";
-       pidl "";
-       pidl "#include \"includes.h\"";
-       pidl "#include \"$h_filename\"";
-       pidl "";
-
-       foreach my $x (@{$idl}) {
-               if ($x->{TYPE} eq "INTERFACE") { 
-                       needed::BuildNeeded($x);
-                       ParseInterface($x);
-               }
+       foreach my $d (reverse @{$interface->{TYPEDEFS}}) {
+           NeededTypedef($d, $needed);
        }
-
-       RegistrationFunction($idl, $filename);
-
-       return $res;
 }
 
 1;
diff --git a/source4/build/pidl/needed.pm b/source4/build/pidl/needed.pm
deleted file mode 100644 (file)
index ae8bf7f..0000000
+++ /dev/null
@@ -1,80 +0,0 @@
-###################################################
-# Samba4 parser generator for IDL structures
-# Copyright tridge@samba.org 2000-2004
-# Copyright jelmer@samba.org 2004
-# released under the GNU GPL
-
-package needed;
-
-use strict;
-
-# the list of needed functions
-my %needed;
-
-sub NeededFunction($)
-{
-       my $fn = shift;
-       $needed{"pull_$fn->{NAME}"} = 1;
-       $needed{"push_$fn->{NAME}"} = 1;
-       foreach my $e (@{$fn->{ELEMENTS}}) {
-               $e->{PARENT} = $fn;
-               $needed{"pull_$e->{TYPE}"} = 1;
-               $needed{"push_$e->{TYPE}"} = 1;
-       }
-}
-
-sub NeededTypedef($)
-{
-       my $t = shift;
-       if (util::has_property($t, "public")) {
-               $needed{"pull_$t->{NAME}"} = 1;
-               $needed{"push_$t->{NAME}"} = 1;         
-       }
-
-       if (util::has_property($t, "nopull")) {
-               $needed{"pull_$t->{NAME}"} = 0;
-       }
-       if (util::has_property($t, "nopush")) {
-               $needed{"push_$t->{NAME}"} = 0;
-       }
-
-       if ($t->{DATA}->{TYPE} eq "STRUCT" or $t->{DATA}->{TYPE} eq "UNION") {
-               if (util::has_property($t, "gensize")) {
-                       $needed{"ndr_size_$t->{NAME}"} = 1;
-               }
-
-               for my $e (@{$t->{DATA}->{ELEMENTS}}) {
-                       $e->{PARENT} = $t->{DATA};
-                       if ($needed{"pull_$t->{NAME}"}) {
-                               $needed{"pull_$e->{TYPE}"} = 1;
-                       }
-                       if ($needed{"push_$t->{NAME}"}) {
-                               $needed{"push_$e->{TYPE}"} = 1;
-                       }
-               }
-       }
-}
-
-#####################################################################
-# work out what parse functions are needed
-sub BuildNeeded($)
-{
-       my($interface) = shift;
-       my($data) = $interface->{DATA};
-       foreach my $d (@{$data}) {
-               ($d->{TYPE} eq "FUNCTION") && 
-                   NeededFunction($d);
-       }
-       foreach my $d (reverse @{$data}) {
-               ($d->{TYPE} eq "TYPEDEF") &&
-                   NeededTypedef($d);
-       }
-}
-
-sub is_needed($)
-{
-       my $name = shift;
-       return $needed{$name};
-}
-
-1;
index 95e81c07ce049cffdf3054cfbdc9447ea7b1cfa9..5ed508dc9397af647d6eaea37c2838b1580f02cf 100644 (file)
@@ -43,12 +43,29 @@ sub ODL2IDL($)
        
        foreach my $x (@{$odl}) {
                # Add [in] ORPCTHIS *this, [out] ORPCTHAT *that
+               # and replace interfacepointers with MInterfacePointer
                # for 'object' interfaces
                if (util::has_property($x, "object")) {
                        foreach my $e (@{$x->{DATA}}) {
                                ($e->{TYPE} eq "FUNCTION") && FunctionAddObjArgs($e);
                                ReplaceInterfacePointers($e);
                        }
+                       # Object interfaces use ORPC
+                       my @depends = ();
+                       if(util::has_property($x, "depends")) {
+                               @depends = split /,/, $x->{PROPERTIES}->{depends};
+                       }
+                       push @depends, "orpc";
+                       $x->{PROPERTIES}->{depends} = join(',',@depends);
+               }
+
+               if ($x->{BASE}) {
+                       my $base = util::get_interface($odl, $x->{BASE});
+
+                       foreach my $fn (reverse @{$base->{DATA}}) {
+                               next unless ($fn->{TYPE} eq "FUNCTION");
+                               unshift (@{$x->{DATA}}, $fn);
+                       }
                }
        }
 
index 2305d9243b27f980268dedc695d5a006058bf281..c7b98a0d34e37dc032e94456965a74b99ab4a3d2 100755 (executable)
@@ -14,9 +14,9 @@ use lib "$RealBin";
 use lib "$RealBin/lib";
 use Getopt::Long;
 use File::Basename;
+use idl;
 use dump;
 use ndr_client;
-use idl;
 use ndr_header;
 use ndr_parser;
 use server;
@@ -24,12 +24,14 @@ use dcom_proxy;
 use dcom_stub;
 use com_header;
 use odl;
-use eparser;
+use eth_parser;
+use eth_header;
 use validator;
 use typelist;
 use util;
 use template;
 use swig;
+use compat;
 
 my($opt_help) = 0;
 my($opt_parse) = 0;
@@ -40,7 +42,8 @@ my($opt_template) = 0;
 my($opt_client) = 0;
 my($opt_server) = 0;
 my($opt_parser);
-my($opt_eparser) = 0;
+my($opt_eth_parser);
+my($opt_eth_header);
 my($opt_keep) = 0;
 my($opt_swig) = 0;
 my($opt_dcom_proxy) = 0;
@@ -48,6 +51,7 @@ my($opt_com_header) = 0;
 my($opt_odl) = 0;
 my($opt_quiet) = 0;
 my($opt_output);
+my($opt_warn_compat) = 0;
 
 my $idl_parser = new idl;
 
@@ -71,13 +75,15 @@ sub ShowHelp()
          --client              create a C NDR client
          --server              create server boilerplate
          --template            print a template for a pipe
-         --eparser             create an ethereal parser
+         --eth-parser          create an ethereal parser
+                --eth-header          create an ethereal header file
          --swig                create swig wrapper file
          --diff                run diff on the idl and dumped output
          --keep                keep the .pidl file
          --odl                 accept ODL input
          --dcom-proxy          create DCOM proxy (implies --odl)
          --com-header          create header for COM interfaces (implies --odl)
+                --warn-compat         warn about incompatibility with other compilers
                 --quiet               be quiet
          \n";
     exit(0);
@@ -94,14 +100,16 @@ GetOptions (
            'template' => \$opt_template,
            'parser:s' => \$opt_parser,
         'client' => \$opt_client,
-           'eparser' => \$opt_eparser,
+           'eth-parser:s' => \$opt_eth_parser,
+               'eth-header:s' => \$opt_eth_header,
            'diff' => \$opt_diff,
                'odl' => \$opt_odl,
            'keep' => \$opt_keep,
            'swig' => \$opt_swig,
                'dcom-proxy' => \$opt_dcom_proxy,
                'com-header' => \$opt_com_header,
-               'quiet' => \$opt_quiet
+               'quiet' => \$opt_quiet,
+               'warn-compat' => \$opt_warn_compat
            );
 
 if ($opt_help) {
@@ -114,6 +122,7 @@ sub process_file($)
        my $idl_file = shift;
        my $output;
        my $pidl;
+       my $ndr;
 
        my $basename = basename($idl_file, ".idl");
 
@@ -175,21 +184,25 @@ sub process_file($)
                $opt_odl = 1;
        }
 
+       if ($opt_warn_compat) {
+               IDLCompat::Check($pidl);
+       }
+
        if ($opt_odl) {
                $pidl = ODL::ODL2IDL($pidl);
        }
 
+       if (defined($opt_header) or defined($opt_eth_parser) or defined($opt_eth_header) or $opt_client or $opt_server or defined($opt_parser)) {
+               $ndr = Ndr::Parse($pidl);
+#              print util::MyDumper($ndr);
+       }
+
        if (defined($opt_header)) {
                my $header = $opt_header;
                if ($header eq "") {
                        $header = util::ChangeExtension($output, ".h");
                }
-
-               util::FileSave($header, NdrHeader::Parse($pidl));
-               if ($opt_eparser) {
-                 my($eparserhdr) = dirname($output) . "/packet-dcerpc-$basename.h";
-                 IdlEParser::RewriteHeader($pidl, $header, $eparserhdr);
-               }
+               util::FileSave($header, NdrHeader::Parse($ndr));
                if ($opt_swig) {
                  my($filename) = $output;
                  $filename =~ s/\/ndr_/\//;
@@ -198,6 +211,15 @@ sub process_file($)
                }
        }
 
+       if (defined($opt_eth_header)) {
+         my($eparserhdr) = $opt_eth_header;
+         if ($eparserhdr eq "") {
+                 $eparserhdr = dirname($output) . "/packet-dcerpc-$basename.h";
+         }
+
+         util::FileSave($eparserhdr, EthHeader::Parse($ndr));
+       }
+
        if ($opt_client) {
                my ($client) = util::ChangeExtension($output, "_c.c");
                my $res = "";
@@ -250,13 +272,19 @@ $dcom
                if ($parser eq "") {
                        $parser = util::ChangeExtension($output, ".c");
                }
-               util::FileSave($parser, NdrParser::Parse($pidl, $parser));
-               if($opt_eparser) {
-                 my($eparser) = dirname($output) . "/packet-dcerpc-$basename.c";
-                 IdlEParser::RewriteC($pidl, $parser, $eparser);
-               }
+               
+               util::FileSave($parser, NdrParser::Parse($ndr, $parser));
        }
 
+       if (defined($opt_eth_parser)) {
+         my($eparser) = $opt_eth_parser;
+         if ($eparser eq "") {
+                 $eparser = dirname($output) . "/packet-dcerpc-$basename.c";
+         }
+         util::FileSave($eparser, EthParser::Parse($ndr, $basename, $eparser));
+       }
+
+
        if ($opt_template) {
                print IdlTemplate::Parse($pidl);
        }
index 920db52aa585940cbc3472537d5c09196277cc3b..5f25d4195c1ed9bb6f3c87a9f210c7e20fc8405b 100644 (file)
@@ -87,7 +87,7 @@ sub link_files($$)
 {
        my ($exe_name,$objs) = @_;
 
-       return system($cc, @ldflags, '-Lbin', '-o', $exe_name, @$objs, '-lrpc', '-ldl', '-lldap');
+       return system($cc, @ldflags, '-Lbin', '-lrpc', '-o', $exe_name, @$objs);
 }
 
 sub test_idl($$$$)
index 8559878a694f6d2e2baeaf49bd1b1cf0002eb64e..f5a06500061bb0bdb0904325cefffef6b000ec3e 100644 (file)
@@ -9,147 +9,6 @@ use strict;
 
 my %typedefs = ();
 
-# a list of known scalar types
-my $scalars = {
-       # 0 byte types
-       "void"          => {
-                               C_TYPE          => "void",
-                               NDR_ALIGN       => 0
-                       },
-
-       # 1 byte types
-       "char"          => {
-                               C_TYPE          => "char",
-                               NDR_ALIGN       => 1
-                       },
-       "int8"          => {
-                               C_TYPE          => "int8_t",
-                               NDR_ALIGN       => 1
-                       },
-       "uint8"         => {
-                               C_TYPE          => "uint8_t",
-                               NDR_ALIGN       => 1
-                       },
-
-       # 2 byte types
-       "int16"         => {
-                               C_TYPE          => "int16_t",
-                               NDR_ALIGN       => 2
-                       },
-       "uint16"        => {    C_TYPE          => "uint16_t",
-                               NDR_ALIGN       => 2
-                       },
-
-       # 4 byte types
-       "int32"         => {
-                               C_TYPE          => "int32_t",
-                               NDR_ALIGN       => 4
-                       },
-       "uint32"        => {    C_TYPE          => "uint32_t",
-                               NDR_ALIGN       => 4
-                       },
-
-       # 8 byte types
-       "int64"         => {
-                               C_TYPE          => "int64_t",
-                               NDR_ALIGN       => 8
-                       },
-       "hyper"         => {
-                               C_TYPE          => "uint64_t",
-                               NDR_ALIGN       => 8
-                       },
-       "dlong"         => {
-                               C_TYPE          => "int64_t",
-                               NDR_ALIGN       => 4
-                       },
-       "udlong"        => {
-                               C_TYPE          => "uint64_t",
-                               NDR_ALIGN       => 4
-                       },
-       "udlongr"       => {
-                               C_TYPE          => "uint64_t",
-                               NDR_ALIGN       => 4
-                       },
-
-       # DATA_BLOB types
-       "DATA_BLOB"     => {
-                               C_TYPE          => "DATA_BLOB",
-                               NDR_ALIGN       => 4
-                       },
-
-       # string types
-       "string"        => {
-                               C_TYPE          => "const char *",
-                               NDR_ALIGN       => 4 #???
-                       },
-       "string_array"  => {
-                               C_TYPE          => "const char **",
-                               NDR_ALIGN       => 4 #???
-                       },
-
-       # time types
-       "time_t"        => {
-                               C_TYPE          => "time_t",
-                               NDR_ALIGN       => 4
-                       },
-       "NTTIME"        => {
-                               C_TYPE          => "NTTIME",
-                               NDR_ALIGN       => 4
-                       },
-       "NTTIME_1sec"   => {
-                               C_TYPE          => "NTTIME",
-                               NDR_ALIGN       => 4
-                       },
-       "NTTIME_hyper"  => {
-                               C_TYPE          => "NTTIME",
-                               NDR_ALIGN       => 8
-                       },
-
-
-       # error code types
-       "WERROR"        => {
-                               C_TYPE          => "WERROR",
-                               NDR_ALIGN       => 4
-                       },
-       "NTSTATUS"      => {
-                               C_TYPE          => "NTSTATUS",
-                               NDR_ALIGN       => 4
-                       },
-
-       # special types
-       "nbt_string"    => {
-                               C_TYPE          => "const char *",
-                               NDR_ALIGN       => 4 #???
-                       },
-       "ipv4address"   => {
-                               C_TYPE          => "const char *",
-                               NDR_ALIGN       => 4
-                       }
-};
-
-# map from a IDL type to a C header type
-sub mapScalarType($)
-{
-       my $name = shift;
-
-       # it's a bug when a type is not in the list
-       # of known scalars or has no mapping
-       return $scalars->{$name}{C_TYPE} if defined($scalars->{$name}) and defined($scalars->{$name}{C_TYPE});
-
-       die("Unknown scalar type $name");
-}
-
-sub getScalarAlignment($)
-{
-       my $name = shift;
-
-       # it's a bug when a type is not in the list
-       # of known scalars or has no mapping
-       return $scalars->{$name}{NDR_ALIGN} if defined($scalars->{$name}) and defined($scalars->{$name}{NDR_ALIGN});
-
-       die("Unknown scalar type $name");
-}
-
 sub addType($)
 {
        my $t = shift;
@@ -159,7 +18,7 @@ sub addType($)
 sub getType($)
 {
        my $t = shift;
-       return undef unless(defined($typedefs{$t}));
+       return undef if not hasType($t);
        return $typedefs{$t};
 }
 
@@ -179,9 +38,17 @@ sub hasType($)
        return 0;
 }
 
-sub RegisterScalars()
+sub RegisterPrimitives()
 {
-       foreach my $k (keys %{$scalars}) {
+       my @primitives = (
+               "char", "int8", "uint8", "short", "wchar_t", 
+               "int16", "uint16", "long", "int32", "uint32", 
+               "dlong", "udlong", "udlongr", "NTTIME", "NTTIME_1sec", 
+               "time_t", "DATA_BLOB", "error_status_t", "WERROR", 
+               "NTSTATUS", "boolean32", "unsigned32", "ipv4address", 
+               "hyper", "NTTIME_hyper");
+               
+       foreach my $k (@primitives) {
                $typedefs{$k} = {
                        NAME => $k,
                        TYPE => "TYPEDEF",
@@ -218,25 +85,66 @@ sub bitmap_type_fn($)
        return "uint32";
 }
 
+# provide mappings between IDL base types and types in our headers
+my %scalar_type_mappings = 
+    (
+     "int8"         => "int8_t",
+     "uint8"        => "uint8_t",
+     "short"        => "int16_t",
+     "wchar_t"      => "uint16_t",
+     "int16"        => "int16_t",
+     "uint16"       => "uint16_t",
+     "int32"        => "int32_t",
+     "uint32"       => "uint32_t",
+     "int64"        => "int64_t",
+     "dlong"        => "int64_t",
+     "udlong"       => "uint64_t",
+     "udlongr"      => "uint64_t",
+     "hyper"        => "uint64_t",
+     "NTTIME"       => "NTTIME",
+     "NTTIME_1sec"  => "NTTIME",
+     "time_t"       => "time_t",
+     "NTTIME_hyper" => "NTTIME",
+     "NTSTATUS"     => "NTSTATUS",
+     "WERROR"       => "WERROR",
+     "DATA_BLOB"    => "DATA_BLOB",
+     "ipv4address"  => "const char *",
+     "nbt_string"   => "const char *"
+     );
+
+# map from a IDL type to a C header type
+sub mapScalarType($)
+{
+       my $name = shift;
+       die("Undef passed to mapScalarType") unless defined($name);
+       if (defined($scalar_type_mappings{$name})) {
+               return $scalar_type_mappings{$name};
+       }
+       die("Tried to map non-scalar type $name");
+}
+
 sub mapType($)
 {
-       my $e = shift;
+       my $t = shift;
+       die("Undef passed to mapType") unless defined($t);
        my $dt;
 
-       if ($e->{TYPE} eq "ENUM" or $e->{TYPE} eq "BITMAP") {
-               $dt = getType($e->{PARENT}->{NAME});
-       }
-       
-       unless ($dt or $dt = getType($e->{TYPE})) {
+       return "void" if ($t eq "void");
+       return "const char *" if ($t =~ "string");
+
+       unless ($dt or ($dt = getType($t))) {
                # Best guess
-               return "struct $e->{TYPE}";
+               return "struct $t";
        }
-       return mapScalarType($e->{TYPE}) if ($dt->{DATA}->{TYPE} eq "SCALAR");
+       return mapScalarType($t) if ($dt->{DATA}->{TYPE} eq "SCALAR");
        return "enum $dt->{NAME}" if ($dt->{DATA}->{TYPE} eq "ENUM");
        return "struct $dt->{NAME}" if ($dt->{DATA}->{TYPE} eq "STRUCT");
        return "struct $dt->{NAME}" if ($dt->{DATA}->{TYPE} eq "INTERFACE");
        return "union $dt->{NAME}" if ($dt->{DATA}->{TYPE} eq "UNION");
-       return mapScalarType(bitmap_type_fn($dt->{DATA})) if ($dt->{DATA}->{TYPE} eq "BITMAP");
+
+       if ($dt->{DATA}->{TYPE} eq "BITMAP") {
+               return mapScalarType(bitmap_type_fn($dt->{DATA}));
+       }
 
        die("Unknown type $dt->{DATA}->{TYPE}");
 }
@@ -258,11 +166,12 @@ sub LoadIdl($)
                foreach my $y (@{$x->{DATA}}) {
                        addType($y) if (
                                $y->{TYPE} eq "TYPEDEF" 
-                        or $y->{TYPE} eq "DECLARE");
+                            or $y->{TYPE} eq "DECLARE");
                }
        }
 }
 
-RegisterScalars();
+RegisterPrimitives();
+
 
 1;
index 42e9f699dc38dc14cd6ca85c5cf4ba704b5fc45c..bb86fcca50a6f7066460fce3869896c0b06c7f36 100644 (file)
@@ -10,11 +10,11 @@ use strict;
 
 #####################################################################
 # signal a fatal validation error
-sub fatal($)
+sub fatal($$)
 {
+       my $pos = shift;
        my $s = shift;
-       print "$s\n";
-       die "IDL is not valid\n";
+       die("$pos->{FILE}:$pos->{LINE}:$s\n");
 }
 
 sub el_name($)
@@ -42,6 +42,7 @@ my %property_list = (
        "uuid"                  => {},
        "endpoint"              => {},
        "pointer_default"       => {},
+       "pointer_default_top"   => {},
        "depends"               => {},
        "authservice"           => {},
 
@@ -103,7 +104,6 @@ my %property_list = (
        "range"                 => {},
        "size_is"               => {},
        "length_is"             => {},
-       "length_of"             => {}, # what is that? --metze
 );
 
 #####################################################################
@@ -116,7 +116,7 @@ sub ValidProperties($)
 
        foreach my $key (keys %{$e->{PROPERTIES}}) {
                if (not defined $property_list{$key}) {
-                       fatal(el_name($e) . ": unknown property '$key'\n");
+                       fatal($e, el_name($e) . ": unknown property '$key'\n");
                }
        }
 }
@@ -130,7 +130,7 @@ sub ValidElement($)
        ValidProperties($e);
 
        if (util::has_property($e, "ptr")) {
-               fatal(el_name($e) . " : pidl does not support full NDR pointers yet\n");
+               fatal($e, el_name($e) . " : pidl does not support full NDR pointers yet\n");
        }
 
        # Check whether switches are used correctly.
@@ -139,7 +139,7 @@ sub ValidElement($)
                my $type = typelist::getType($e->{TYPE});
 
                if (defined($type) and $type->{DATA}->{TYPE} ne "UNION") {
-                       fatal(el_name($e) . ": switch_is() used on non-union type $e->{TYPE} which is a $type->{DATA}->{TYPE}");
+                       fatal($e, el_name($e) . ": switch_is() used on non-union type $e->{TYPE} which is a $type->{DATA}->{TYPE}");
                }
 
                if (!util::has_property($type, "nodiscriminant") and defined($e2)) {
@@ -152,24 +152,16 @@ sub ValidElement($)
                }
        }
 
-       if (util::has_property($e, "size_is") and not defined ($e->{ARRAY_LEN})) {
-               fatal(el_name($e) . " : size_is() on non-array element");
-       }
-
-       if (util::has_property($e, "length_is") and not defined ($e->{ARRAY_LEN})) {
-               fatal(el_name($e) . " : length_is() on non-array element");
-       }
-
        if (defined (util::has_property($e, "subcontext_size")) and not defined(util::has_property($e, "subcontext"))) {
-               fatal(el_name($e) . " : subcontext_size() on non-subcontext element");
+               fatal($e, el_name($e) . " : subcontext_size() on non-subcontext element");
        }
 
        if (defined (util::has_property($e, "compression")) and not defined(util::has_property($e, "subcontext"))) {
-               fatal(el_name($e) . " : compression() on non-subcontext element");
+               fatal($e, el_name($e) . " : compression() on non-subcontext element");
        }
 
        if (defined (util::has_property($e, "obfuscation")) and not defined(util::has_property($e, "subcontext"))) {
-               fatal(el_name($e) . " : obfuscation() on non-subcontext element");
+               fatal($e, el_name($e) . " : obfuscation() on non-subcontext element");
        }
 
        if (!$e->{POINTERS} && (
@@ -177,7 +169,7 @@ sub ValidElement($)
                util::has_property($e, "unique") or
                util::has_property($e, "relative") or
                util::has_property($e, "ref"))) {
-               fatal(el_name($e) . " : pointer properties on non-pointer element\n");  
+               fatal($e, el_name($e) . " : pointer properties on non-pointer element\n");      
        }
 }
 
@@ -204,7 +196,7 @@ sub ValidUnion($)
        ValidProperties($union);
 
        if (util::has_property($union->{PARENT}, "nodiscriminant") and util::has_property($union->{PARENT}, "switch_type")) {
-               fatal($union->{PARENT}->{NAME} . ": switch_type() on union without discriminant");
+               fatal($union->{PARENT}, $union->{PARENT}->{NAME} . ": switch_type() on union without discriminant");
        }
        
        foreach my $e (@{$union->{ELEMENTS}}) {
@@ -212,16 +204,16 @@ sub ValidUnion($)
 
                if (defined($e->{PROPERTIES}->{default}) and 
                        defined($e->{PROPERTIES}->{case})) {
-                       fatal "Union member $e->{NAME} can not have both default and case properties!\n";
+                       fatal $e, "Union member $e->{NAME} can not have both default and case properties!\n";
                }
                
                unless (defined ($e->{PROPERTIES}->{default}) or 
                                defined ($e->{PROPERTIES}->{case})) {
-                       fatal "Union member $e->{NAME} must have default or case property\n";
+                       fatal $e, "Union member $e->{NAME} must have default or case property\n";
                }
 
                if (util::has_property($e, "ref")) {
-                       fatal(el_name($e) . " : embedded ref pointers are not supported yet\n");
+                       fatal($e, el_name($e) . " : embedded ref pointers are not supported yet\n");
                }
 
 
@@ -262,7 +254,7 @@ sub ValidFunction($)
        foreach my $e (@{$fn->{ELEMENTS}}) {
                $e->{PARENT} = $fn;
                if (util::has_property($e, "ref") && !$e->{POINTERS}) {
-                       fatal "[ref] variables must be pointers ($fn->{NAME}/$e->{NAME})\n";
+                       fatal $e, "[ref] variables must be pointers ($fn->{NAME}/$e->{NAME})\n";
                }
                ValidElement($e);
        }
@@ -279,18 +271,18 @@ sub ValidInterface($)
 
        if (util::has_property($interface, "pointer_default") && 
                $interface->{PROPERTIES}->{pointer_default} eq "ptr") {
-               fatal "Full pointers are not supported yet\n";
+               fatal $interface, "Full pointers are not supported yet\n";
        }
 
        if (util::has_property($interface, "object")) {
                if (util::has_property($interface, "version") && 
                        $interface->{PROPERTIES}->{version} != 0) {
-                       fatal "Object interfaces must have version 0.0 ($interface->{NAME})\n";
+                       fatal $interface, "Object interfaces must have version 0.0 ($interface->{NAME})\n";
                }
 
                if (!defined($interface->{BASE}) && 
                        not ($interface->{NAME} eq "IUnknown")) {
-                       fatal "Object interfaces must all derive from IUnknown ($interface->{NAME})\n";
+                       fatal $interface, "Object interfaces must all derive from IUnknown ($interface->{NAME})\n";
                }
        }
                
index bf7743a37ca07435a8809194097a3ce88f723b1b..a11a2cf7464a0f3f4ef2508253a19b4c4f2196fd 100644 (file)
@@ -7,6 +7,7 @@
 [ uuid("1ff70682-0a51-30e8-076d-740be8cee98b"),
   version(1.0),
   pointer_default(unique),
+  pointer_default_top(unique),
   helpstring("Queue/List/Remove jobs for later execution"),
   endpoint("ncacn_np:[\\pipe\\atsvc]", "ncalrpc:")
 ] interface atsvc
@@ -46,7 +47,7 @@
 
        typedef struct {
                uint32 entries_read;
-               [size_is(entries_read)] atsvc_JobEnumInfo *first_entry[];
+               [size_is(entries_read)] atsvc_JobEnumInfo *first_entry;
        } atsvc_enum_ctr;
 
        /******************/
index 9b9399ffee2103d0721a1bef402a72dc2b6048df..2b27b757dd3117ce69d7ba9426477da4182cd7e7 100644 (file)
@@ -2,6 +2,7 @@
        uuid("0a74ef1c-41a4-4e06-83ae-dc74fb1cdd53"),
        version(1.0),
        pointer_default(unique),
+       pointer_default_top(unique),
        helpstring("Audio Server")
 ] interface audiosrv
 {
index 5cc2475119f109bd2f089aa81cf7c905abc753cc..b2008c7321c2dff718999cb049d208a82423a559 100644 (file)
@@ -3,6 +3,7 @@
   version(0.0), 
   helpstring("Browsing"),
   pointer_default(unique),
+  pointer_default_top(unique),
   endpoint("ncacn_np:[\\pipe\\browser]", "ncacn_ip_tcp:", "ncalrpc:")
 ] 
 interface browser
index 8d2133d81f230b467425efa91291d4f7e7dfaa3d..1c21637b74e04184ec83babcbeedf3602f625918 100644 (file)
@@ -1,7 +1,7 @@
 [
        uuid("1d55b526-c137-46c5-ab79-638f2a68e869"),
        version(1.0),
-    pointer_default(unique),
+       pointer_default(unique),
        helpstring("Remote IDL debugger")
 ] interface dbgidl 
 {
index 3e4d9d0c2cc7495ca1e1e7dd4c1d7fa297527a54..f8db720817b8490bdb84cb4004ed65313a8cdbc7 100644 (file)
@@ -10,6 +10,7 @@
 [
        uuid("18f70770-8e64-11cf-9af1-0020af6e72f4"),
        pointer_default(unique),
+       pointer_default_top(unique),
        version(0.0)
 ] interface dcom_Unknown
 {
@@ -22,6 +23,7 @@
        object,
        uuid("00000000-0000-0000-C000-000000000046"),
        pointer_default(unique),
+       pointer_default_top(unique),
        helpstring("Base interface for all COM interfaces")
 ]
 interface IUnknown
@@ -46,6 +48,7 @@ interface IUnknown
 [
        object,
        uuid("00000001-0000-0000-C000-000000000046"),
+       pointer_default_top(unique),
        pointer_default(unique)
 ] interface IClassFactory : IUnknown
 {
@@ -72,6 +75,7 @@ interface IUnknown
 [
        uuid("00000131-0000-0000-C000-000000000046"),
        object,
+       pointer_default_top(unique),
        pointer_default(unique),
        helpstring("Remote version of IUnknown")
 ]
@@ -113,6 +117,7 @@ interface IRemUnknown : IUnknown
 
 [
        uuid("00000140-0000-0000-c000-000000000046"),
+       pointer_default_top(unique),
        pointer_default(unique),
        object
 ] interface IClassActivator : IUnknown
@@ -126,6 +131,7 @@ interface IRemUnknown : IUnknown
 
 [
        uuid("00000136-0000-0000-c000-000000000046"),
+       pointer_default_top(unique),
        pointer_default(unique),
        object
 ] interface ISCMLocalActivator : IClassActivator
@@ -135,6 +141,7 @@ interface IRemUnknown : IUnknown
 
 [
        pointer_default(unique),
+       pointer_default_top(unique),
        uuid("c6f3ee72-ce7e-11d1-b71e-00c04fc3111a")
 ] interface IMachineLocalActivator 
 {
@@ -143,6 +150,7 @@ interface IRemUnknown : IUnknown
 
 [
        pointer_default(unique),
+       pointer_default_top(unique),
        uuid("e60c73e6-88f9-11cf-9af1-0020af6e72f4")
 ] interface ILocalObjectExporter
 {
@@ -154,6 +162,7 @@ interface IRemUnknown : IUnknown
 [
        uuid("000001a0-0000-0000-c000-000000000046"),
        pointer_default(unique),
+       pointer_default_top(unique),
        object
 ]
        interface ISystemActivator : IClassActivator
@@ -173,6 +182,7 @@ interface IRemUnknown : IUnknown
 [
        object,
        pointer_default(unique),
+       pointer_default_top(unique),
        uuid("00000143-0000-0000-C000-000000000046")
 ]
 
@@ -188,8 +198,9 @@ interface IRemUnknown2 : IRemUnknown
 }
 
 [
-object,
+       object,
        pointer_default(unique),
+       pointer_default_top(unique),
        uuid("00000136-0000-0000-C000-000000000046")
        ] interface ISCMActivator : IClassActivator
 {
@@ -199,6 +210,7 @@ object,
 [
        object,
        pointer_default(unique),
+       pointer_default_top(unique),
        uuid("00020400-0000-0000-C000-000000000046")
        ] interface IDispatch : IUnknown
 {
@@ -267,6 +279,7 @@ object,
        uuid(DA23F6DB-6F45-466C-9EED-0B65286F2D78),
        helpstring("ICoffeeMachine Interface"),
        pointer_default(unique),
+       pointer_default_top(unique),
        object
 ] interface ICoffeeMachine : IUnknown
 {
@@ -284,6 +297,7 @@ object,
 [
        object,
        pointer_default(unique),
+       pointer_default_top(unique),
        uuid("0000000C-0000-0000-C000-000000000046"),
        helpstring("Stream")
 ]
index d418b8b5468e05f9433a7c3e318cf056182f891c..8bbb3e02ff12a1702215b37fb24f7218b6ab0bc8 100644 (file)
@@ -7,6 +7,7 @@
 [ uuid("4fc742e0-4a10-11cf-8273-00aa004ae673"),
   version(3.0),
   pointer_default(unique),
+  pointer_default_top(unique),
   helpstring("Settings for Microsoft Distributed File System")
 ] interface netdfs
 {
index e682de452f9c7891c09e9e61d29517fc467d9d0b..c7d1a5fb48adf3e0a2562202a8fec75e664730a7 100644 (file)
@@ -4,6 +4,7 @@
   uuid("38578646-4566-4564-2244-275796345667"),
   version(0.0),
   pointer_default(unique),
+  pointer_default_top(unique),
   helpstring("Active Directory Replication LDAP Blobs"),
   depends(drsuapi)
 ]
index 16b8da82b8978132c4a09d0d993d2a2cc3f7c2ca..737cd3b131f5711424acce20031c16fe672f68a0 100644 (file)
@@ -7,6 +7,7 @@
   authservice("ldap"),
   helpstring("Active Directory Replication"),
   pointer_default(unique),
+  pointer_default_top(unique),
   depends(security)
 ] 
 interface drsuapi
@@ -554,7 +555,7 @@ interface drsuapi
                [size_is(count)] drsuapi_DsReplicaMetaData meta_data[];
        } drsuapi_DsReplicaMetaDataCtr;
 
-       typedef [noprint] struct {
+       typedef [public,noprint] struct {
                drsuapi_DsReplicaObjectListItemEx *next_object;
                drsuapi_DsReplicaObject object;
                uint32 unknown1;
@@ -908,7 +909,7 @@ interface drsuapi
 
        /*****************/
         /* Function 0x11 */
-       typedef [noprint] struct {
+       typedef [public,noprint] struct {
                drsuapi_DsReplicaObjectListItem *next_object;
                drsuapi_DsReplicaObject object;
        } drsuapi_DsReplicaObjectListItem;
index c4f3d3cded5866617912b0ee45a2f39ea5e9245f..5ba5ffe95927a3edbfcec46bcbd4de4f52a401d3 100644 (file)
@@ -1,7 +1,8 @@
 [
        uuid("ecec0d70-a603-11d0-96b1-00a0c91ece30"),
        version(1.0),
-    pointer_default(unique),
+       pointer_default(unique),
+       pointer_default_top(unique),
        helpstring("Backup support for Active Directory")
 ] interface ad_backup
 {
@@ -19,7 +20,7 @@
 [
        uuid("16e0cf3a-a604-11d0-96b1-00a0c91ece30"),
        version(1.0),
-    pointer_default(unique),
+       pointer_default(unique),
        helpstring("Restoring Active Directory backups")
 ] interface ad_restore
 {
index 098a14890497dfe685e6857f939840da9a8cca2a..f10027466b7a2ab5f21b2dea709e155c1dcd056b 100644 (file)
@@ -9,6 +9,7 @@
        version(0.0),
        endpoint("ncacn_np:[\\pipe\\lsarpc]", "ncacn_np:[\\pipe\\lsass]", "ncacn_ip_tcp:", "ncalrpc:"),
        pointer_default(unique),
+       pointer_default_top(unique),
        helpstring("Active Directory Setup")
 ] interface dssetup
 {
index d3d0305cb6dd001f4ed2aee82d96dfa9a2029009..deb7c95bac53722d1b9e5b488ef74ef254d40161 100644 (file)
@@ -5,6 +5,7 @@
   uuid("60a15ec5-4de8-11d7-a637-005056a20182"),
   endpoint("ncacn_np:[\\pipe\\rpcecho]", "ncacn_ip_tcp:", "ncalrpc:"),
   pointer_default(unique),
+  pointer_default_top(unique),
   version(1.0),
   helpstring("Simple echo pipe")
 ]
index 9a97223e6ad8bde20bd677fb3de763cd73b19f53..8ff34c92b9667f235ec5f05457a168f41769db33 100644 (file)
@@ -1,7 +1,7 @@
 [
        uuid("c681d488-d850-11d0-8c52-00c04fd90f7e"),
        version(1.0),
-    pointer_default(unique),
+       pointer_default(unique),
        helpstring("Encrypted File System")
 ] interface efs 
 {
index 7881e47fe67fdfccf62e2fe01c1f3baee4b1626f..766b867a3566babf475f2922de59c9facff6987d 100644 (file)
@@ -14,6 +14,7 @@ http://www.opengroup.org/onlinepubs/9629399/chap6.htm#tagcjh_11_02_03_01: bindin
  endpoint("ncacn_np:[\\pipe\\epmapper]", "ncacn_ip_tcp:[135]", 
                  "ncalrpc:[EPMAPPER]"),
  helpstring("EndPoint Mapper"),
+ pointer_default_top(unique),
  pointer_default(unique)
 ]
 interface epmapper
@@ -202,7 +203,7 @@ interface epmapper
 
        typedef struct {
                [subcontext(2)] epm_lhs lhs;
-               [subcontext(2),switch_is(lhs.protocol)] epm_rhs rhs;
+               [subcontext(2),switch_is(r->lhs.protocol)] epm_rhs rhs;
        } epm_floor;
 
        /* note that the NDR_NOALIGN flag is inherited by all nested
index 14923e390fe4a78a5b18e6ae05f507ba2ed56cbb..8b4963c1e1f427be3cd776fb6d1bc7399e5a377a 100644 (file)
@@ -7,6 +7,7 @@
   version(0.0),
   depends(security),
   pointer_default(unique),
+  pointer_default_top(unique),
   helpstring("Event Logger")
 ] interface eventlog
 {
index 15b31794fae97144396126edcd0dfa27c1c6c0df..f8af3c77c62aba7a5aeb2be2a4aea5c83e4dfdad 100644 (file)
@@ -192,6 +192,7 @@ System Attendant Private Interface
 [
   uuid("a4f1db00-ca47-1067-b31f-00dd010662da"),
   pointer_default(unique),
+  pointer_default_top(unique),
   version(0.81),
   helpstring("Exchange 5.5 EMSMDB")
 ] interface exchange_emsmdb
index e84edb47b89acca30a90a53fa864b94d6a0d6ed5..f4f1f93f5ed91c4d8e8278da937304d02ea0ab99 100644 (file)
@@ -9,6 +9,7 @@
   version(1.0),
   endpoint("ncacn_np:[\\pipe\\InitShutdown]"),
   pointer_default(unique),
+  pointer_default_top(unique),
   helpstring("Init shutdown service")
 ] interface initshutdown
 {
index a8a0ca06974b6429572c62f51d07b75e196c3304..16524197c57282957c8a1f112125443f49506456 100644 (file)
@@ -8,6 +8,7 @@
   uuid("46746756-7567-7567-5677-756756756756"),
   version(0.0),
   pointer_default(unique),
+  pointer_default_top(unique),
   depends(security,netlogon)
 ]
 interface krb5pac
index 68adcf1d9dc7e5f74e7f66ca929d2b0f2d841030..3737d4c0eac12f0d354676f69f01c3065a0c7569 100644 (file)
@@ -8,6 +8,7 @@
   version(0.0),
   endpoint("ncacn_np:[\\pipe\\lsarpc]","ncacn_np:[\\pipe\\lsass]", "ncacn_ip_tcp:", "ncalrpc:"),
   pointer_default(unique),
+  pointer_default_top(unique),
   helpstring("Local Security Authority"),
   depends(security)
 ] interface lsarpc
index b649e0db29aa1bec0cd0eb1ad7d45ed1dde09ef2..2c4910e677e802734a56d24d88d324d679e089fd 100644 (file)
@@ -8,6 +8,7 @@
   uuid("afa8bd80-7d8a-11c9-bef4-08002b102989"), 
   version(1.0),
   pointer_default(unique),
+  pointer_default_top(unique),
   endpoint("ncalrpc:[EPMAPPER]", "ncacn_ip_tcp:[135]", "ncacn_np:[\\pipe\\epmapper]"),
   helpstring("DCE/RPC Remote Management")
 ] 
index 371084bc652e3c5b982881f21ed65463b9077847..95e4abd9747a78e92c355fadd9993181a62d5a96 100644 (file)
@@ -66,7 +66,7 @@
 
        /* the ndr parser for nbt_name is separately defined in
           nbtname.c (along with the parsers for nbt_string) */
-       typedef [nopull,nopush] struct {
+       typedef [public,nopull,nopush] struct {
                string        name;
                string        scope;
                nbt_name_type type;
index 68a5078aae56d4a5ac485988d1c708abd4421b2a..9d9d2dd98f62e45cc62a38a6eaa40948ee8c9e8a 100644 (file)
@@ -11,6 +11,7 @@
   version(1.0),
   endpoint("ncacn_np:[\\pipe\\netlogon]","ncacn_ip_tcp:","ncalrpc:"),
   pointer_default(unique),
+  pointer_default_top(unique),
   depends(lsa,samr)
 ]
 
index 3b6d4efd283231725472a4742685c483feddc6ca..ad38fce9a549e84886a85e9be114f55aa24d27ff 100644 (file)
@@ -17,6 +17,7 @@
        helpstring("Object Exporter ID Resolver"),
        endpoint("ncacn_np:[\\pipe\\epmapper]", "ncacn_ip_tcp:[135]", "ncalrpc:"),
        pointer_default(unique),
+       pointer_default_top(unique),
        depends(dcom)
 ]
 interface IOXIDResolver
index 6da5cbb8f46c85293fbb612fb6b72d554f2c5657..295b70a2a1dddc89550e6290a3511e2434c26b02 100644 (file)
@@ -3,7 +3,7 @@
 [
        uuid("d335b8f6-cb31-11d0-b0f9-006097ba4e54"),
        version(1.5),
-    pointer_default(unique),
+       pointer_default(unique),
        helpstring("IPSec Policy Agent")
 ] interface policyagent
 {
index 7a879e717fe30b0e0b37460b3ba0b5f904304141..232ae9fffcbfd2d55e79713b3dd94ddec6d89e7a 100644 (file)
@@ -8,6 +8,7 @@
 [
        uuid("4d9f4ab8-7d1c-11cf-861e-0020af6e7c57"),
        pointer_default(unique),
+       pointer_default_top(unique),
        endpoint("ncalrpc:", "ncacn_ip_tcp:[135]", "ncacn_np:[\\pipe\\epmapper]"),
        depends(dcom)
 ]
index fd9fd42467656079d3f314d52f3741f77cdae448..8ae5502bdc19d296c361ce89af474a10b7554943 100644 (file)
@@ -3,7 +3,8 @@
 [
        uuid("b9e79e60-3d52-11ce-aaa1-00006901293f"),
        version(0.2),
-    pointer_default(unique),
+       pointer_default(unique),
+       pointer_default_top(unique),
        depends(orpc),
        endpoint("ncacn_np:[\\pipe\\epmapper]", "ncacn_ip_tcp:[135]", 
                  "ncalrpc:[EPMAPPER]")
index 3cf2aeaf7eb18e8ca1aa573f4650c8a665b3832b..59de0d1b4a34312e559542284cfb1b9bc08cb3b0 100644 (file)
@@ -12,6 +12,7 @@
   version(1.0),
   endpoint("ncacn_np:[\\pipe\\samr]","ncacn_ip_tcp:", "ncalrpc:"),
   pointer_default(unique),
+  pointer_default_top(unique),
   depends(lsa,security)
 ] interface samr
 {
 
        typedef struct {
                uint32 count;
-               [size_is(count)] samr_String *names[];
+               [size_is(count)] samr_String *names;
        } samr_Strings;
 
        NTSTATUS samr_LookupRids(
index 5d4e957f071ada73046f631c8ce4497879c18bf9..0693d3c3c48556f1166a770ffd72531272174c37 100644 (file)
@@ -8,6 +8,7 @@
   version(1.0),
   endpoint("ncacn_np:[\\pipe\\spoolss]"),
   pointer_default(unique),
+  pointer_default_top(unique),
   helpstring("Spooler SubSystem"),
   depends(security)
 ] interface spoolss
index e986ea16ede4a9d57d0580a83ec92d530cac7514..3661bfb9cc2faab8635141457ba3ac77b2ed2602 100644 (file)
@@ -8,6 +8,7 @@
   version(3.0),
   endpoint("ncacn_np:[\\pipe\\srvsvc]", "ncacn_ip_tcp:", "ncalrpc:"),
   pointer_default(unique),
+  pointer_default_top(unique),
   helpstring("Server Service"),
   depends(security,svcctl)
 ] interface srvsvc
index 544d5d83f326612ca5670e6d803ee3e0e23e8830..3ffe41c109be752eeca4ab43cc8dcdf1745b3459 100644 (file)
@@ -7,6 +7,7 @@
 [ uuid("367abb81-9844-35f1-ad32-98f038001003"),
   version(2.0),
   pointer_default(unique),
+  pointer_default_top(unique),
   endpoint("ncacn_np:[\\pipe\\svcctl]", "ncalrpc:"),
   helpstring("Service Control")
 ] interface svcctl
        WERROR svcctl_StartServiceW(
                                                           [in,ref] policy_handle *handle,
                                                           [in] uint32 NumArgs,
-                                                          [in,length_of(NumArgs)] unistr *Arguments);
+                                                          [in,length_is(NumArgs)] unistr *Arguments);
 
        /*****************/
        /* Function 0x14 */
        WERROR svcctl_StartServiceA(
                                                           [in,ref] policy_handle *handle,
                                                           [in] uint32 NumArgs,
-                                                          [in,length_of(NumArgs)] unistr *Arguments);
+                                                          [in,length_is(NumArgs)] unistr *Arguments);
 
        /*****************/
        /* Function 0x20 */
index 8f8c759d1772d91d13ee43947adfb6a189ee4bbf..7f11af189bae58fd87fdb3583e52607ec196827e 100644 (file)
@@ -5,7 +5,7 @@
 [
        uuid("300f3532-38cc-11d0-a3f0-0020af6b0add"),
        version(1.2),
-    pointer_default(unique),
+       pointer_default(unique),
        helpstring("Distributed Key Tracking Service")
 ]
 interface trkwks
index 47531d47102c3912dddb0cf9b1446134ed036554..31f293267a14967ba960b57d2ff2c6ef2561ca58 100644 (file)
@@ -9,6 +9,7 @@
   version(1.0),
   endpoint("ncacn_np:[\\pipe\\winreg]","ncacn_ip_tcp:","ncalrpc:"),
   pointer_default(unique),
+  pointer_default_top(unique),
   helpstring("Remote Registry Service"),
   depends(lsa,initshutdown)
 ] interface winreg
index cec82a51066820149397b60e9e60a02592dfe459..8bcea421aae53cdc85e9633f8ef5dda126fcc6e8 100644 (file)
@@ -12,7 +12,8 @@
 [
   uuid("0-1-2-3-4"),
   version(0.0),
-  pointer_default(unique)
+  pointer_default(unique),
+  pointer_default_top(unique)
 ]
 interface wrepl
 {
index 0d018db4b93c2bf79285df59eefa60d2dcbdb2ed..a948f53dbf2809e4cd9f00153d6353ba1f9c11a8 100644 (file)
@@ -7,6 +7,7 @@
 [ uuid("6bffd098-a112-3610-9833-46c3f87e345a"),
   version(1.0),
   pointer_default(unique),
+  pointer_default_top(unique),
   helpstring("Workstation Service"),
   depends(srvsvc)
 ] interface wkssvc
index ddf9664b9b519964d75dc6cf3dc18fe9c33d464a..892f3c27ca1b60638f32abc7498fe434a4be4e41 100644 (file)
@@ -147,7 +147,6 @@ struct ndr_print {
 #define NDR_BE(ndr) (((ndr)->flags & (LIBNDR_FLAG_BIGENDIAN|LIBNDR_FLAG_LITTLE_ENDIAN)) == LIBNDR_FLAG_BIGENDIAN)
 
 enum ndr_err_code {
-       NDR_ERR_CONFORMANT_SIZE,
        NDR_ERR_ARRAY_SIZE,
        NDR_ERR_BAD_SWITCH,
        NDR_ERR_OFFSET,
index 82967268665e87608e21abe06f8ef39cd00653b5..dfd21018d2ee529cac2e4659895fee2438ad86c8 100644 (file)
@@ -182,120 +182,6 @@ NTSTATUS ndr_push_expand(struct ndr_push *ndr, uint32_t size)
        return NT_STATUS_OK;
 }
 
-/* This function does not appear to be used */
-
-#if 0
-
-/*
-  set the push offset to 'ofs'
-*/
-static NTSTATUS ndr_push_set_offset(struct ndr_push *ndr, uint32_t ofs)
-{
-       NDR_CHECK(ndr_push_expand(ndr, ofs));
-       ndr->offset = ofs;
-       return NT_STATUS_OK;
-}
-
-#endif
-
-/*
-  push a generic array
-*/
-NTSTATUS ndr_push_array(struct ndr_push *ndr, int ndr_flags, void *base, 
-                       size_t elsize, uint32_t count, 
-                       NTSTATUS (*push_fn)(struct ndr_push *, int, void *))
-{
-       int i;
-       char *p = base;
-       if (!(ndr_flags & NDR_SCALARS)) goto buffers;
-       for (i=0;i<count;i++) {
-               NDR_CHECK(push_fn(ndr, NDR_SCALARS, p));
-               p += elsize;
-       }
-       if (!(ndr_flags & NDR_BUFFERS)) goto done;
-buffers:
-       p = base;
-       for (i=0;i<count;i++) {
-               NDR_CHECK(push_fn(ndr, NDR_BUFFERS, p));
-               p += elsize;
-       }
-done:
-       return NT_STATUS_OK;
-}
-
-/*
-  pull a constant sized array
-*/
-NTSTATUS ndr_pull_array(struct ndr_pull *ndr, int ndr_flags, void *base, 
-                       size_t elsize, uint32_t count, 
-                       NTSTATUS (*pull_fn)(struct ndr_pull *, int, void *))
-{
-       int i;
-       char *p;
-       p = base;
-       if (!(ndr_flags & NDR_SCALARS)) goto buffers;
-       for (i=0;i<count;i++) {
-               NDR_CHECK(pull_fn(ndr, NDR_SCALARS, p));
-               p += elsize;
-       }
-       if (!(ndr_flags & NDR_BUFFERS)) goto done;
-buffers:
-       p = base;
-       for (i=0;i<count;i++) {
-               NDR_CHECK(pull_fn(ndr, NDR_BUFFERS, p));
-               p += elsize;
-       }
-done:
-       return NT_STATUS_OK;
-}
-
-/*
-  pull a constant size array of structures
-*/
-NTSTATUS ndr_pull_struct_array(struct ndr_pull *ndr, uint32_t count,
-                              size_t elsize, void **info,
-                              NTSTATUS (*pull_fn)(struct ndr_pull *, int, void *))
-{
-       int i;
-       char *base;
-
-       NDR_ALLOC_N_SIZE(ndr, *info, count, elsize);
-       base = (char *)*info;
-
-       for (i = 0; i < count; i++) {
-               ndr->data += ndr->offset;
-               ndr->offset = 0;
-               NDR_CHECK(pull_fn(ndr, NDR_SCALARS|NDR_BUFFERS, &base[count * elsize]));
-       }
-
-       return NT_STATUS_OK;
-}
-
-/*
-  print a generic array
-*/
-void ndr_print_array(struct ndr_print *ndr, const char *name, void *base, 
-                    size_t elsize, uint32_t count, 
-                    void (*print_fn)(struct ndr_print *, const char *, void *))
-{
-       int i;
-       char *p = base;
-       ndr->print(ndr, "%s: ARRAY(%d)", name, count);
-       ndr->depth++;
-       for (i=0;i<count;i++) {
-               char *idx=NULL;
-               asprintf(&idx, "[%d]", i);
-               if (idx) {
-                       print_fn(ndr, idx, p);
-                       free(idx);
-               }
-               p += elsize;
-       }
-       ndr->depth--;
-}
-
-
-
 void ndr_print_debug_helper(struct ndr_print *ndr, const char *format, ...) _PRINTF_ATTRIBUTE(2,3)
 {
        va_list ap;
@@ -390,7 +276,7 @@ static NTSTATUS ndr_map_error(enum ndr_err_code err)
                break;
        }
 
-       /* we should all error codes to different status codes */
+       /* we should map all error codes to different status codes */
        return NT_STATUS_INVALID_PARAMETER;
 }
 
@@ -623,7 +509,7 @@ uint32_t ndr_get_array_size(struct ndr_pull *ndr, const void *p)
 NTSTATUS ndr_check_array_size(struct ndr_pull *ndr, void *p, uint32_t size)
 {
        uint32_t stored;
-       NDR_CHECK(ndr_token_retrieve(&ndr->array_size_list, p, &stored));
+       stored = ndr_token_peek(&ndr->array_size_list, p);
        if (stored != size) {
                return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE, 
                                      "Bad array size - got %u expected %u\n",
@@ -661,7 +547,7 @@ uint32_t ndr_get_array_length(struct ndr_pull *ndr, const void *p)
 NTSTATUS ndr_check_array_length(struct ndr_pull *ndr, void *p, uint32_t length)
 {
        uint32_t stored;
-       NDR_CHECK(ndr_token_retrieve(&ndr->array_length_list, p, &stored));
+       stored = ndr_token_peek(&ndr->array_length_list, p);
        if (stored != length) {
                return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE, 
                                      "Bad array length - got %u expected %u\n",
index 9e4bc526dcfec30c2a8f889cb1ccf8d53e8147a7..2e9bf86aac1a6c1e4cf60257c155010ac2ba13b0 100644 (file)
@@ -37,8 +37,8 @@ NTSTATUS ndr_pull_dom_sid2(struct ndr_pull *ndr, int ndr_flags, struct dom_sid *
        NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &num_auths));
        NDR_CHECK(ndr_pull_dom_sid(ndr, ndr_flags, sid));
        if (sid->num_auths != num_auths) {
-               return ndr_pull_error(ndr, NDR_ERR_CONFORMANT_SIZE, 
-                                     "Bad conformant size %u should be %u", 
+               return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE, 
+                                     "Bad array size %u should exceed %u", 
                                      num_auths, sid->num_auths);
        }
        return NT_STATUS_OK;
index 2a7ca8eb17672205e8fc95880f25dda6a589d58d..0194decb4a33581f22f1a5ba68dd2d77476cb8dd 100644 (file)
@@ -1025,6 +1025,7 @@ static NTSTATUS dcerpc_ndr_validate_in(struct dcerpc_connection *c,
        if (!pull) {
                return NT_STATUS_NO_MEMORY;
        }
+       pull->flags |= LIBNDR_FLAG_REF_ALLOC;
 
        status = ndr_pull(pull, NDR_IN, st);
        if (!NT_STATUS_IS_OK(status)) {
@@ -1277,7 +1278,7 @@ NTSTATUS dcerpc_ndr_request_recv(struct rpc_request *req)
        if (pull->offset != pull->data_size) {
                DEBUG(0,("Warning! ignoring %d unread bytes in rpc packet!\n", 
                         pull->data_size - pull->offset));
-               /* we used return NT_STATUS_INFO_LENGTH_MISMATCH here,
+               /* we used to return NT_STATUS_INFO_LENGTH_MISMATCH here,
                   but it turns out that early versions of NT
                   (specifically NT3.1) add junk onto the end of rpc
                   packets, so if we want to interoperate at all with
index 52da43a35e44c019f16a1f0829b635e600224797..241986a4b1bf8ac048b6bc58937cf528c781a065 100644 (file)
@@ -756,6 +756,8 @@ static NTSTATUS dcesrv_request(struct dcesrv_call_state *call)
        pull = ndr_pull_init_blob(&call->pkt.u.request.stub_and_verifier, call);
        NT_STATUS_HAVE_NO_MEMORY(pull);
 
+       pull->flags |= LIBNDR_FLAG_REF_ALLOC;
+
        call->context   = context;
        call->event_ctx = context->conn->srv_conn->event.ctx;
        call->ndr_pull  = pull;
index bcfbb45e60b65939f1d1662c9f41bb124df9ebde..eabeaad5374b5136a2629c7ffe01d28f87e75c0e 100644 (file)
@@ -200,6 +200,7 @@ static char *stdin_load(TALLOC_CTX *mem_ctx, size_t *size)
                blob.length = size;
 
                ndr = ndr_pull_init_blob(&blob, mem_ctx);
+               ndr->flags |= LIBNDR_FLAG_REF_ALLOC;
 
                status = f->ndr_pull(ndr, NDR_IN, st);
 
@@ -230,10 +231,7 @@ static char *stdin_load(TALLOC_CTX *mem_ctx, size_t *size)
        blob.length = size;
 
        ndr = ndr_pull_init_blob(&blob, mem_ctx);
-
-       if (flags == NDR_OUT) {
-               ndr->flags |= LIBNDR_FLAG_REF_ALLOC;
-       }
+       ndr->flags |= LIBNDR_FLAG_REF_ALLOC;
 
        status = f->ndr_pull(ndr, flags, st);