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")