summaryrefslogtreecommitdiff
path: root/source4/build/pidl
diff options
context:
space:
mode:
authorJelmer Vernooij <jelmer@samba.org>2005-05-25 13:50:27 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 13:17:01 -0500
commite427f58622e3d88c59953d6c1fb583acfb046213 (patch)
tree4fe708ec07cdcb85dd3af028e158505e065ca59e /source4/build/pidl
parente7b3f91678a27d85791f7a62fc418988edc92214 (diff)
downloadsamba-e427f58622e3d88c59953d6c1fb583acfb046213.tar.gz
samba-e427f58622e3d88c59953d6c1fb583acfb046213.tar.bz2
samba-e427f58622e3d88c59953d6c1fb583acfb046213.zip
r6973: Merge new version of pidl into the main SAMBA_4_0 branch.
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)
Diffstat (limited to 'source4/build/pidl')
-rw-r--r--source4/build/pidl/README4
-rw-r--r--source4/build/pidl/com_header.pm4
-rw-r--r--source4/build/pidl/compat.pm55
-rw-r--r--source4/build/pidl/dcom_proxy.pm2
-rw-r--r--source4/build/pidl/eparser.pm865
-rw-r--r--source4/build/pidl/eth_header.pm102
-rw-r--r--source4/build/pidl/eth_parser.pm1410
-rw-r--r--source4/build/pidl/idl.pm159
-rw-r--r--source4/build/pidl/idl.yp49
-rw-r--r--source4/build/pidl/ndr.pm286
-rw-r--r--source4/build/pidl/ndr_client.pm8
-rw-r--r--source4/build/pidl/ndr_header.pm128
-rw-r--r--source4/build/pidl/ndr_parser.pm1873
-rw-r--r--source4/build/pidl/needed.pm80
-rw-r--r--source4/build/pidl/odl.pm17
-rwxr-xr-xsource4/build/pidl/pidl.pl62
-rw-r--r--source4/build/pidl/test.pm2
-rw-r--r--source4/build/pidl/typelist.pm219
-rw-r--r--source4/build/pidl/validator.pm46
19 files changed, 3095 insertions, 2276 deletions
diff --git a/source4/build/pidl/README b/source4/build/pidl/README
index e087888840..eac0674153 100644
--- a/source4/build/pidl/README
+++ b/source4/build/pidl/README
@@ -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
diff --git a/source4/build/pidl/com_header.pm b/source4/build/pidl/com_header.pm
index 1c7194d85c..95bbc9c720 100644
--- a/source4/build/pidl/com_header.pm
+++ b/source4/build/pidl/com_header.pm
@@ -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
index 0000000000..3ab94b70f3
--- /dev/null
+++ b/source4/build/pidl/compat.pm
@@ -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;
diff --git a/source4/build/pidl/dcom_proxy.pm b/source4/build/pidl/dcom_proxy.pm
index 8cc5547680..3d46064548 100644
--- a/source4/build/pidl/dcom_proxy.pm
+++ b/source4/build/pidl/dcom_proxy.pm
@@ -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
index 23ff8e7954..0000000000
--- a/source4/build/pidl/eparser.pm
+++ /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
index 0000000000..f0a5778854
--- /dev/null
+++ b/source4/build/pidl/eth_header.pm
@@ -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
index 0000000000..a2e1bf051c
--- /dev/null
+++ b/source4/build/pidl/eth_parser.pm
@@ -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;
diff --git a/source4/build/pidl/idl.pm b/source4/build/pidl/idl.pm
index 53c06f22d8..d5100812ed 100644
--- a/source4/build/pidl/idl.pm
+++ b/source4/build/pidl/idl.pm
@@ -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);
}
diff --git a/source4/build/pidl/idl.yp b/source4/build/pidl/idl.yp
index 186f003396..d58dc9d023 100644
--- a/source4/build/pidl/idl.yp
+++ b/source4/build/pidl/idl.yp
@@ -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);
}
diff --git a/source4/build/pidl/ndr.pm b/source4/build/pidl/ndr.pm
index 3c75b29227..5c39578f40 100644
--- a/source4/build/pidl/ndr.pm
+++ b/source4/build/pidl/ndr.pm
@@ -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;
diff --git a/source4/build/pidl/ndr_client.pm b/source4/build/pidl/ndr_client.pm
index e5d4cc1569..ca6fc22465 100644
--- a/source4/build/pidl/ndr_client.pm
+++ b/source4/build/pidl/ndr_client.pm
@@ -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;
}
diff --git a/source4/build/pidl/ndr_header.pm b/source4/build/pidl/ndr_header.pm
index 0c6291fca7..bebf6937ae 100644
--- a/source4/build/pidl/ndr_header.pm
+++ b/source4/build/pidl/ndr_header.pm
@@ -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);
}
}
diff --git a/source4/build/pidl/ndr_parser.pm b/source4/build/pidl/ndr_parser.pm
index d0eba81bef..1abf8f7006 100644
--- a/source4/build/pidl/ndr_parser.pm
+++ b/source4/build/pidl/ndr_parser.pm
@@ -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($)
+sub is_scalar_array($$)
{
my $e = shift;
- my $pointers = "";
- foreach my $i (Ndr::need_wire_pointer($e)..$e->{POINTERS}-1) { $pointers.="*"; }
- return $pointers;
-}
+ my $l = shift;
-# 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($)
-{
- my $e = shift;
+ return 0 if ($l->{TYPE} ne "ARRAY");
- my $ret = "";
-
- 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;
- my $cprefix = c_pull_prefix($e);
- my $length = ParseExpr($e, util::array_size($e), $var_prefix);
+ 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 (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;
+ }
+
+ my $counter = "cntr_$e->{NAME}_$l->{LEVEL_INDEX}";
- 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}) {";
+ 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}));";
- }
- 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}));";
+ # strings are passed by value rather then reference
+ if (not Ndr::is_scalar_type($l->{DATA_TYPE})) {
+ $var_name = get_pointer_to($var_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;
- return unless (need_buffers_section($e));
+ 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);
- 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;
@@ -1760,152 +1888,81 @@ sub ParseFunctionPrint($)
}
#####################################################################
-# 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);
+ my $l = shift;
+ my $ndr = shift;
+ my $env = shift;
+ my $size = shift;
- # note that if the variable is also an "in"
- # variable then we copy the initial value from
- # the in side
+ my $var = ParseExpr($e->{NAME}, $env);
- 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;
- }
-
- # 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;
+ }
+ unless(defined($needed->{"push_$e->{TYPE}"})) {
+ $needed->{"push_$e->{TYPE}"} = 1;
}
- if ($d->{TYPE} eq "FUNCTION") {
- CheckPointerTypes($d,
- $x->{PROPERTIES}->{pointer_default} # MIDL defaults to "ref"
- );
+ 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");
+ }
- foreach my $x (@{$idl}) {
- LoadInterface($x);
+ 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}"} 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
index ae8bf7f078..0000000000
--- a/source4/build/pidl/needed.pm
+++ /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;
diff --git a/source4/build/pidl/odl.pm b/source4/build/pidl/odl.pm
index 95e81c07ce..5ed508dc93 100644
--- a/source4/build/pidl/odl.pm
+++ b/source4/build/pidl/odl.pm
@@ -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);
+ }
}
}
diff --git a/source4/build/pidl/pidl.pl b/source4/build/pidl/pidl.pl
index 2305d9243b..c7b98a0d34 100755
--- a/source4/build/pidl/pidl.pl
+++ b/source4/build/pidl/pidl.pl
@@ -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);
}
diff --git a/source4/build/pidl/test.pm b/source4/build/pidl/test.pm
index 920db52aa5..5f25d4195c 100644
--- a/source4/build/pidl/test.pm
+++ b/source4/build/pidl/test.pm
@@ -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($$$$)
diff --git a/source4/build/pidl/typelist.pm b/source4/build/pidl/typelist.pm
index 8559878a69..f5a0650006 100644
--- a/source4/build/pidl/typelist.pm
+++ b/source4/build/pidl/typelist.pm
@@ -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;
diff --git a/source4/build/pidl/validator.pm b/source4/build/pidl/validator.pm
index 42e9f699dc..bb86fcca50 100644
--- a/source4/build/pidl/validator.pm
+++ b/source4/build/pidl/validator.pm
@@ -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";
}
}