From a4819b27afaf849382cad8487d454a1eb6d19a2f Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Mon, 7 Jun 2004 15:57:22 +0000 Subject: [PATCH] r1070: adding build directory (and pidl) --- SAMBA_3_2_MERGE/source/build/pidl/Makefile | 5 + SAMBA_3_2_MERGE/source/build/pidl/client.pm | 76 + SAMBA_3_2_MERGE/source/build/pidl/dump.pm | 241 +++ SAMBA_3_2_MERGE/source/build/pidl/eparser.pm | 1022 ++++++++++ SAMBA_3_2_MERGE/source/build/pidl/header.pm | 335 ++++ SAMBA_3_2_MERGE/source/build/pidl/idl.gram | 183 ++ SAMBA_3_2_MERGE/source/build/pidl/idl.pm | 1997 ++++++++++++++++++++ SAMBA_3_2_MERGE/source/build/pidl/idl.yp | 325 ++++ .../source/build/pidl/packet-dcerpc-eparser.c | 177 ++ .../source/build/pidl/packet-dcerpc-eparser.h | 80 + SAMBA_3_2_MERGE/source/build/pidl/parser.pm | 1531 +++++++++++++++ SAMBA_3_2_MERGE/source/build/pidl/pidl.pl | 166 ++ SAMBA_3_2_MERGE/source/build/pidl/server.pm | 224 +++ SAMBA_3_2_MERGE/source/build/pidl/tables.pl | 97 + SAMBA_3_2_MERGE/source/build/pidl/template.pm | 86 + SAMBA_3_2_MERGE/source/build/pidl/util.pm | 379 ++++ SAMBA_3_2_MERGE/source/build/pidl/validator.pm | 138 ++ 17 files changed, 7062 insertions(+) create mode 100644 SAMBA_3_2_MERGE/source/build/pidl/Makefile create mode 100644 SAMBA_3_2_MERGE/source/build/pidl/client.pm create mode 100644 SAMBA_3_2_MERGE/source/build/pidl/dump.pm create mode 100644 SAMBA_3_2_MERGE/source/build/pidl/eparser.pm create mode 100644 SAMBA_3_2_MERGE/source/build/pidl/header.pm create mode 100644 SAMBA_3_2_MERGE/source/build/pidl/idl.gram create mode 100644 SAMBA_3_2_MERGE/source/build/pidl/idl.pm create mode 100644 SAMBA_3_2_MERGE/source/build/pidl/idl.yp create mode 100644 SAMBA_3_2_MERGE/source/build/pidl/packet-dcerpc-eparser.c create mode 100644 SAMBA_3_2_MERGE/source/build/pidl/packet-dcerpc-eparser.h create mode 100644 SAMBA_3_2_MERGE/source/build/pidl/parser.pm create mode 100755 SAMBA_3_2_MERGE/source/build/pidl/pidl.pl create mode 100644 SAMBA_3_2_MERGE/source/build/pidl/server.pm create mode 100755 SAMBA_3_2_MERGE/source/build/pidl/tables.pl create mode 100644 SAMBA_3_2_MERGE/source/build/pidl/template.pm create mode 100644 SAMBA_3_2_MERGE/source/build/pidl/util.pm create mode 100644 SAMBA_3_2_MERGE/source/build/pidl/validator.pm diff --git a/SAMBA_3_2_MERGE/source/build/pidl/Makefile b/SAMBA_3_2_MERGE/source/build/pidl/Makefile new file mode 100644 index 00000000000..e2cc7be3eb3 --- /dev/null +++ b/SAMBA_3_2_MERGE/source/build/pidl/Makefile @@ -0,0 +1,5 @@ +idl.pm: idl.yp + yapp -s idl.yp + +clean: + rm -f idl.pm diff --git a/SAMBA_3_2_MERGE/source/build/pidl/client.pm b/SAMBA_3_2_MERGE/source/build/pidl/client.pm new file mode 100644 index 00000000000..89d367f0377 --- /dev/null +++ b/SAMBA_3_2_MERGE/source/build/pidl/client.pm @@ -0,0 +1,76 @@ +################################################### +# client calls generator +# Copyright tridge@samba.org 2003 +# released under the GNU GPL + +package IdlClient; + +use strict; + +my($res); + +##################################################################### +# parse a function +sub ParseFunction($) +{ + my $fn = shift; + my $name = $fn->{NAME}; + my $uname = uc $name; + + $res .= +" +NTSTATUS dcerpc_$name(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, struct $name *r) +{ + NTSTATUS status; + + if (p->flags & DCERPC_DEBUG_PRINT_IN) { + NDR_PRINT_IN_DEBUG($name, r); + } + + status = dcerpc_ndr_request(p, DCERPC_$uname, mem_ctx, + (ndr_push_flags_fn_t) ndr_push_$name, + (ndr_pull_flags_fn_t) ndr_pull_$name, + r, sizeof(*r)); + + if (NT_STATUS_IS_OK(status) && (p->flags & DCERPC_DEBUG_PRINT_OUT)) { + NDR_PRINT_OUT_DEBUG($name, r); + } +"; + if ($fn->{RETURN_TYPE} eq "NTSTATUS") { + $res .= "\tif (NT_STATUS_IS_OK(status)) status = r->out.result;\n"; + } + $res .= +" + return status; +} +"; +} + + +##################################################################### +# parse the interface definitions +sub ParseInterface($) +{ + my($interface) = shift; + my($data) = $interface->{DATA}; + foreach my $d (@{$data}) { + ($d->{TYPE} eq "FUNCTION") && + ParseFunction($d); + } +} + + +##################################################################### +# parse a parsed IDL structure back into an IDL file +sub Parse($) +{ + my($idl) = shift; + $res = "/* dcerpc client calls generated by pidl */\n\n"; + foreach my $x (@{$idl}) { + ($x->{TYPE} eq "INTERFACE") && + ParseInterface($x); + } + return $res; +} + +1; diff --git a/SAMBA_3_2_MERGE/source/build/pidl/dump.pm b/SAMBA_3_2_MERGE/source/build/pidl/dump.pm new file mode 100644 index 00000000000..e74ffe6203d --- /dev/null +++ b/SAMBA_3_2_MERGE/source/build/pidl/dump.pm @@ -0,0 +1,241 @@ +################################################### +# dump function for IDL structures +# Copyright tridge@samba.org 2000 +# released under the GNU GPL + +package IdlDump; + +use strict; + +my($res); + +##################################################################### +# dump a properties list +sub DumpProperties($) +{ + my($props) = shift; + my($res); + + foreach my $d ($props) { + foreach my $k (keys %{$d}) { + if ($k eq "in") { + $res .= "[in] "; + next; + } + if ($k eq "out") { + $res .= "[out] "; + next; + } + if ($k eq "ref") { + $res .= "[ref] "; + next; + } + $res .= "[$k($d->{$k})] "; + } + } + return $res; +} + +##################################################################### +# dump a structure element +sub DumpElement($) +{ + my($element) = shift; + my($res); + + (defined $element->{PROPERTIES}) && + ($res .= DumpProperties($element->{PROPERTIES})); + $res .= DumpType($element->{TYPE}); + $res .= " "; + if ($element->{POINTERS}) { + for (my($i)=0; $i < $element->{POINTERS}; $i++) { + $res .= "*"; + } + } + $res .= "$element->{NAME}"; + (defined $element->{ARRAY_LEN}) && ($res .= "[$element->{ARRAY_LEN}]"); + + return $res; +} + +##################################################################### +# dump a struct +sub DumpStruct($) +{ + my($struct) = shift; + my($res); + + $res .= "struct {\n"; + if (defined $struct->{ELEMENTS}) { + foreach my $e (@{$struct->{ELEMENTS}}) { + $res .= DumpElement($e); + $res .= ";\n"; + } + } + $res .= "}"; + + return $res; +} + + +##################################################################### +# dump a struct +sub DumpEnum($) +{ + my($enum) = shift; + my($res); + + $res .= "enum"; + + return $res; +} + + +##################################################################### +# dump a union element +sub DumpUnionElement($) +{ + my($element) = shift; + my($res); + + if ($element->{CASE} eq "default") { + $res .= "[default] ;\n"; + } else { + $res .= "[case($element->{CASE})] "; + $res .= DumpElement($element->{DATA}), if defined($element->{DATA}); + $res .= ";\n"; + } + + return $res; +} + +##################################################################### +# dump a union +sub DumpUnion($) +{ + my($union) = shift; + my($res); + + (defined $union->{PROPERTIES}) && + ($res .= DumpProperties($union->{PROPERTIES})); + $res .= "union {\n"; + foreach my $e (@{$union->{DATA}}) { + $res .= DumpUnionElement($e); + } + $res .= "}"; + + return $res; +} + +##################################################################### +# dump a type +sub DumpType($) +{ + my($data) = shift; + my($res); + + if (ref($data) eq "HASH") { + ($data->{TYPE} eq "STRUCT") && + ($res .= DumpStruct($data)); + ($data->{TYPE} eq "UNION") && + ($res .= DumpUnion($data)); + ($data->{TYPE} eq "ENUM") && + ($res .= DumpEnum($data)); + } else { + $res .= "$data"; + } + + return $res; +} + +##################################################################### +# dump a typedef +sub DumpTypedef($) +{ + my($typedef) = shift; + my($res); + + $res .= "typedef "; + $res .= DumpType($typedef->{DATA}); + $res .= " $typedef->{NAME};\n\n"; + + return $res; +} + +##################################################################### +# dump a typedef +sub DumpFunction($) +{ + my($function) = shift; + my($first) = 1; + my($res); + + $res .= DumpType($function->{RETURN_TYPE}); + $res .= " $function->{NAME}(\n"; + for my $d (@{$function->{DATA}}) { + $first || ($res .= ",\n"); $first = 0; + $res .= DumpElement($d); + } + $res .= "\n);\n\n"; + + return $res; +} + +##################################################################### +# dump a module header +sub DumpModuleHeader($) +{ + my($header) = shift; + my($data) = $header->{DATA}; + my($first) = 1; + my($res); + + $res .= "[\n"; + foreach my $k (keys %{$data}) { + $first || ($res .= ",\n"); $first = 0; + $res .= "$k($data->{$k})"; + } + $res .= "\n]\n"; + + return $res; +} + +##################################################################### +# dump the interface definitions +sub DumpInterface($) +{ + my($interface) = shift; + my($data) = $interface->{DATA}; + my($res); + + $res .= "interface $interface->{NAME}\n{\n"; + foreach my $d (@{$data}) { + ($d->{TYPE} eq "TYPEDEF") && + ($res .= DumpTypedef($d)); + ($d->{TYPE} eq "FUNCTION") && + ($res .= DumpFunction($d)); + } + $res .= "}\n"; + + return $res; +} + + +##################################################################### +# dump a parsed IDL structure back into an IDL file +sub Dump($) +{ + my($idl) = shift; + my($res); + + $res = "/* Dumped by pidl */\n\n"; + foreach my $x (@{$idl}) { + ($x->{TYPE} eq "MODULEHEADER") && + ($res .= DumpModuleHeader($x)); + ($x->{TYPE} eq "INTERFACE") && + ($res .= DumpInterface($x)); + } + return $res; +} + +1; diff --git a/SAMBA_3_2_MERGE/source/build/pidl/eparser.pm b/SAMBA_3_2_MERGE/source/build/pidl/eparser.pm new file mode 100644 index 00000000000..fb8d0e39ca8 --- /dev/null +++ b/SAMBA_3_2_MERGE/source/build/pidl/eparser.pm @@ -0,0 +1,1022 @@ +################################################### +# Samba4 parser generator for IDL structures +# Copyright tridge@samba.org 2000-2003 +# Copyright tpot@samba.org 2001,2004 +# released under the GNU GPL + +package IdlEParser; + +use strict; + +# the list of needed functions +my %needed; +my %structs; + +my $module = "samr"; +my $if_uuid; +my $if_version; +my $if_endpoints; + +sub pidl($) +{ + print OUT shift; +} + +##################################################################### +# parse a properties list +sub ParseProperties($) +{ + my($props) = shift; + foreach my $d (@{$props}) { + if (ref($d) ne "HASH") { + pidl "[$d] "; + } else { + foreach my $k (keys %{$d}) { + pidl "[$k($d->{$k})] "; + } + } + } +} + +################################### +# find a sibling var in a structure +sub find_sibling($$) +{ + my($e) = shift; + my($name) = shift; + my($fn) = $e->{PARENT}; + + if ($name =~ /\*(.*)/) { + $name = $1; + } + + if ($fn->{TYPE} eq "FUNCTION") { + for my $e2 (@{$fn->{DATA}}) { + if ($e2->{NAME} eq $name) { + return $e2; + } + } + } + + for my $e2 (@{$fn->{ELEMENTS}}) { + if ($e2->{NAME} eq $name) { + return $e2; + } + } + die "invalid sibling '$name'"; +} + +#################################################################### +# work out the name of a size_is() variable +sub find_size_var($$$) +{ + my($e) = shift; + my($size) = shift; + my($var_prefix) = shift; + + my($fn) = $e->{PARENT}; + + if (util::is_constant($size)) { + return $size; + } + + if ($size =~ /ndr->|\(/) { + return $size; + } + + my $prefix = ""; + + if ($size =~ /\*(.*)/) { + $size = $1; + $prefix = "*"; + } + + if ($fn->{TYPE} ne "FUNCTION") { + return $prefix . "r->$size"; + } + + my $e2 = find_sibling($e, $size); + + 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"; + } + + die "invalid variable in $size for element $e->{NAME} in $fn->{NAME}\n"; +} + + +##################################################################### +# 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->{DATA}, "public")) { + return ""; + } + } + + if ($fn->{TYPE} eq "FUNCTION") { + if (util::has_property($fn, "public")) { + return ""; + } + } + 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 "\t{ guint32 _flags_save_$e->{TYPE} = ndr->flags;\n"; + pidl "\tndr->flags |= $flags;\n"; + } +} + +################################################################### +# 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 "\tndr->flags = _flags_save_$e->{TYPE};\n\t}\n"; + } +} + + +##################################################################### +# work out the correct alignment for a structure +sub struct_alignment +{ + my $s = shift; + + my $align = 1; + for my $e (@{$s->{ELEMENTS}}) { + my $a = 1; + + if (!util::need_wire_pointer($e) + && defined $structs{$e->{TYPE}}) { + if ($structs{$e->{TYPE}}->{DATA}->{TYPE} eq "STRUCT") { + $a = struct_alignment($structs{$e->{TYPE}}->{DATA}); + } elsif ($structs{$e->{TYPE}}->{DATA}->{TYPE} eq "UNION") { + if (defined $structs{$e->{TYPE}}->{DATA}) { + $a = union_alignment($structs{$e->{TYPE}}->{DATA}); + } + } + } else { + $a = util::type_align($e); + } + + if ($align < $a) { + $align = $a; + } + } + + return $align; +} + +##################################################################### +# work out the correct alignment for a union +sub union_alignment +{ + my $u = shift; + + my $align = 1; + + foreach my $e (@{$u->{DATA}}) { + my $a = 1; + + if ($e->{TYPE} eq "EMPTY") { + next; + } + + if (!util::need_wire_pointer($e) + && defined $structs{$e->{DATA}->{TYPE}}) { + my $s = $structs{$e->{DATA}->{TYPE}}; + if ($s->{DATA}->{TYPE} eq "STRUCT") { + $a = struct_alignment($s->{DATA}); + } elsif ($s->{DATA}->{TYPE} eq "UNION") { + $a = union_alignment($s->{DATA}); + } + } else { + $a = util::type_align($e->{DATA}); + } + + if ($align < $a) { + $align = $a; + } + } + + return $align; +} + +##################################################################### +# parse an array - pull side +sub ParseArrayPull($$$) +{ + my $e = shift; + my $var_prefix = shift; + my $ndr_flags = shift; + + my $size = find_size_var($e, util::array_size($e), $var_prefix); + my $alloc_size = $size; + + pidl "// ParseArrayPull under construction\n"; + return; + + pidl "\t{ guint32 _array_size;\n"; + # if this is a conformant array then we use that size to allocate, and make sure + # we allocate enough to pull the elements + if (defined $e->{CONFORMANT_SIZE}) { + $alloc_size = $e->{CONFORMANT_SIZE}; + + pidl "\tif ($size > $alloc_size) {\n"; + pidl "\t\treturn ndr_pull_error(ndr, \"Bad conformant size %u should be %u\", $alloc_size, $size);\n"; + pidl "\t}\n"; + } elsif (!util::is_inline_array($e)) { + if ($var_prefix =~ /^r->out/ && $size =~ /^\*r->in/) { + my $size2 = substr($size, 1); +# pidl "if (ndr->flags & LIBNDR_FLAG_REF_ALLOC) { NDR_ALLOC(ndr, $size2); }\n"; + } + + # non fixed arrays encode the size just before the array + pidl "\t{\n"; + pidl "\t\tdissect_ndr_uint32(ndr->tvb, ndr->offset, ndr->pinfo, ndr->tree, ndr->drep, hf_array_size, &_array_size);\n"; + if ($size =~ /r->in/) { + pidl "\t\t// if (!(ndr->flags & LIBNDR_FLAG_REF_ALLOC) && _array_size != $size) {\n"; + } else { + pidl "\t\t// if ($size != _array_size) {\n"; + } + pidl "\t\t\t// return ndr_pull_error(ndr, \"Bad array size %u should be %u\", _array_size, $size);\n"; + pidl "\t\t// }\n"; + if ($size =~ /r->in/) { + pidl "else { $size = _array_size; }\n"; + } + pidl "\t}\n"; + } + + if ((util::need_alloc($e) && !util::is_fixed_array($e)) || + ($var_prefix eq "r->in." && util::has_property($e, "ref"))) { + if (!util::is_inline_array($e) || $ndr_flags eq "NDR_SCALARS") { +# pidl "\t\tNDR_ALLOC_N(ndr, $var_prefix$e->{NAME}, MAX(1, $alloc_size));\n"; + } + } + + if (($var_prefix eq "r->out." && util::has_property($e, "ref"))) { + if (!util::is_inline_array($e) || $ndr_flags eq "NDR_SCALARS") { +# pidl "\tif (ndr->flags & LIBNDR_FLAG_REF_ALLOC) {"; +# pidl "\t\tNDR_ALLOC_N(ndr, $var_prefix$e->{NAME}, MAX(1, $alloc_size));\n"; +# pidl "\t}\n"; + } + } + + pidl "\t{\n"; + + if (my $length = util::has_property($e, "length_is")) { + $length = find_size_var($e, $length, $var_prefix); + pidl "\t\tguint32 _offset, _length;\n"; + pidl "\t\tndr_pull_uint32(ndr, &_offset);\n"; + pidl "\t\tndr_pull_uint32(ndr, &_length);\n"; + pidl "\t\tif (_offset != 0) return ndr_pull_error(ndr, \"Bad array offset 0x%08x\", _offset);\n"; + pidl "\t\t//if (_length > $size || _length != $length) return ndr_pull_error(ndr, \"Bad array length 0x%08x > size 0x%08x\", _offset, $size);\n\n"; + $size = "_length"; + } + + if (util::is_scalar_type($e->{TYPE})) { + pidl "\t\tndr_pull_array_$e->{TYPE}(ndr, $ndr_flags, _array_size);\n"; + } else { + pidl "\t\tndr_pull_array(ndr, $ndr_flags, /* sizeof($var_prefix$e->{NAME}\[0]), */ _array_size, ndr_pull_$e->{TYPE});\n"; + } + + pidl "\t}\n"; + pidl "\t}\n"; +} + + +##################################################################### +# parse scalars in a structure element - pull size +sub ParseElementPullSwitch($$$$) +{ + my($e) = shift; + my($var_prefix) = shift; + my($ndr_flags) = shift; + my $switch = shift; + my $switch_var = find_size_var($e, $switch, $var_prefix); + + my $cprefix = util::c_pull_prefix($e); + + my $utype = $structs{$e->{TYPE}}; + if (!defined $utype || + !util::has_property($utype->{DATA}, "nodiscriminant")) { + my $e2 = find_sibling($e, $switch); + pidl "\tint _level;\n"; + pidl "\tif (($ndr_flags) & NDR_SCALARS) {\n"; + pidl "\t\tndr_pull_level(ndr, hf_level, &_level);\n"; + if ($switch_var =~ /r->in/) { + pidl "\t\t // if (!(ndr->flags & LIBNDR_FLAG_REF_ALLOC) && _level != $switch_var) {\n"; + } else { + pidl "\t\t // if (_level != $switch_var) {\n"; + } + pidl "\t\t\t // return ndr_pull_error(ndr, \"Bad switch value %u in $e->{NAME}\");\t\t}\n"; + if ($switch_var =~ /r->/) { + pidl "// else { $switch_var = _level;\n }\n"; + } + pidl "\t// }\n"; + } + + my $sub_size = util::has_property($e, "subcontext"); + if (defined $sub_size) { + pidl "\tndr_pull_subcontext_union_fn(ndr, $sub_size, $switch_var, $cprefix$var_prefix$e->{NAME}, (ndr_pull_union_fn_t) ndr_pull_$e->{TYPE});\n"; + } else { + pidl "\tndr_pull_$e->{TYPE}(ndr, $ndr_flags, _level);\n"; + } + + +} + +##################################################################### +# parse scalars in a structure element - pull size +sub ParseElementPullScalar($$$) +{ + my($e) = shift; + my($var_prefix) = shift; + my($ndr_flags) = shift; + my $cprefix = util::c_pull_prefix($e); + my $sub_size = util::has_property($e, "subcontext"); + + start_flags($e); + + if (util::has_property($e, "relative")) { + pidl "\tndr_pull_relative(ndr, (const void **)&$var_prefix$e->{NAME}, sizeof(*$var_prefix$e->{NAME}), (ndr_pull_flags_fn_t)ndr_pull_$e->{TYPE});\n"; + } elsif (util::is_inline_array($e)) { + ParseArrayPull($e, "r->", "NDR_SCALARS"); + } elsif (util::need_wire_pointer($e)) { + pidl "\tndr_pull_ptr(ndr, hf_ptr, &_ptr_$e->{NAME});\n"; +# pidl "\tif (_ptr_$e->{NAME}) {\n"; +# pidl "\t\tNDR_ALLOC(ndr, $var_prefix$e->{NAME});\n"; +# pidl "\t} else {\n"; +# pidl "\t\t$var_prefix$e->{NAME} = NULL;\n"; +# pidl "\t}\n"; + } elsif (util::need_alloc($e)) { + # no scalar component + } elsif (my $switch = util::has_property($e, "switch_is")) { + ParseElementPullSwitch($e, $var_prefix, $ndr_flags, $switch); + } elsif (defined $sub_size) { + if (util::is_builtin_type($e->{TYPE})) { + pidl "\tndr_pull_subcontext_fn(ndr, $sub_size, $cprefix$var_prefix$e->{NAME}, (ndr_pull_fn_t) ndr_pull_$e->{TYPE});\n"; + } else { + pidl "\tndr_pull_subcontext_flags_fn(ndr, $sub_size, $cprefix$var_prefix$e->{NAME}, (ndr_pull_flags_fn_t) ndr_pull_$e->{TYPE});\n"; + } + } elsif (util::is_builtin_type($e->{TYPE}) || $e->{TYPE} eq "policy_handle") { + pidl "\tndr_pull_$e->{TYPE}(ndr, hf_$e->{NAME}_$e->{TYPE});\n"; + } else { + pidl "\tndr_pull_$e->{TYPE}(ndr, $ndr_flags);\n"; + } + + end_flags($e); +} + +##################################################################### +# parse buffers in a structure element - pull side +sub ParseElementPullBuffer($$$) +{ + my($e) = shift; + my($var_prefix) = shift; + my($ndr_flags) = shift; + my $cprefix = util::c_pull_prefix($e); + my $sub_size = util::has_property($e, "subcontext"); + + if (util::is_pure_scalar($e)) { + return; + } + + if (util::has_property($e, "relative")) { + return; + } + + start_flags($e); + + if (util::need_wire_pointer($e)) { + pidl "\tif (_ptr_$e->{NAME}) {\n"; + } + + if (util::is_inline_array($e)) { + ParseArrayPull($e, "r->", "NDR_BUFFERS"); + } elsif (util::array_size($e)) { + ParseArrayPull($e, "r->", "NDR_SCALARS|NDR_BUFFERS"); + } elsif (my $switch = util::has_property($e, "switch_is")) { + if ($e->{POINTERS}) { + ParseElementPullSwitch($e, $var_prefix, "NDR_SCALARS|NDR_BUFFERS", $switch); + } else { + ParseElementPullSwitch($e, $var_prefix, "NDR_BUFFERS", $switch); + } + } elsif (defined $sub_size) { + if ($e->{POINTERS}) { + if (util::is_builtin_type($e->{TYPE})) { + pidl "\tndr_pull_subcontext_fn(ndr, $sub_size, _pull_$e->{TYPE});\n"; + } else { + pidl "\tndr_pull_subcontext_flags_fn(ndr, $sub_size, ndr_pull_$e->{TYPE});\n"; + } + } + } elsif (util::is_builtin_type($e->{TYPE}) || $e->{TYPE} eq "policy_handle") { + pidl "\t\tndr_pull_$e->{TYPE}(ndr, hf_$e->{NAME}_$e->{TYPE});\n"; + } elsif ($e->{POINTERS}) { + pidl "\t\tndr_pull_$e->{TYPE}(ndr, NDR_SCALARS|NDR_BUFFERS);\n"; + } else { + pidl "\t\tndr_pull_$e->{TYPE}(ndr, $ndr_flags);\n"; + } + + if (util::need_wire_pointer($e)) { + pidl "\t}\n"; + } + + end_flags($e); +} + +##################################################################### +# parse a struct - pull side +sub ParseStructPull($) +{ + my($struct) = shift; + my $conform_e; + + if (! defined $struct->{ELEMENTS}) { + return; + } + + # 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 (defined $e->{ARRAY_LEN} && $e->{ARRAY_LEN} eq "*") { + $conform_e = $e; + pidl "\tguint32 _conformant_size;\n"; + $conform_e->{CONFORMANT_SIZE} = "_conformant_size"; + } + + # declare any internal pointers we need + foreach my $e (@{$struct->{ELEMENTS}}) { + if (util::need_wire_pointer($e) && + !util::has_property($e, "relative")) { + pidl "\tguint32 _ptr_$e->{NAME};\n"; + } + } + + start_flags($struct); + + pidl "\tif (!(ndr_flags & NDR_SCALARS)) goto buffers;\n"; + + pidl "\tndr_pull_struct_start(ndr);\n"; + + if (defined $conform_e) { + pidl "\tndr_pull_uint32(ndr, &$conform_e->{CONFORMANT_SIZE});\n"; + } + + my $align = struct_alignment($struct); + pidl "\tndr_pull_align(ndr, $align);\n"; + + foreach my $e (@{$struct->{ELEMENTS}}) { + ParseElementPullScalar($e, "r->", "NDR_SCALARS"); + } + + pidl "buffers:\n"; + pidl "\tif (!(ndr_flags & NDR_BUFFERS)) goto done;\n"; + foreach my $e (@{$struct->{ELEMENTS}}) { + ParseElementPullBuffer($e, "r->", "NDR_BUFFERS"); + } + + pidl "\tndr_pull_struct_end(ndr);\n"; + + pidl "done: ;\n"; + + end_flags($struct); +} + +##################################################################### +# parse a union - pull side +sub ParseUnionPull($) +{ + my $e = shift; + my $have_default = 0; + + start_flags($e); + + pidl "\tif (!(ndr_flags & NDR_SCALARS)) goto buffers;\n"; + + pidl "\tndr_pull_struct_start(ndr);\n"; + +# my $align = union_alignment($e); +# pidl "\tndr_pull_align(ndr, $align);\n"; + + pidl "\tswitch (level) {\n"; + foreach my $el (@{$e->{DATA}}) { + if ($el->{CASE} eq "default") { + pidl "\tdefault: {\n"; + $have_default = 1; + } else { + pidl "\tcase $el->{CASE}: {\n"; + } + if ($el->{TYPE} eq "UNION_ELEMENT") { + my $e2 = $el->{DATA}; + if ($e2->{POINTERS}) { + pidl "\t\tguint32 _ptr_$e2->{NAME};\n"; + } + ParseElementPullScalar($el->{DATA}, "r->", "NDR_SCALARS"); + } + pidl "\tbreak; }\n\n"; + } + if (! $have_default) { + pidl "\tdefault:\n"; + pidl "\t\t// return ndr_pull_error(ndr, \"Bad switch value \%u\", level);\n"; + } + pidl "\t}\n"; + pidl "buffers:\n"; + pidl "\tif (!(ndr_flags & NDR_BUFFERS)) goto done;\n"; + pidl "\tswitch (level) {\n"; + foreach my $el (@{$e->{DATA}}) { + if ($el->{CASE} eq "default") { + pidl "\tdefault:\n"; + } else { + pidl "\tcase $el->{CASE}:\n"; + } + if ($el->{TYPE} eq "UNION_ELEMENT") { + ParseElementPullBuffer($el->{DATA}, "r->", "NDR_BUFFERS"); + } + pidl "\tbreak;\n\n"; + } + if (! $have_default) { + pidl "\tdefault:\n"; + pidl "\t\t// return ndr_pull_error(ndr, \"Bad switch value \%u\", level);\n"; + } + pidl "\t}\n"; + pidl "\tndr_pull_struct_end(ndr);\n"; + pidl "done:\n"; + end_flags($e); +} + +##################################################################### +# parse a enum - pull side +sub ParseEnumPull($) +{ + my $e = shift; + + my $name; + my $ndx = 0; + + for my $x (@{$e->{ELEMENTS}}) { + if ($x =~ /([a-zA-Z_]+)=([0-9]+)/) { + $name = $1; + $ndx = $2; + } else { + $name = $x; + } + pidl "#define $name $ndx\n"; + $ndx++; + } +} + +##################################################################### +# parse a type +sub ParseTypePull($) +{ + my($data) = shift; + + if (ref($data) eq "HASH") { + ($data->{TYPE} eq "STRUCT") && + ParseStructPull($data); + ($data->{TYPE} eq "UNION") && + ParseUnionPull($data); + ($data->{TYPE} eq "ENUM") && + ParseEnumPull($data); + } +} + +##################################################################### +# parse a typedef - pull side +sub ParseTypedefPull($) +{ + my($e) = shift; + my $static = fn_prefix($e); + +# if (! $needed{"pull_$e->{NAME}"}) { +# print "pull_$e->{NAME} not needed\n"; +# return; +# } + + pidl "/*\n\n"; + pidl IdlDump::DumpTypedef($e); + pidl "*/\n\n"; + + if ($e->{DATA}->{TYPE} eq "STRUCT") { + pidl $static . "void ndr_pull_$e->{NAME}(struct e_ndr_pull *ndr, int ndr_flags)"; + pidl "\n{\n"; + ParseTypePull($e->{DATA}); + pidl "}\n\n"; + } + + if ($e->{DATA}->{TYPE} eq "UNION") { + pidl $static . "void ndr_pull_$e->{NAME}(struct e_ndr_pull *ndr, int ndr_flags, int level)"; + pidl "\n{\n"; + ParseTypePull($e->{DATA}); + pidl "}\n\n"; + } + + if ($e->{DATA}->{TYPE} eq "ENUM") { + ParseEnumPull($e->{DATA}); + } +} + + +##################################################################### +# parse a function element +sub ParseFunctionElementPull($$) +{ + my $e = shift; + my $inout = shift; + + if (util::array_size($e)) { + if (util::need_wire_pointer($e)) { + pidl "\tndr_pull_ptr(ndr, &_ptr_$e->{NAME});\n"; + pidl "\tif (_ptr_$e->{NAME}) {\n"; + } elsif ($inout eq "out" && util::has_property($e, "ref")) { + pidl "\tif (r->$inout.$e->{NAME}) {\n"; + } else { + pidl "\t{\n"; + } + ParseArrayPull($e, "r->$inout.", "NDR_SCALARS|NDR_BUFFERS"); + pidl "\t}\n"; + } else { + if ($inout eq "out" && util::has_property($e, "ref")) { +# pidl "\tif (ndr->flags & LIBNDR_FLAG_REF_ALLOC) {\n"; +# pidl "\tNDR_ALLOC(ndr, r->out.$e->{NAME});\n"; +# pidl "\t}\n"; + } + if ($inout eq "in" && util::has_property($e, "ref")) { +# pidl "\tNDR_ALLOC(ndr, r->in.$e->{NAME});\n"; + } + + ParseElementPullScalar($e, "r->$inout.", "NDR_SCALARS|NDR_BUFFERS"); + if ($e->{POINTERS}) { + ParseElementPullBuffer($e, "r->$inout.", "NDR_SCALARS|NDR_BUFFERS"); + } + } +} + +##################################################################### +# parse a function +sub ParseFunctionPull($) +{ + my($fn) = shift; + my $static = fn_prefix($fn); + + # Comment displaying IDL for this function + + pidl "/*\n\n"; + pidl IdlDump::DumpFunction($fn); + pidl "*/\n\n"; + + # Request + + pidl $static . "int $fn->{NAME}_rqst(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, guint8 *drep)\n"; + pidl "{\n"; + pidl "\tstruct e_ndr_pull *ndr = ndr_pull_init(tvb, offset, pinfo, tree, drep);\n"; + + # declare any internal pointers we need + foreach my $e (@{$fn->{DATA}}) { + if (util::need_wire_pointer($e) && + util::has_property($e, "in")) { + pidl "\tguint32 _ptr_$e->{NAME};\n"; + } + } + + foreach my $e (@{$fn->{DATA}}) { + if (util::has_property($e, "in")) { + ParseFunctionElementPull($e, "in"); + } + } + + pidl "\toffset = ndr->offset;\n"; + pidl "\tndr_pull_free(ndr);\n"; + pidl "\treturn offset;\n"; + pidl "}\n\n"; + + # Response + + pidl $static . "int $fn->{NAME}_resp(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, guint8 *drep)\n"; + pidl "{\n"; + pidl "\tstruct e_ndr_pull *ndr = ndr_pull_init(tvb, offset, pinfo, tree, drep);\n"; + + # declare any internal pointers we need + foreach my $e (@{$fn->{DATA}}) { + if (util::need_wire_pointer($e) && + util::has_property($e, "out")) { + pidl "\tguint32 _ptr_$e->{NAME};\n"; + } + } + + foreach my $e (@{$fn->{DATA}}) { + if (util::has_property($e, "out")) { + ParseFunctionElementPull($e, "out"); + } + } + + if ($fn->{RETURN_TYPE} && $fn->{RETURN_TYPE} ne "void") { + pidl "\tndr_pull_$fn->{RETURN_TYPE}(ndr, hf_rc);\n"; + } + + pidl "\toffset = ndr->offset;\n"; + pidl "\tndr_pull_free(ndr);\n"; + pidl "\treturn offset;\n"; + pidl "}\n\n"; +} + +##################################################################### +# produce a function call table +sub FunctionTable($) +{ + my($interface) = shift; + my($data) = $interface->{DATA}; + my $count = 0; + my $uname = uc $interface->{NAME}; + + foreach my $d (@{$data}) { + if ($d->{TYPE} eq "FUNCTION") { $count++; } + } + + if ($count == 0) { + return; + } + + 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"; +} + +##################################################################### +# parse the interface definitions +sub ParseInterface($) +{ + my($interface) = shift; + my($data) = $interface->{DATA}; + + foreach my $d (@{$data}) { + if ($d->{TYPE} eq "TYPEDEF") { + $structs{$d->{NAME}} = $d; + } + } + + foreach my $d (@{$data}) { + ($d->{TYPE} eq "TYPEDEF") && + ParseTypedefPull($d); + ($d->{TYPE} eq "FUNCTION") && + ParseFunctionPull($d); + } + + FunctionTable($interface); +} + +sub type2ft($) +{ + my($t) = shift; + + return "FT_UINT32", if ($t eq "uint32"); + return "FT_UINT16", if ($t eq "uint16"); + return "FT_BYTES"; +} + +sub type2base($) +{ + my($t) = shift; + + return "BASE_DEC", if ($t eq "uint32") or ($t eq "uint16"); + return "BASE_NONE"; +} + +sub NeededFunction($) +{ + my $fn = shift; + foreach my $e (@{$fn->{DATA}}) { + $needed{"hf_$e->{NAME}_$e->{TYPE}"} = { + 'name' => $e->{NAME}, + 'type' => $e->{TYPE}, + 'ft' => type2ft($e->{TYPE}), + 'base' => type2base($e->{TYPE}) + }; + $needed{"proto_$e->{TYPE}"} = 1, + if !util::is_builtin_type($e->{TYPE}); + $e->{PARENT} = $fn; + } +} + +sub NeededTypedef($) +{ + my $t = shift; + + if (util::has_property($t->{DATA}, "public")) { + $needed{"pull_$t->{NAME}"} = 1; + } + + if ($t->{DATA}->{TYPE} eq "STRUCT") { + for my $e (@{$t->{DATA}->{ELEMENTS}}) { + + $needed{"hf_$e->{NAME}_$e->{TYPE}"} = { + 'name' => $e->{NAME}, + 'type' => $e->{TYPE}, + 'ft' => type2ft($e->{TYPE}), + 'base' => type2base($e->{TYPE}) + }; + + $needed{"proto_$e->{TYPE}"} = 1, + if !util::is_builtin_type($e->{TYPE}); + + $e->{PARENT} = $t->{DATA}; + if ($needed{"pull_$t->{NAME}"}) { + $needed{"pull_$e->{TYPE}"} = 1; + } + } + } + if ($t->{DATA}->{TYPE} eq "UNION") { + $needed{"proto_$t->{NAME}"} = "union"; + for my $e (@{$t->{DATA}->{DATA}}) { + $e->{PARENT} = $t->{DATA}; + if ($e->{TYPE} eq "UNION_ELEMENT") { + $needed{"proto_$e->{DATA}->{TYPE}"} = 1; + if ($needed{"pull_$t->{NAME}"}) { + $needed{"pull_$e->{DATA}->{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); + } +} + +##################################################################### +# parse the interface definitions +sub ModuleHeader($) +{ + my($h) = shift; + + $if_uuid = $h->{PROPERTIES}->{uuid}; + $if_version = $h->{PROPERTIES}->{version}; + $if_endpoints = $h->{PROPERTIES}->{endpoints}; +} + +##################################################################### +# parse a parsed IDL structure back into an IDL file +sub Parse($$) +{ + my($idl) = shift; + my($filename) = shift; + + open(OUT, ">$filename") || die "can't open $filename"; + + pidl "/* parser auto-generated by pidl */\n\n"; + pidl "#ifdef HAVE_CONFIG_H\n"; + pidl "#include \"config.h\"\n"; + pidl "#endif\n\n"; + + pidl "#include \"packet-dcerpc.h\"\n"; + pidl "#include \"packet-dcerpc-nt.h\"\n\n"; + pidl "#include \"packet-dcerpc-eparser.h\"\n\n"; + + pidl "extern const value_string NT_errors[];\n\n"; + + pidl "static int proto_dcerpc_$module = -1;\n\n"; + + pidl "static gint ett_dcerpc_$module = -1;\n\n"; + + pidl "static int hf_opnum = -1;\n"; + pidl "static int hf_rc = -1;\n"; + pidl "static int hf_ptr = -1;\n"; + pidl "static int hf_array_size = -1;\n"; + pidl "static int hf_level = -1;\n"; + + foreach my $x (@{$idl}) { + ($x->{TYPE} eq "MODULEHEADER") && + ModuleHeader($x); + + if ($x->{TYPE} eq "INTERFACE") { + BuildNeeded($x); + + # Declarations for hf variables + + foreach my $y (keys(%needed)) { + pidl "static int $y = -1;\n", if $y =~ /^hf_/; + } + + # Function prototypes + + foreach my $x (keys(%needed)) { + next, if !($x =~ /^proto_/); + my $name = $x; + $name =~ s/^proto_//; + pidl "void ndr_pull_$name(struct e_ndr_pull *ndr, int ndr_flags"; + + pidl ", int level", if $needed{$x} eq "union"; + + pidl ");\n"; + } + + ParseInterface($x); + } + } + + pidl "static e_uuid_t uuid_dcerpc_$module = {\n"; + pidl "\t0x" . substr($if_uuid, 0, 8); + pidl ", 0x" . substr($if_uuid, 9, 4); + pidl ", 0x" . substr($if_uuid, 14, 4) . ",\n"; + pidl "\t{ 0x" . substr($if_uuid, 19, 2); + pidl ", 0x" . substr($if_uuid, 21, 2); + pidl ", 0x" . substr($if_uuid, 24, 2); + pidl ", 0x" . substr($if_uuid, 26, 2); + pidl ", 0x" . substr($if_uuid, 28, 2); + pidl ", 0x" . substr($if_uuid, 30, 2); + pidl ", 0x" . substr($if_uuid, 32, 2); + pidl ", 0x" . substr($if_uuid, 34, 2) . " }\n"; + pidl "};\n\n"; + + pidl "static guint16 ver_dcerpc_$module = " . $if_version . ";\n\n"; + + + pidl "void proto_register_dcerpc_samr(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_rc, { \"Return code\", \"$module.rc\", FT_UINT32, BASE_HEX, VALS(NT_errors), 0x0, \"Return status code\", HFILL }},\n"; + pidl "\t{ &hf_array_size, { \"Array size\", \"$module.array_size\", FT_UINT32, BASE_DEC, NULL, 0x0, \"Array size\", HFILL }},\n"; + pidl "\t{ &hf_level, { \"Level\", \"$module.level\", FT_UINT32, BASE_DEC, NULL, 0x0, \"Level\", 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"; + pidl "\t { \"$needed{$x}{name}\", \"$x\", $needed{$x}{ft}, $needed{$x}{base},\n"; + pidl"\t NULL, 0, \"$x\", HFILL }},\n"; + } + + pidl "\t};\n\n"; + + pidl "\tstatic gint *ett[] = {\n"; + pidl "\t\t&ett_dcerpc_$module,\n"; + pidl "\t};\n\n"; + + pidl "\tproto_dcerpc_$module = proto_register_protocol(\"$module\", \"$module\", \"$module\");\n\n"; + + pidl "\tproto_register_field_array(proto_dcerpc_$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_$module(void)\n"; + pidl "{\n"; + pidl "\tdcerpc_init_uuid(proto_dcerpc_$module, ett_dcerpc_$module, \n"; + pidl "\t\t&uuid_dcerpc_$module, ver_dcerpc_$module, \n"; + pidl "\t\tdcerpc_dissectors, hf_opnum);\n"; + pidl "}\n"; + + close(OUT); +} + +1; diff --git a/SAMBA_3_2_MERGE/source/build/pidl/header.pm b/SAMBA_3_2_MERGE/source/build/pidl/header.pm new file mode 100644 index 00000000000..c1b6eb44a14 --- /dev/null +++ b/SAMBA_3_2_MERGE/source/build/pidl/header.pm @@ -0,0 +1,335 @@ +################################################### +# create C header files for an IDL structure +# Copyright tridge@samba.org 2000 +# released under the GNU GPL + +package IdlHeader; + +use strict; + +my($res); +my($tab_depth); +my $if_uuid; +my $if_version; + +sub tabs() +{ + for (my($i)=0; $i < $tab_depth; $i++) { + $res .= "\t"; + } +} + +##################################################################### +# parse a properties list +sub HeaderProperties($) +{ + my($props) = shift; + + return; + + foreach my $d (@{$props}) { + if (ref($d) ne "HASH") { + $res .= "/* [$d] */ "; + } else { + foreach my $k (keys %{$d}) { + $res .= "/* [$k($d->{$k})] */ "; + } + } + } +} + +##################################################################### +# parse a structure element +sub HeaderElement($) +{ + my($element) = shift; + + (defined $element->{PROPERTIES}) && HeaderProperties($element->{PROPERTIES}); + $res .= tabs(); + HeaderType($element, $element->{TYPE}, ""); + $res .= " "; + if ($element->{POINTERS} && + $element->{TYPE} ne "string") { + my($n) = $element->{POINTERS}; + for (my($i)=$n; $i > 0; $i--) { + $res .= "*"; + } + } + if (defined $element->{ARRAY_LEN} && + !util::is_constant($element->{ARRAY_LEN}) && + !$element->{POINTERS}) { + # conformant arrays are ugly! I choose to implement them with + # pointers instead of the [1] method + $res .= "*"; + } + $res .= "$element->{NAME}"; + if (defined $element->{ARRAY_LEN} && util::is_constant($element->{ARRAY_LEN})) { + $res .= "[$element->{ARRAY_LEN}]"; + } + $res .= ";\n"; +} + +##################################################################### +# parse a struct +sub HeaderStruct($$) +{ + my($struct) = shift; + my($name) = shift; + $res .= "\nstruct $name {\n"; + $tab_depth++; + if (defined $struct->{ELEMENTS}) { + foreach my $e (@{$struct->{ELEMENTS}}) { + HeaderElement($e); + } + } + $tab_depth--; + $res .= "}"; +} + +##################################################################### +# parse a struct +sub HeaderEnum($$) +{ + my($enum) = shift; + my($name) = shift; + $res .= "\nenum $name {\n"; + $tab_depth++; + my $els = \@{$enum->{ELEMENTS}}; + foreach my $i (0 .. $#{$els}-1) { + my $e = ${$els}[$i]; + tabs(); + chomp $e; + $res .= "$e,\n"; + } + + my $e = ${$els}[$#{$els}]; + tabs(); + chomp $e; + if ($e !~ /^(.*?)\s*$/) { + die "Bad enum $name\n"; + } + $res .= "$1\n"; + $tab_depth--; + $res .= "}"; +} + + +##################################################################### +# parse a union +sub HeaderUnion($$) +{ + my($union) = shift; + my($name) = shift; + my %done = (); + + (defined $union->{PROPERTIES}) && HeaderProperties($union->{PROPERTIES}); + $res .= "\nunion $name {\n"; + $tab_depth++; + foreach my $e (@{$union->{DATA}}) { + if ($e->{TYPE} eq "UNION_ELEMENT") { + if (! defined $done{$e->{DATA}->{NAME}}) { + HeaderElement($e->{DATA}); + } + $done{$e->{DATA}->{NAME}} = 1; + } + } + $tab_depth--; + $res .= "}"; +} + +##################################################################### +# parse a type +sub HeaderType($$$) +{ + my $e = shift; + my($data) = shift; + my($name) = shift; + if (ref($data) eq "HASH") { + ($data->{TYPE} eq "ENUM") && + HeaderEnum($data, $name); + ($data->{TYPE} eq "STRUCT") && + HeaderStruct($data, $name); + ($data->{TYPE} eq "UNION") && + HeaderUnion($data, $name); + return; + } + if ($data =~ "string") { + $res .= "const char *"; + } elsif (util::is_scalar_type($data)) { + $res .= "$data"; + } elsif (util::has_property($e, "switch_is")) { + $res .= "union $data"; + } else { + $res .= "struct $data"; + } +} + +##################################################################### +# parse a typedef +sub HeaderTypedef($) +{ + my($typedef) = shift; + HeaderType($typedef, $typedef->{DATA}, $typedef->{NAME}); + $res .= ";\n"; +} + +##################################################################### +# parse a typedef +sub HeaderConst($) +{ + my($const) = shift; + $res .= "#define $const->{NAME}\t( $const->{VALUE} )\n"; +} + +##################################################################### +# parse a function +sub HeaderFunctionInOut($$) +{ + my($fn) = shift; + my($prop) = shift; + foreach my $e (@{$fn->{DATA}}) { + if (util::has_property($e, $prop)) { + HeaderElement($e); + } + } +} + +##################################################################### +# determine if we need an "in" or "out" section +sub HeaderFunctionInOut_needed($$) +{ + my($fn) = shift; + my($prop) = shift; + + if ($prop eq "out" && $fn->{RETURN_TYPE} && $fn->{RETURN_TYPE} ne "void") { + return 1; + } + + foreach my $e (@{$fn->{DATA}}) { + if (util::has_property($e, $prop)) { + return 1; + } + } + + return undef; +} + + +##################################################################### +# parse a function +sub HeaderFunction($) +{ + my($fn) = shift; + $res .= "\nstruct $fn->{NAME} {\n"; + $tab_depth++; + my $needed = 0; + + if (HeaderFunctionInOut_needed($fn, "in")) { + tabs(); + $res .= "struct {\n"; + $tab_depth++; + HeaderFunctionInOut($fn, "in"); + $tab_depth--; + tabs(); + $res .= "} in;\n\n"; + $needed++; + } + + if (HeaderFunctionInOut_needed($fn, "out")) { + tabs(); + $res .= "struct {\n"; + $tab_depth++; + HeaderFunctionInOut($fn, "out"); + if ($fn->{RETURN_TYPE} && $fn->{RETURN_TYPE} ne "void") { + tabs(); + $res .= "$fn->{RETURN_TYPE} result;\n"; + } + $tab_depth--; + tabs(); + $res .= "} out;\n\n"; + $needed++; + } + + if (! $needed) { + # sigh - some compilers don't like empty structures + tabs(); + $res .= "int _dummy_element;\n"; + } + + $tab_depth--; + $res .= "};\n\n"; +} + +##################################################################### +# parse the interface definitions +sub HeaderInterface($) +{ + my($interface) = shift; + my($data) = $interface->{DATA}; + + my $count = 0; + + $res .= "#ifndef _HEADER_NDR_$interface->{NAME}\n"; + $res .= "#define _HEADER_NDR_$interface->{NAME}\n\n"; + + if (defined $if_uuid) { + my $name = uc $interface->{NAME}; + $res .= "#define DCERPC_$name\_UUID \"$if_uuid\"\n"; + $res .= "#define DCERPC_$name\_VERSION $if_version\n"; + $res .= "#define DCERPC_$name\_NAME \"$interface->{NAME}\"\n\n"; + $res .= "extern const struct dcerpc_interface_table dcerpc_table_$interface->{NAME};\n"; + $res .= "NTSTATUS dcerpc_$interface->{NAME}_init(void);\n\n"; + } + + foreach my $d (@{$data}) { + if ($d->{TYPE} eq "FUNCTION") { + my $u_name = uc $d->{NAME}; + $res .= "#define DCERPC_$u_name " . sprintf("0x%02x", $count) . "\n"; + $count++; + } + } + + $res .= "\n\n"; + + foreach my $d (@{$data}) { + ($d->{TYPE} eq "CONST") && + HeaderConst($d); + ($d->{TYPE} eq "TYPEDEF") && + HeaderTypedef($d); + ($d->{TYPE} eq "FUNCTION") && + HeaderFunction($d); + } + + $res .= "#endif /* _HEADER_NDR_$interface->{NAME} */\n"; +} + +##################################################################### +# parse the interface definitions +sub ModuleHeader($) +{ + my($h) = shift; + + $if_uuid = $h->{PROPERTIES}->{uuid}; + $if_version = $h->{PROPERTIES}->{version}; +} + + +##################################################################### +# parse a parsed IDL into a C header +sub Parse($) +{ + my($idl) = shift; + $tab_depth = 0; + + $res = "/* header auto-generated by pidl */\n\n"; + foreach my $x (@{$idl}) { + ($x->{TYPE} eq "MODULEHEADER") && + ModuleHeader($x); + + ($x->{TYPE} eq "INTERFACE") && + HeaderInterface($x); + } + return $res; +} + +1; diff --git a/SAMBA_3_2_MERGE/source/build/pidl/idl.gram b/SAMBA_3_2_MERGE/source/build/pidl/idl.gram new file mode 100644 index 00000000000..fdadb91c5ce --- /dev/null +++ b/SAMBA_3_2_MERGE/source/build/pidl/idl.gram @@ -0,0 +1,183 @@ +{ + use util; +} + +idl: idl_interface(s) + {{ util::FlattenArray($item[1]) }} + | + +idl_interface: module_header interface + { [$item{module_header}, $item{interface}] } + | + +module_header: '[' module_param(s? /,/) ']' + {{ + "TYPE" => "MODULEHEADER", + "PROPERTIES" => util::FlattenHash($item[3]) + }} + | + +module_param: identifier '(' text ')' + {{ "$item{identifier}" => "$item{text}" }} + | + +interface: 'interface' identifier '{' definition(s?) '}' + {{ + "TYPE" => "INTERFACE", + "NAME" => $item{identifier}, + "DATA" => $item[5] + }} + | + +definition : typedef { $item[1] } + | function { $item[1] } + | const { $item[1] } + +const : 'const' identifier identifier '=' anytext ';' + {{ + "TYPE" => "CONST", + "DTYPE" => $item[3], + "NAME" => $item[4], + "VALUE" => $item{anytext} + }} + | + +typedef : 'typedef' type identifier array_len(?) ';' + {{ + "TYPE" => "TYPEDEF", + "NAME" => $item{identifier}, + "DATA" => $item{type}, + "ARRAY_LEN" => $item[5][0] + }} + | + +enum: 'enum' '{' enum_element(s? /,/) '}' + {{ + "TYPE" => "ENUM", + "ELEMENTS" => $item[4] + }} + | + +enum_element: /[\w\s=]+/ + +struct: property_list(s?) 'struct' '{' element_list1(?) '}' + {{ + "TYPE" => "STRUCT", + "PROPERTIES" => util::FlattenArray($item[1]), + "ELEMENTS" => util::FlattenArray2($item[5]) + }} + | + +union: property_list(s?) 'union' '{' union_element(s?) '}' + {{ + "TYPE" => "UNION", + "PROPERTIES" => util::FlattenArray($item[1]), + "DATA" => $item[5] + }} + | + +union_element: + '[' 'case' '(' identifier ')' ']' base_element ';' + {{ + "TYPE" => "UNION_ELEMENT", + "CASE" => $item{identifier}, + "DATA" => $item{base_element} + }} + | '[' 'case' '(' identifier ')' ']' ';' + {{ + "TYPE" => "EMPTY", + "CASE" => $item{identifier}, + }} + | '[' 'default' ']' base_element ';' + {{ + "TYPE" => "UNION_ELEMENT", + "CASE" => "default", + "DATA" => $item{base_element} + }} + | '[' 'default' ']' ';' + {{ + "TYPE" => "EMPTY", + "CASE" => "default", + }} + +base_element: property_list(s?) type pointer(s?) identifier array_len(?) + {{ + "NAME" => $item{identifier}, + "TYPE" => $item{type}, + "PROPERTIES" => util::FlattenArray($item[1]), + "POINTERS" => $#{$item[3]}==-1?undef:$#{$item[3]}+1, + "ARRAY_LEN" => $item[5][0] + }} + | + +array_len: + '[' ']' + { "*" } + | '[' '*' ']' + { "*" } + | '[' anytext ']' + { "$item{anytext}" } + | + +element_list1: base_element(s? /;/) ';' + { $item[1] } + +element_list2: 'void' + | base_element(s? /,/) + { $item[1] } + +pointer: '*' + +property_list: '[' property(s /,/) ']' + { $item[3] } + | + +property: 'unique' + | 'in' + | 'out' + | 'ref' + | 'public' + | 'noprint' + | 'relative' + | 'nodiscriminant' + | 'subcontext' '(' constant ')' {{ "$item[1]" => "$item{constant}" }} + | 'flag' '(' anytext ')' {{ "$item[1]" => "$item{anytext}" }} + | 'size_is' '(' expression ')' {{ "$item[1]" => "$item{expression}" }} + | 'length_is' '(' expression ')' {{ "$item[1]" => "$item{expression}" }} + | 'switch_is' '(' expression ')' {{ "$item[1]" => "$item{expression}" }} + | 'value' '(' anytext ')' {{ "$item[1]" => "$item{anytext}" }} + +identifier: /[\w?]+/ + +expression: /[\w.?\/+*-_]+/ + +function : property_list(s?) type identifier '(' element_list2 ');' + {{ + "TYPE" => "FUNCTION", + "NAME" => $item{identifier}, + "RETURN_TYPE" => $item{type}, + "PROPERTIES" => util::FlattenArray($item[1]), + "DATA" => $item{element_list2} + }} + | + +type : + struct { $item[1] } + | union { $item[1] } + | enum { $item[1] } + | identifier { $item[1] } + | + +text: /[\w\s\..?-]*/ + +text2: /[\|\w\s,\*&\>"\/\..?-]*/ + +anytext: text2 '(' anytext ')' anytext + {{ "$item[1]($item[4])$item[6]" }} + | text2 '+' anytext + {{ "$item[1]+$item[3]" }} + | text2 + +constant: /-?[\dx]+/ + | '*' + diff --git a/SAMBA_3_2_MERGE/source/build/pidl/idl.pm b/SAMBA_3_2_MERGE/source/build/pidl/idl.pm new file mode 100644 index 00000000000..e469c0fdc8c --- /dev/null +++ b/SAMBA_3_2_MERGE/source/build/pidl/idl.pm @@ -0,0 +1,1997 @@ +#################################################################### +# +# This file was generated using Parse::Yapp version 1.05. +# +# Don't edit this file, use source file instead. +# +# ANY CHANGE MADE HERE WILL BE LOST ! +# +#################################################################### +package idl; +use vars qw ( @ISA ); +use strict; + +@ISA= qw ( Parse::Yapp::Driver ); +#Included Parse/Yapp/Driver.pm file---------------------------------------- +{ +# +# Module Parse::Yapp::Driver +# +# This module is part of the Parse::Yapp package available on your +# nearest CPAN +# +# Any use of this module in a standalone parser make the included +# text under the same copyright as the Parse::Yapp module itself. +# +# This notice should remain unchanged. +# +# (c) Copyright 1998-2001 Francois Desarmenien, all rights reserved. +# (see the pod text in Parse::Yapp module for use and distribution rights) +# + +package Parse::Yapp::Driver; + +require 5.004; + +use strict; + +use vars qw ( $VERSION $COMPATIBLE $FILENAME ); + +$VERSION = '1.05'; +$COMPATIBLE = '0.07'; +$FILENAME=__FILE__; + +use Carp; + +#Known parameters, all starting with YY (leading YY will be discarded) +my(%params)=(YYLEX => 'CODE', 'YYERROR' => 'CODE', YYVERSION => '', + YYRULES => 'ARRAY', YYSTATES => 'ARRAY', YYDEBUG => ''); +#Mandatory parameters +my(@params)=('LEX','RULES','STATES'); + +sub new { + my($class)=shift; + my($errst,$nberr,$token,$value,$check,$dotpos); + my($self)={ ERROR => \&_Error, + ERRST => \$errst, + NBERR => \$nberr, + TOKEN => \$token, + VALUE => \$value, + DOTPOS => \$dotpos, + STACK => [], + DEBUG => 0, + CHECK => \$check }; + + _CheckParams( [], \%params, \@_, $self ); + + exists($$self{VERSION}) + and $$self{VERSION} < $COMPATIBLE + and croak "Yapp driver version $VERSION ". + "incompatible with version $$self{VERSION}:\n". + "Please recompile parser module."; + + ref($class) + and $class=ref($class); + + bless($self,$class); +} + +sub YYParse { + my($self)=shift; + my($retval); + + _CheckParams( \@params, \%params, \@_, $self ); + + if($$self{DEBUG}) { + _DBLoad(); + $retval = eval '$self->_DBParse()';#Do not create stab entry on compile + $@ and die $@; + } + else { + $retval = $self->_Parse(); + } + $retval +} + +sub YYData { + my($self)=shift; + + exists($$self{USER}) + or $$self{USER}={}; + + $$self{USER}; + +} + +sub YYErrok { + my($self)=shift; + + ${$$self{ERRST}}=0; + undef; +} + +sub YYNberr { + my($self)=shift; + + ${$$self{NBERR}}; +} + +sub YYRecovering { + my($self)=shift; + + ${$$self{ERRST}} != 0; +} + +sub YYAbort { + my($self)=shift; + + ${$$self{CHECK}}='ABORT'; + undef; +} + +sub YYAccept { + my($self)=shift; + + ${$$self{CHECK}}='ACCEPT'; + undef; +} + +sub YYError { + my($self)=shift; + + ${$$self{CHECK}}='ERROR'; + undef; +} + +sub YYSemval { + my($self)=shift; + my($index)= $_[0] - ${$$self{DOTPOS}} - 1; + + $index < 0 + and -$index <= @{$$self{STACK}} + and return $$self{STACK}[$index][1]; + + undef; #Invalid index +} + +sub YYCurtok { + my($self)=shift; + + @_ + and ${$$self{TOKEN}}=$_[0]; + ${$$self{TOKEN}}; +} + +sub YYCurval { + my($self)=shift; + + @_ + and ${$$self{VALUE}}=$_[0]; + ${$$self{VALUE}}; +} + +sub YYExpect { + my($self)=shift; + + keys %{$self->{STATES}[$self->{STACK}[-1][0]]{ACTIONS}} +} + +sub YYLexer { + my($self)=shift; + + $$self{LEX}; +} + + +################# +# Private stuff # +################# + + +sub _CheckParams { + my($mandatory,$checklist,$inarray,$outhash)=@_; + my($prm,$value); + my($prmlst)={}; + + while(($prm,$value)=splice(@$inarray,0,2)) { + $prm=uc($prm); + exists($$checklist{$prm}) + or croak("Unknow parameter '$prm'"); + ref($value) eq $$checklist{$prm} + or croak("Invalid value for parameter '$prm'"); + $prm=unpack('@2A*',$prm); + $$outhash{$prm}=$value; + } + for (@$mandatory) { + exists($$outhash{$_}) + or croak("Missing mandatory parameter '".lc($_)."'"); + } +} + +sub _Error { + print "Parse error.\n"; +} + +sub _DBLoad { + { + no strict 'refs'; + + exists(${__PACKAGE__.'::'}{_DBParse})#Already loaded ? + and return; + } + my($fname)=__FILE__; + my(@drv); + open(DRV,"<$fname") or die "Report this as a BUG: Cannot open $fname"; + while() { + /^\s*sub\s+_Parse\s*{\s*$/ .. /^\s*}\s*#\s*_Parse\s*$/ + and do { + s/^#DBG>//; + push(@drv,$_); + } + } + close(DRV); + + $drv[0]=~s/_P/_DBP/; + eval join('',@drv); +} + +#Note that for loading debugging version of the driver, +#this file will be parsed from 'sub _Parse' up to '}#_Parse' inclusive. +#So, DO NOT remove comment at end of sub !!! +sub _Parse { + my($self)=shift; + + my($rules,$states,$lex,$error) + = @$self{ 'RULES', 'STATES', 'LEX', 'ERROR' }; + my($errstatus,$nberror,$token,$value,$stack,$check,$dotpos) + = @$self{ 'ERRST', 'NBERR', 'TOKEN', 'VALUE', 'STACK', 'CHECK', 'DOTPOS' }; + +#DBG> my($debug)=$$self{DEBUG}; +#DBG> my($dbgerror)=0; + +#DBG> my($ShowCurToken) = sub { +#DBG> my($tok)='>'; +#DBG> for (split('',$$token)) { +#DBG> $tok.= (ord($_) < 32 or ord($_) > 126) +#DBG> ? sprintf('<%02X>',ord($_)) +#DBG> : $_; +#DBG> } +#DBG> $tok.='<'; +#DBG> }; + + $$errstatus=0; + $$nberror=0; + ($$token,$$value)=(undef,undef); + @$stack=( [ 0, undef ] ); + $$check=''; + + while(1) { + my($actions,$act,$stateno); + + $stateno=$$stack[-1][0]; + $actions=$$states[$stateno]; + +#DBG> print STDERR ('-' x 40),"\n"; +#DBG> $debug & 0x2 +#DBG> and print STDERR "In state $stateno:\n"; +#DBG> $debug & 0x08 +#DBG> and print STDERR "Stack:[". +#DBG> join(',',map { $$_[0] } @$stack). +#DBG> "]\n"; + + + if (exists($$actions{ACTIONS})) { + + defined($$token) + or do { + ($$token,$$value)=&$lex($self); +#DBG> $debug & 0x01 +#DBG> and print STDERR "Need token. Got ".&$ShowCurToken."\n"; + }; + + $act= exists($$actions{ACTIONS}{$$token}) + ? $$actions{ACTIONS}{$$token} + : exists($$actions{DEFAULT}) + ? $$actions{DEFAULT} + : undef; + } + else { + $act=$$actions{DEFAULT}; +#DBG> $debug & 0x01 +#DBG> and print STDERR "Don't need token.\n"; + } + + defined($act) + and do { + + $act > 0 + and do { #shift + +#DBG> $debug & 0x04 +#DBG> and print STDERR "Shift and go to state $act.\n"; + + $$errstatus + and do { + --$$errstatus; + +#DBG> $debug & 0x10 +#DBG> and $dbgerror +#DBG> and $$errstatus == 0 +#DBG> and do { +#DBG> print STDERR "**End of Error recovery.\n"; +#DBG> $dbgerror=0; +#DBG> }; + }; + + + push(@$stack,[ $act, $$value ]); + + $$token ne '' #Don't eat the eof + and $$token=$$value=undef; + next; + }; + + #reduce + my($lhs,$len,$code,@sempar,$semval); + ($lhs,$len,$code)=@{$$rules[-$act]}; + +#DBG> $debug & 0x04 +#DBG> and $act +#DBG> and print STDERR "Reduce using rule ".-$act." ($lhs,$len): "; + + $act + or $self->YYAccept(); + + $$dotpos=$len; + + unpack('A1',$lhs) eq '@' #In line rule + and do { + $lhs =~ /^\@[0-9]+\-([0-9]+)$/ + or die "In line rule name '$lhs' ill formed: ". + "report it as a BUG.\n"; + $$dotpos = $1; + }; + + @sempar = $$dotpos + ? map { $$_[1] } @$stack[ -$$dotpos .. -1 ] + : (); + + $semval = $code ? &$code( $self, @sempar ) + : @sempar ? $sempar[0] : undef; + + splice(@$stack,-$len,$len); + + $$check eq 'ACCEPT' + and do { + +#DBG> $debug & 0x04 +#DBG> and print STDERR "Accept.\n"; + + return($semval); + }; + + $$check eq 'ABORT' + and do { + +#DBG> $debug & 0x04 +#DBG> and print STDERR "Abort.\n"; + + return(undef); + + }; + +#DBG> $debug & 0x04 +#DBG> and print STDERR "Back to state $$stack[-1][0], then "; + + $$check eq 'ERROR' + or do { +#DBG> $debug & 0x04 +#DBG> and print STDERR +#DBG> "go to state $$states[$$stack[-1][0]]{GOTOS}{$lhs}.\n"; + +#DBG> $debug & 0x10 +#DBG> and $dbgerror +#DBG> and $$errstatus == 0 +#DBG> and do { +#DBG> print STDERR "**End of Error recovery.\n"; +#DBG> $dbgerror=0; +#DBG> }; + + push(@$stack, + [ $$states[$$stack[-1][0]]{GOTOS}{$lhs}, $semval ]); + $$check=''; + next; + }; + +#DBG> $debug & 0x04 +#DBG> and print STDERR "Forced Error recovery.\n"; + + $$check=''; + + }; + + #Error + $$errstatus + or do { + + $$errstatus = 1; + &$error($self); + $$errstatus # if 0, then YYErrok has been called + or next; # so continue parsing + +#DBG> $debug & 0x10 +#DBG> and do { +#DBG> print STDERR "**Entering Error recovery.\n"; +#DBG> ++$dbgerror; +#DBG> }; + + ++$$nberror; + + }; + + $$errstatus == 3 #The next token is not valid: discard it + and do { + $$token eq '' # End of input: no hope + and do { +#DBG> $debug & 0x10 +#DBG> and print STDERR "**At eof: aborting.\n"; + return(undef); + }; + +#DBG> $debug & 0x10 +#DBG> and print STDERR "**Dicard invalid token ".&$ShowCurToken.".\n"; + + $$token=$$value=undef; + }; + + $$errstatus=3; + + while( @$stack + and ( not exists($$states[$$stack[-1][0]]{ACTIONS}) + or not exists($$states[$$stack[-1][0]]{ACTIONS}{error}) + or $$states[$$stack[-1][0]]{ACTIONS}{error} <= 0)) { + +#DBG> $debug & 0x10 +#DBG> and print STDERR "**Pop state $$stack[-1][0].\n"; + + pop(@$stack); + } + + @$stack + or do { + +#DBG> $debug & 0x10 +#DBG> and print STDERR "**No state left on stack: aborting.\n"; + + return(undef); + }; + + #shift the error token + +#DBG> $debug & 0x10 +#DBG> and print STDERR "**Shift \$error token and go to state ". +#DBG> $$states[$$stack[-1][0]]{ACTIONS}{error}. +#DBG> ".\n"; + + push(@$stack, [ $$states[$$stack[-1][0]]{ACTIONS}{error}, undef ]); + + } + + #never reached + croak("Error in driver logic. Please, report it as a BUG"); + +}#_Parse +#DO NOT remove comment + +1; + +} +#End of include-------------------------------------------------- + + + + +sub new { + my($class)=shift; + ref($class) + and $class=ref($class); + + my($self)=$class->SUPER::new( yyversion => '1.05', + yystates => +[ + {#State 0 + ACTIONS => { + "[" => 2 + }, + GOTOS => { + 'idl_interface' => 1, + 'idl' => 3, + 'module_header' => 4 + } + }, + {#State 1 + DEFAULT => -1 + }, + {#State 2 + ACTIONS => { + 'IDENTIFIER' => 5 + }, + DEFAULT => -5, + GOTOS => { + 'module_params' => 7, + 'identifier' => 6, + 'module_param' => 8 + } + }, + {#State 3 + ACTIONS => { + '' => 9, + "[" => 2 + }, + GOTOS => { + 'idl_interface' => 10, + 'module_header' => 4 + } + }, + {#State 4 + ACTIONS => { + "interface" => 12 + }, + GOTOS => { + 'interface' => 11 + } + }, + {#State 5 + DEFAULT => -69 + }, + {#State 6 + ACTIONS => { + "(" => 13 + } + }, + {#State 7 + ACTIONS => { + "," => 14, + "]" => 15 + } + }, + {#State 8 + DEFAULT => -6 + }, + {#State 9 + DEFAULT => 0 + }, + {#State 10 + DEFAULT => -2 + }, + {#State 11 + DEFAULT => -3 + }, + {#State 12 + ACTIONS => { + 'IDENTIFIER' => 5 + }, + GOTOS => { + 'identifier' => 16 + } + }, + {#State 13 + ACTIONS => { + 'IDENTIFIER' => 5, + 'CONSTANT' => 23, + 'TEXT' => 17 + }, + DEFAULT => -56, + GOTOS => { + 'identifier' => 18, + 'listtext' => 21, + 'anytext' => 20, + 'text' => 19, + 'constant' => 22 + } + }, + {#State 14 + ACTIONS => { + 'IDENTIFIER' => 5 + }, + GOTOS => { + 'identifier' => 6, + 'module_param' => 24 + } + }, + {#State 15 + DEFAULT => -4 + }, + {#State 16 + ACTIONS => { + "{" => 25 + } + }, + {#State 17 + DEFAULT => -71 + }, + {#State 18 + DEFAULT => -57 + }, + {#State 19 + DEFAULT => -59 + }, + {#State 20 + ACTIONS => { + "-" => 26, + "+" => 27, + "&" => 28, + "/" => 29, + "|" => 30, + "(" => 31, + "*" => 32, + "." => 33, + ">" => 34 + }, + DEFAULT => -54 + }, + {#State 21 + ACTIONS => { + "," => 35, + ")" => 36 + } + }, + {#State 22 + DEFAULT => -58 + }, + {#State 23 + DEFAULT => -70 + }, + {#State 24 + DEFAULT => -7 + }, + {#State 25 + ACTIONS => { + "typedef" => 37, + "const" => 43 + }, + DEFAULT => -48, + GOTOS => { + 'const' => 42, + 'function' => 38, + 'typedef' => 44, + 'definitions' => 39, + 'definition' => 41, + 'property_list' => 40 + } + }, + {#State 26 + ACTIONS => { + 'CONSTANT' => 23, + 'TEXT' => 17, + 'IDENTIFIER' => 5 + }, + DEFAULT => -56, + GOTOS => { + 'identifier' => 18, + 'text' => 19, + 'anytext' => 45, + 'constant' => 22 + } + }, + {#State 27 + ACTIONS => { + 'CONSTANT' => 23, + 'TEXT' => 17, + 'IDENTIFIER' => 5 + }, + DEFAULT => -56, + GOTOS => { + 'identifier' => 18, + 'text' => 19, + 'anytext' => 46, + 'constant' => 22 + } + }, + {#State 28 + ACTIONS => { + 'CONSTANT' => 23, + 'TEXT' => 17, + 'IDENTIFIER' => 5 + }, + DEFAULT => -56, + GOTOS => { + 'identifier' => 18, + 'text' => 19, + 'anytext' => 47, + 'constant' => 22 + } + }, + {#State 29 + ACTIONS => { + 'CONSTANT' => 23, + 'TEXT' => 17, + 'IDENTIFIER' => 5 + }, + DEFAULT => -56, + GOTOS => { + 'identifier' => 18, + 'text' => 19, + 'anytext' => 48, + 'constant' => 22 + } + }, + {#State 30 + ACTIONS => { + 'CONSTANT' => 23, + 'TEXT' => 17, + 'IDENTIFIER' => 5 + }, + DEFAULT => -56, + GOTOS => { + 'identifier' => 18, + 'text' => 19, + 'anytext' => 49, + 'constant' => 22 + } + }, + {#State 31 + ACTIONS => { + 'IDENTIFIER' => 5, + 'CONSTANT' => 23, + 'TEXT' => 17 + }, + DEFAULT => -56, + GOTOS => { + 'identifier' => 18, + 'text' => 19, + 'anytext' => 50, + 'constant' => 22 + } + }, + {#State 32 + ACTIONS => { + 'CONSTANT' => 23, + 'TEXT' => 17, + 'IDENTIFIER' => 5 + }, + DEFAULT => -56, + GOTOS => { + 'identifier' => 18, + 'text' => 19, + 'anytext' => 51, + 'constant' => 22 + } + }, + {#State 33 + ACTIONS => { + 'CONSTANT' => 23, + 'TEXT' => 17, + 'IDENTIFIER' => 5 + }, + DEFAULT => -56, + GOTOS => { + 'identifier' => 18, + 'text' => 19, + 'anytext' => 52, + 'constant' => 22 + } + }, + {#State 34 + ACTIONS => { + 'CONSTANT' => 23, + 'TEXT' => 17, + 'IDENTIFIER' => 5 + }, + DEFAULT => -56, + GOTOS => { + 'identifier' => 18, + 'text' => 19, + 'anytext' => 53, + 'constant' => 22 + } + }, + {#State 35 + ACTIONS => { + 'IDENTIFIER' => 5, + 'CONSTANT' => 23, + 'TEXT' => 17 + }, + DEFAULT => -56, + GOTOS => { + 'identifier' => 18, + 'text' => 19, + 'anytext' => 54, + 'constant' => 22 + } + }, + {#State 36 + DEFAULT => -8 + }, + {#State 37 + ACTIONS => { + 'IDENTIFIER' => 5, + "enum" => 55, + 'void' => 56 + }, + DEFAULT => -48, + GOTOS => { + 'identifier' => 58, + 'struct' => 59, + 'enum' => 60, + 'type' => 61, + 'union' => 62, + 'property_list' => 57 + } + }, + {#State 38 + DEFAULT => -12 + }, + {#State 39 + ACTIONS => { + "}" => 63, + "typedef" => 37, + "const" => 43 + }, + DEFAULT => -48, + GOTOS => { + 'const' => 42, + 'function' => 38, + 'typedef' => 44, + 'definition' => 64, + 'property_list' => 40 + } + }, + {#State 40 + ACTIONS => { + 'IDENTIFIER' => 5, + "enum" => 55, + "[" => 65, + 'void' => 56 + }, + DEFAULT => -48, + GOTOS => { + 'identifier' => 58, + 'struct' => 59, + 'enum' => 60, + 'type' => 66, + 'union' => 62, + 'property_list' => 57 + } + }, + {#State 41 + DEFAULT => -10 + }, + {#State 42 + DEFAULT => -13 + }, + {#State 43 + ACTIONS => { + 'IDENTIFIER' => 5 + }, + GOTOS => { + 'identifier' => 67 + } + }, + {#State 44 + DEFAULT => -14 + }, + {#State 45 + DEFAULT => -60 + }, + {#State 46 + DEFAULT => -67 + }, + {#State 47 + DEFAULT => -65 + }, + {#State 48 + DEFAULT => -66 + }, + {#State 49 + DEFAULT => -64 + }, + {#State 50 + ACTIONS => { + "-" => 26, + "+" => 27, + "&" => 28, + "/" => 29, + "(" => 31, + "|" => 30, + "*" => 32, + "." => 33, + ")" => 68, + ">" => 34 + } + }, + {#State 51 + DEFAULT => -62 + }, + {#State 52 + DEFAULT => -61 + }, + {#State 53 + DEFAULT => -63 + }, + {#State 54 + ACTIONS => { + "-" => 26, + "+" => 27, + "&" => 28, + "/" => 29, + "(" => 31, + "|" => 30, + "*" => 32, + "." => 33, + ">" => 34 + }, + DEFAULT => -55 + }, + {#State 55 + ACTIONS => { + "{" => 69 + } + }, + {#State 56 + DEFAULT => -22 + }, + {#State 57 + ACTIONS => { + "union" => 70, + "[" => 65, + "struct" => 71 + } + }, + {#State 58 + DEFAULT => -21 + }, + {#State 59 + DEFAULT => -18 + }, + {#State 60 + DEFAULT => -20 + }, + {#State 61 + ACTIONS => { + 'IDENTIFIER' => 5 + }, + GOTOS => { + 'identifier' => 72 + } + }, + {#State 62 + DEFAULT => -19 + }, + {#State 63 + DEFAULT => -9 + }, + {#State 64 + DEFAULT => -11 + }, + {#State 65 + ACTIONS => { + 'IDENTIFIER' => 5 + }, + GOTOS => { + 'identifier' => 74, + 'property' => 75, + 'properties' => 73 + } + }, + {#State 66 + ACTIONS => { + 'IDENTIFIER' => 5 + }, + GOTOS => { + 'identifier' => 76 + } + }, + {#State 67 + ACTIONS => { + 'IDENTIFIER' => 5 + }, + GOTOS => { + 'identifier' => 77 + } + }, + {#State 68 + ACTIONS => { + 'CONSTANT' => 23, + 'TEXT' => 17, + 'IDENTIFIER' => 5 + }, + DEFAULT => -56, + GOTOS => { + 'identifier' => 18, + 'text' => 19, + 'anytext' => 78, + 'constant' => 22 + } + }, + {#State 69 + ACTIONS => { + 'IDENTIFIER' => 5 + }, + GOTOS => { + 'identifier' => 79, + 'enum_element' => 80, + 'enum_elements' => 81 + } + }, + {#State 70 + ACTIONS => { + "{" => 82 + } + }, + {#State 71 + ACTIONS => { + "{" => 83 + } + }, + {#State 72 + ACTIONS => { + "[" => 85 + }, + DEFAULT => -45, + GOTOS => { + 'array_len' => 84 + } + }, + {#State 73 + ACTIONS => { + "," => 86, + "]" => 87 + } + }, + {#State 74 + ACTIONS => { + "(" => 88 + }, + DEFAULT => -52 + }, + {#State 75 + DEFAULT => -50 + }, + {#State 76 + ACTIONS => { + "(" => 89 + } + }, + {#State 77 + ACTIONS => { + "=" => 90 + } + }, + {#State 78 + DEFAULT => -68 + }, + {#State 79 + ACTIONS => { + "=" => 91 + }, + DEFAULT => -26 + }, + {#State 80 + DEFAULT => -24 + }, + {#State 81 + ACTIONS => { + "}" => 92, + "," => 93 + } + }, + {#State 82 + ACTIONS => { + "[" => 96 + }, + GOTOS => { + 'union_elements' => 94, + 'union_element' => 95 + } + }, + {#State 83 + DEFAULT => -39, + GOTOS => { + 'element_list1' => 97 + } + }, + {#State 84 + ACTIONS => { + ";" => 98 + } + }, + {#State 85 + ACTIONS => { + 'IDENTIFIER' => 5, + 'CONSTANT' => 23, + 'TEXT' => 17, + "]" => 100 + }, + DEFAULT => -56, + GOTOS => { + 'identifier' => 18, + 'text' => 19, + 'anytext' => 99, + 'constant' => 22 + } + }, + {#State 86 + ACTIONS => { + 'IDENTIFIER' => 5 + }, + GOTOS => { + 'identifier' => 74, + 'property' => 101 + } + }, + {#State 87 + DEFAULT => -49 + }, + {#State 88 + ACTIONS => { + 'IDENTIFIER' => 5, + 'CONSTANT' => 23, + 'TEXT' => 17 + }, + DEFAULT => -56, + GOTOS => { + 'identifier' => 18, + 'text' => 19, + 'anytext' => 102, + 'constant' => 22 + } + }, + {#State 89 + ACTIONS => { + "void" => 105, + "," => -41, + ")" => -41 + }, + DEFAULT => -48, + GOTOS => { + 'base_element' => 103, + 'element_list2' => 106, + 'property_list' => 104 + } + }, + {#State 90 + ACTIONS => { + 'IDENTIFIER' => 5, + 'CONSTANT' => 23, + 'TEXT' => 17 + }, + DEFAULT => -56, + GOTOS => { + 'identifier' => 18, + 'text' => 19, + 'anytext' => 107, + 'constant' => 22 + } + }, + {#State 91 + ACTIONS => { + 'IDENTIFIER' => 5, + 'CONSTANT' => 23, + 'TEXT' => 17 + }, + DEFAULT => -56, + GOTOS => { + 'identifier' => 18, + 'text' => 19, + 'anytext' => 108, + 'constant' => 22 + } + }, + {#State 92 + DEFAULT => -23 + }, + {#State 93 + ACTIONS => { + 'IDENTIFIER' => 5 + }, + GOTOS => { + 'identifier' => 79, + 'enum_element' => 109 + } + }, + {#State 94 + ACTIONS => { + "}" => 110, + "[" => 96 + }, + GOTOS => { + 'union_element' => 111 + } + }, + {#State 95 + DEFAULT => -30 + }, + {#State 96 + ACTIONS => { + "case" => 112, + "default" => 113 + } + }, + {#State 97 + ACTIONS => { + "}" => 114 + }, + DEFAULT => -48, + GOTOS => { + 'base_element' => 115, + 'property_list' => 104 + } + }, + {#State 98 + DEFAULT => -17 + }, + {#State 99 + ACTIONS => { + "-" => 26, + "+" => 27, + "&" => 28, + "/" => 29, + "(" => 31, + "|" => 30, + "*" => 32, + "." => 33, + "]" => 116, + ">" => 34 + } + }, + {#State 100 + DEFAULT => -46 + }, + {#State 101 + DEFAULT => -51 + }, + {#State 102 + ACTIONS => { + "-" => 26, + "+" => 27, + "&" => 28, + "/" => 29, + "(" => 31, + "|" => 30, + "*" => 32, + "." => 33, + ")" => 117, + ">" => 34 + } + }, + {#State 103 + DEFAULT => -43 + }, + {#State 104 + ACTIONS => { + 'IDENTIFIER' => 5, + "enum" => 55, + "[" => 65, + 'void' => 56 + }, + DEFAULT => -48, + GOTOS => { + 'identifier' => 58, + 'struct' => 59, + 'enum' => 60, + 'type' => 118, + 'union' => 62, + 'property_list' => 57 + } + }, + {#State 105 + DEFAULT => -42 + }, + {#State 106 + ACTIONS => { + "," => 119, + ")" => 120 + } + }, + {#State 107 + ACTIONS => { + "-" => 26, + "|" => 30, + "(" => 31, + "*" => 32, + ";" => 121, + "+" => 27, + "&" => 28, + "/" => 29, + "." => 33, + ">" => 34 + } + }, + {#State 108 + ACTIONS => { + "-" => 26, + "+" => 27, + "&" => 28, + "/" => 29, + "(" => 31, + "|" => 30, + "*" => 32, + "." => 33, + ">" => 34 + }, + DEFAULT => -27 + }, + {#State 109 + DEFAULT => -25 + }, + {#State 110 + DEFAULT => -29 + }, + {#State 111 + DEFAULT => -31 + }, + {#State 112 + ACTIONS => { + "(" => 122 + } + }, + {#State 113 + ACTIONS => { + "]" => 123 + } + }, + {#State 114 + DEFAULT => -28 + }, + {#State 115 + ACTIONS => { + ";" => 124 + } + }, + {#State 116 + DEFAULT => -47 + }, + {#State 117 + DEFAULT => -53 + }, + {#State 118 + DEFAULT => -37, + GOTOS => { + 'pointers' => 125 + } + }, + {#State 119 + DEFAULT => -48, + GOTOS => { + 'base_element' => 126, + 'property_list' => 104 + } + }, + {#State 120 + ACTIONS => { + ";" => 127 + } + }, + {#State 121 + DEFAULT => -15 + }, + {#State 122 + ACTIONS => { + 'IDENTIFIER' => 5, + 'CONSTANT' => 23, + 'TEXT' => 17 + }, + DEFAULT => -56, + GOTOS => { + 'identifier' => 18, + 'text' => 19, + 'anytext' => 128, + 'constant' => 22 + } + }, + {#State 123 + ACTIONS => { + ";" => 129 + }, + DEFAULT => -48, + GOTOS => { + 'base_element' => 130, + 'property_list' => 104 + } + }, + {#State 124 + DEFAULT => -40 + }, + {#State 125 + ACTIONS => { + 'IDENTIFIER' => 5, + "*" => 132 + }, + GOTOS => { + 'identifier' => 131 + } + }, + {#State 126 + DEFAULT => -44 + }, + {#State 127 + DEFAULT => -16 + }, + {#State 128 + ACTIONS => { + "-" => 26, + "+" => 27, + "&" => 28, + "/" => 29, + "(" => 31, + "|" => 30, + "*" => 32, + "." => 33, + ")" => 133, + ">" => 34 + } + }, + {#State 129 + DEFAULT => -35 + }, + {#State 130 + ACTIONS => { + ";" => 134 + } + }, + {#State 131 + ACTIONS => { + "[" => 85 + }, + DEFAULT => -45, + GOTOS => { + 'array_len' => 135 + } + }, + {#State 132 + DEFAULT => -38 + }, + {#State 133 + ACTIONS => { + "]" => 136 + } + }, + {#State 134 + DEFAULT => -34 + }, + {#State 135 + DEFAULT => -36 + }, + {#State 136 + ACTIONS => { + ";" => 137 + }, + DEFAULT => -48, + GOTOS => { + 'base_element' => 138, + 'property_list' => 104 + } + }, + {#State 137 + DEFAULT => -33 + }, + {#State 138 + ACTIONS => { + ";" => 139 + } + }, + {#State 139 + DEFAULT => -32 + } +], + yyrules => +[ + [#Rule 0 + '$start', 2, undef + ], + [#Rule 1 + 'idl', 1, undef + ], + [#Rule 2 + 'idl', 2, +sub +#line 18 "build/pidl/idl.yp" +{ util::FlattenArray([$_[1],$_[2]]) } + ], + [#Rule 3 + 'idl_interface', 2, +sub +#line 21 "build/pidl/idl.yp" +{ [ $_[1], $_[2] ] } + ], + [#Rule 4 + 'module_header', 3, +sub +#line 25 "build/pidl/idl.yp" +{{ + "TYPE" => "MODULEHEADER", + "PROPERTIES" => util::FlattenHash($_[2]) + }} + ], + [#Rule 5 + 'module_params', 0, undef + ], + [#Rule 6 + 'module_params', 1, +sub +#line 33 "build/pidl/idl.yp" +{ [ $_[1] ] } + ], + [#Rule 7 + 'module_params', 3, +sub +#line 34 "build/pidl/idl.yp" +{ push(@{$_[1]}, $_[3]); $_[1] } + ], + [#Rule 8 + 'module_param', 4, +sub +#line 38 "build/pidl/idl.yp" +{ { "$_[1]" => "$_[3]" } } + ], + [#Rule 9 + 'interface', 5, +sub +#line 42 "build/pidl/idl.yp" +{{ + "TYPE" => "INTERFACE", + "NAME" => $_[2], + "DATA" => $_[4] + }} + ], + [#Rule 10 + 'definitions', 1, +sub +#line 50 "build/pidl/idl.yp" +{ [ $_[1] ] } + ], + [#Rule 11 + 'definitions', 2, +sub +#line 51 "build/pidl/idl.yp" +{ push(@{$_[1]}, $_[2]); $_[1] } + ], + [#Rule 12 + 'definition', 1, undef + ], + [#Rule 13 + 'definition', 1, undef + ], + [#Rule 14 + 'definition', 1, undef + ], + [#Rule 15 + 'const', 6, +sub +#line 59 "build/pidl/idl.yp" +{{ + "TYPE" => "CONST", + "DTYPE" => $_[2], + "NAME" => $_[3], + "VALUE" => $_[5] + }} + ], + [#Rule 16 + 'function', 7, +sub +#line 69 "build/pidl/idl.yp" +{{ + "TYPE" => "FUNCTION", + "NAME" => $_[3], + "RETURN_TYPE" => $_[2], + "PROPERTIES" => $_[1], + "DATA" => $_[5] + }} + ], + [#Rule 17 + 'typedef', 5, +sub +#line 79 "build/pidl/idl.yp" +{{ + "TYPE" => "TYPEDEF", + "NAME" => $_[3], + "DATA" => $_[2], + "ARRAY_LEN" => $_[4] + }} + ], + [#Rule 18 + 'type', 1, undef + ], + [#Rule 19 + 'type', 1, undef + ], + [#Rule 20 + 'type', 1, undef + ], + [#Rule 21 + 'type', 1, undef + ], + [#Rule 22 + 'type', 1, +sub +#line 88 "build/pidl/idl.yp" +{ "void" } + ], + [#Rule 23 + 'enum', 4, +sub +#line 93 "build/pidl/idl.yp" +{{ + "TYPE" => "ENUM", + "ELEMENTS" => $_[3] + }} + ], + [#Rule 24 + 'enum_elements', 1, +sub +#line 100 "build/pidl/idl.yp" +{ [ $_[1] ] } + ], + [#Rule 25 + 'enum_elements', 3, +sub +#line 101 "build/pidl/idl.yp" +{ push(@{$_[1]}, $_[3]); $_[1] } + ], + [#Rule 26 + 'enum_element', 1, undef + ], + [#Rule 27 + 'enum_element', 3, +sub +#line 105 "build/pidl/idl.yp" +{ "$_[1]$_[2]$_[3]" } + ], + [#Rule 28 + 'struct', 5, +sub +#line 109 "build/pidl/idl.yp" +{{ + "TYPE" => "STRUCT", + "PROPERTIES" => $_[1], + "ELEMENTS" => $_[4] + }} + ], + [#Rule 29 + 'union', 5, +sub +#line 117 "build/pidl/idl.yp" +{{ + "TYPE" => "UNION", + "PROPERTIES" => $_[1], + "DATA" => $_[4] + }} + ], + [#Rule 30 + 'union_elements', 1, +sub +#line 125 "build/pidl/idl.yp" +{ [ $_[1] ] } + ], + [#Rule 31 + 'union_elements', 2, +sub +#line 126 "build/pidl/idl.yp" +{ push(@{$_[1]}, $_[2]); $_[1] } + ], + [#Rule 32 + 'union_element', 8, +sub +#line 131 "build/pidl/idl.yp" +{{ + "TYPE" => "UNION_ELEMENT", + "CASE" => $_[4], + "DATA" => $_[7] + }} + ], + [#Rule 33 + 'union_element', 7, +sub +#line 137 "build/pidl/idl.yp" +{{ + "TYPE" => "EMPTY", + "CASE" => $_[4], + }} + ], + [#Rule 34 + 'union_element', 5, +sub +#line 142 "build/pidl/idl.yp" +{{ + "TYPE" => "UNION_ELEMENT", + "CASE" => "default", + "DATA" => $_[4] + }} + ], + [#Rule 35 + 'union_element', 4, +sub +#line 148 "build/pidl/idl.yp" +{{ + "TYPE" => "EMPTY", + "CASE" => "default", + }} + ], + [#Rule 36 + 'base_element', 5, +sub +#line 155 "build/pidl/idl.yp" +{{ + "NAME" => $_[4], + "TYPE" => $_[2], + "PROPERTIES" => $_[1], + "POINTERS" => $_[3], + "ARRAY_LEN" => $_[5] + }} + ], + [#Rule 37 + 'pointers', 0, +sub +#line 167 "build/pidl/idl.yp" +{ 0 } + ], + [#Rule 38 + 'pointers', 2, +sub +#line 168 "build/pidl/idl.yp" +{ $_[1]+1 } + ], + [#Rule 39 + 'element_list1', 0, undef + ], + [#Rule 40 + 'element_list1', 3, +sub +#line 175 "build/pidl/idl.yp" +{ push(@{$_[1]}, $_[2]); $_[1] } + ], + [#Rule 41 + 'element_list2', 0, undef + ], + [#Rule 42 + 'element_list2', 1, undef + ], + [#Rule 43 + 'element_list2', 1, +sub +#line 181 "build/pidl/idl.yp" +{ [ $_[1] ] } + ], + [#Rule 44 + 'element_list2', 3, +sub +#line 182 "build/pidl/idl.yp" +{ push(@{$_[1]}, $_[3]); $_[1] } + ], + [#Rule 45 + 'array_len', 0, undef + ], + [#Rule 46 + 'array_len', 2, +sub +#line 187 "build/pidl/idl.yp" +{ "*" } + ], + [#Rule 47 + 'array_len', 3, +sub +#line 188 "build/pidl/idl.yp" +{ "$_[2]" } + ], + [#Rule 48 + 'property_list', 0, undef + ], + [#Rule 49 + 'property_list', 4, +sub +#line 194 "build/pidl/idl.yp" +{ util::FlattenHash([$_[1],$_[3]]); } + ], + [#Rule 50 + 'properties', 1, +sub +#line 197 "build/pidl/idl.yp" +{ $_[1] } + ], + [#Rule 51 + 'properties', 3, +sub +#line 198 "build/pidl/idl.yp" +{ util::FlattenHash([$_[1], $_[3]]); } + ], + [#Rule 52 + 'property', 1, +sub +#line 201 "build/pidl/idl.yp" +{{ "$_[1]" => "1" }} + ], + [#Rule 53 + 'property', 4, +sub +#line 202 "build/pidl/idl.yp" +{{ "$_[1]" => "$_[3]" }} + ], + [#Rule 54 + 'listtext', 1, undef + ], + [#Rule 55 + 'listtext', 3, +sub +#line 207 "build/pidl/idl.yp" +{ "$_[1] $_[3]" } + ], + [#Rule 56 + 'anytext', 0, +sub +#line 211 "build/pidl/idl.yp" +{ "" } + ], + [#Rule 57 + 'anytext', 1, undef + ], + [#Rule 58 + 'anytext', 1, undef + ], + [#Rule 59 + 'anytext', 1, undef + ], + [#Rule 60 + 'anytext', 3, +sub +#line 213 "build/pidl/idl.yp" +{ "$_[1]$_[2]$_[3]" } + ], + [#Rule 61 + 'anytext', 3, +sub +#line 214 "build/pidl/idl.yp" +{ "$_[1]$_[2]$_[3]" } + ], + [#Rule 62 + 'anytext', 3, +sub +#line 215 "build/pidl/idl.yp" +{ "$_[1]$_[2]$_[3]" } + ], + [#Rule 63 + 'anytext', 3, +sub +#line 216 "build/pidl/idl.yp" +{ "$_[1]$_[2]$_[3]" } + ], + [#Rule 64 + 'anytext', 3, +sub +#line 217 "build/pidl/idl.yp" +{ "$_[1]$_[2]$_[3]" } + ], + [#Rule 65 + 'anytext', 3, +sub +#line 218 "build/pidl/idl.yp" +{ "$_[1]$_[2]$_[3]" } + ], + [#Rule 66 + 'anytext', 3, +sub +#line 219 "build/pidl/idl.yp" +{ "$_[1]$_[2]$_[3]" } + ], + [#Rule 67 + 'anytext', 3, +sub +#line 220 "build/pidl/idl.yp" +{ "$_[1]$_[2]$_[3]" } + ], + [#Rule 68 + 'anytext', 5, +sub +#line 221 "build/pidl/idl.yp" +{ "$_[1]$_[2]$_[3]$_[4]$_[5]" } + ], + [#Rule 69 + 'identifier', 1, undef + ], + [#Rule 70 + 'constant', 1, undef + ], + [#Rule 71 + 'text', 1, +sub +#line 230 "build/pidl/idl.yp" +{ "\"$_[1]\"" } + ] +], + @_); + bless($self,$class); +} + +#line 236 "build/pidl/idl.yp" + + +use util; + +sub _Error { + if (exists $_[0]->YYData->{ERRMSG}) { + print $_[0]->YYData->{ERRMSG}; + delete $_[0]->YYData->{ERRMSG}; + return; + }; + my $line = $_[0]->YYData->{LINE}; + my $last_token = $_[0]->YYData->{LAST_TOKEN}; + my $file = $_[0]->YYData->{INPUT_FILENAME}; + + print "$file:$line: Syntax error near '$last_token'\n"; +} + +sub _Lexer($) +{ + my($parser)=shift; + + $parser->YYData->{INPUT} + or return('',undef); + +again: + $parser->YYData->{INPUT} =~ s/^[ \t]*//; + + for ($parser->YYData->{INPUT}) { + if (/^\#/) { + if (s/^\# (\d+) \"(.*?)\"( \d+|)//) { + $parser->YYData->{LINE} = $1-1; + $parser->YYData->{INPUT_FILENAME} = $2; + goto again; + } + if (s/^\#line (\d+) \"(.*?)\"( \d+|)//) { + $parser->YYData->{LINE} = $1-1; + $parser->YYData->{INPUT_FILENAME} = $2; + goto again; + } + if (s/^(\#.*)$//m) { + goto again; + } + } + if (s/^(\n)//) { + $parser->YYData->{LINE}++; + goto again; + } + if (s/^\"(.*?)\"//) { + $parser->YYData->{LAST_TOKEN} = $1; + return('TEXT',$1); + } + if (s/^(\d+)(\W|$)/$2/) { + $parser->YYData->{LAST_TOKEN} = $1; + return('CONSTANT',$1); + } + if (s/^([\w_]+)//) { + $parser->YYData->{LAST_TOKEN} = $1; + if ($1 =~ + /^(interface|const|typedef|union + |struct|enum|void|case|default)$/x) { + return $1; + } + return('IDENTIFIER',$1); + } + if (s/^(.)//s) { + $parser->YYData->{LAST_TOKEN} = $1; + return($1,$1); + } + } +} + +sub parse_idl($$) +{ + my $self = shift; + my $filename = shift; + + my $saved_delim = $/; + undef $/; + my $cpp = $ENV{CPP}; + if (! defined $cpp) { + $cpp = "cpp" + } + my $data = `$cpp -xc $filename`; + $/ = $saved_delim; + + $self->YYData->{INPUT} = $data; + $self->YYData->{LINE} = 0; + $self->YYData->{LAST_TOKEN} = "NONE"; + return $self->YYParse( yylex => \&_Lexer, yyerror => \&_Error ); +} + +1; diff --git a/SAMBA_3_2_MERGE/source/build/pidl/idl.yp b/SAMBA_3_2_MERGE/source/build/pidl/idl.yp new file mode 100644 index 00000000000..cb293de2725 --- /dev/null +++ b/SAMBA_3_2_MERGE/source/build/pidl/idl.yp @@ -0,0 +1,325 @@ +######################## +# IDL Parse::Yapp parser +# Copyright (C) Andrew Tridgell +# released under the GNU GPL version 2 or later + + + +# the precedence actually doesn't matter at all for this grammer, but +# by providing a precedence we reduce the number of conflicts +# enormously +%left '-' '+' '&' '|' '*' '>' '.' '/' '(' ')' '[' ',' ';' + + +################ +# grammer +%% +idl: idl_interface + | idl idl_interface { util::FlattenArray([$_[1],$_[2]]) } +; + +idl_interface: module_header interface { [ $_[1], $_[2] ] } +; + +module_header: '[' module_params ']' + {{ + "TYPE" => "MODULEHEADER", + "PROPERTIES" => util::FlattenHash($_[2]) + }} +; + +module_params: + #empty + | module_param { [ $_[1] ] } + | module_params ',' module_param { push(@{$_[1]}, $_[3]); $_[1] } +; + +module_param: identifier '(' listtext ')' +{ { "$_[1]" => "$_[3]" } } +; + +interface: 'interface' identifier '{' definitions '}' + {{ + "TYPE" => "INTERFACE", + "NAME" => $_[2], + "DATA" => $_[4] + }} +; + +definitions: + definition { [ $_[1] ] } + | definitions definition { push(@{$_[1]}, $_[2]); $_[1] } +; + + +definition: function | const | typedef +; + +const: 'const' identifier identifier '=' anytext ';' + {{ + "TYPE" => "CONST", + "DTYPE" => $_[2], + "NAME" => $_[3], + "VALUE" => $_[5] + }} +; + + +function: property_list type identifier '(' element_list2 ')' ';' + {{ + "TYPE" => "FUNCTION", + "NAME" => $_[3], + "RETURN_TYPE" => $_[2], + "PROPERTIES" => $_[1], + "DATA" => $_[5] + }} +; + +typedef: 'typedef' type identifier array_len ';' + {{ + "TYPE" => "TYPEDEF", + "NAME" => $_[3], + "DATA" => $_[2], + "ARRAY_LEN" => $_[4] + }} +; + +type: struct | union | enum | identifier + | void { "void" } +; + + +enum: 'enum' '{' enum_elements '}' + {{ + "TYPE" => "ENUM", + "ELEMENTS" => $_[3] + }} +; + +enum_elements: + enum_element { [ $_[1] ] } + | enum_elements ',' enum_element { push(@{$_[1]}, $_[3]); $_[1] } +; + +enum_element: identifier + | identifier '=' anytext { "$_[1]$_[2]$_[3]" } +; + +struct: property_list 'struct' '{' element_list1 '}' + {{ + "TYPE" => "STRUCT", + "PROPERTIES" => $_[1], + "ELEMENTS" => $_[4] + }} +; + +union: property_list 'union' '{' union_elements '}' + {{ + "TYPE" => "UNION", + "PROPERTIES" => $_[1], + "DATA" => $_[4] + }} +; + +union_elements: + union_element { [ $_[1] ] } + | union_elements union_element { push(@{$_[1]}, $_[2]); $_[1] } +; + +union_element: + '[' 'case' '(' anytext ')' ']' base_element ';' + {{ + "TYPE" => "UNION_ELEMENT", + "CASE" => $_[4], + "DATA" => $_[7] + }} + | '[' 'case' '(' anytext ')' ']' ';' + {{ + "TYPE" => "EMPTY", + "CASE" => $_[4], + }} + | '[' 'default' ']' base_element ';' + {{ + "TYPE" => "UNION_ELEMENT", + "CASE" => "default", + "DATA" => $_[4] + }} + | '[' 'default' ']' ';' + {{ + "TYPE" => "EMPTY", + "CASE" => "default", + }} +; + +base_element: property_list type pointers identifier array_len + {{ + "NAME" => $_[4], + "TYPE" => $_[2], + "PROPERTIES" => $_[1], + "POINTERS" => $_[3], + "ARRAY_LEN" => $_[5] + }} +; + + +pointers: + #empty + { 0 } + | pointers '*' { $_[1]+1 } +; + + + +element_list1: + #empty + | element_list1 base_element ';' { push(@{$_[1]}, $_[2]); $_[1] } +; + +element_list2: + #empty + | 'void' + | base_element { [ $_[1] ] } + | element_list2 ',' base_element { push(@{$_[1]}, $_[3]); $_[1] } +; + +array_len: + #empty + | '[' ']' { "*" } + | '[' anytext ']' { "$_[2]" } +; + + +property_list: + #empty + | property_list '[' properties ']' { util::FlattenHash([$_[1],$_[3]]); } +; + +properties: property { $_[1] } + | properties ',' property { util::FlattenHash([$_[1], $_[3]]); } +; + +property: identifier {{ "$_[1]" => "1" }} + | identifier '(' anytext ')' {{ "$_[1]" => "$_[3]" }} +; + +listtext: + anytext + | listtext ',' anytext { "$_[1] $_[3]" } +; + +anytext: #empty + { "" } + | identifier | constant | text + | anytext '-' anytext { "$_[1]$_[2]$_[3]" } + | anytext '.' anytext { "$_[1]$_[2]$_[3]" } + | anytext '*' anytext { "$_[1]$_[2]$_[3]" } + | anytext '>' anytext { "$_[1]$_[2]$_[3]" } + | anytext '|' anytext { "$_[1]$_[2]$_[3]" } + | anytext '&' anytext { "$_[1]$_[2]$_[3]" } + | anytext '/' anytext { "$_[1]$_[2]$_[3]" } + | anytext '+' anytext { "$_[1]$_[2]$_[3]" } + | anytext '(' anytext ')' anytext { "$_[1]$_[2]$_[3]$_[4]$_[5]" } +; + +identifier: IDENTIFIER +; + +constant: CONSTANT +; + +text: TEXT { "\"$_[1]\"" } +; + + +##################################### +# start code +%% + +use util; + +sub _Error { + if (exists $_[0]->YYData->{ERRMSG}) { + print $_[0]->YYData->{ERRMSG}; + delete $_[0]->YYData->{ERRMSG}; + return; + }; + my $line = $_[0]->YYData->{LINE}; + my $last_token = $_[0]->YYData->{LAST_TOKEN}; + my $file = $_[0]->YYData->{INPUT_FILENAME}; + + print "$file:$line: Syntax error near '$last_token'\n"; +} + +sub _Lexer($) +{ + my($parser)=shift; + + $parser->YYData->{INPUT} + or return('',undef); + +again: + $parser->YYData->{INPUT} =~ s/^[ \t]*//; + + for ($parser->YYData->{INPUT}) { + if (/^\#/) { + if (s/^\# (\d+) \"(.*?)\"( \d+|)//) { + $parser->YYData->{LINE} = $1-1; + $parser->YYData->{INPUT_FILENAME} = $2; + goto again; + } + if (s/^\#line (\d+) \"(.*?)\"( \d+|)//) { + $parser->YYData->{LINE} = $1-1; + $parser->YYData->{INPUT_FILENAME} = $2; + goto again; + } + if (s/^(\#.*)$//m) { + goto again; + } + } + if (s/^(\n)//) { + $parser->YYData->{LINE}++; + goto again; + } + if (s/^\"(.*?)\"//) { + $parser->YYData->{LAST_TOKEN} = $1; + return('TEXT',$1); + } + if (s/^(\d+)(\W|$)/$2/) { + $parser->YYData->{LAST_TOKEN} = $1; + return('CONSTANT',$1); + } + if (s/^([\w_]+)//) { + $parser->YYData->{LAST_TOKEN} = $1; + if ($1 =~ + /^(interface|const|typedef|union + |struct|enum|void|case|default)$/x) { + return $1; + } + return('IDENTIFIER',$1); + } + if (s/^(.)//s) { + $parser->YYData->{LAST_TOKEN} = $1; + return($1,$1); + } + } +} + +sub parse_idl($$) +{ + my $self = shift; + my $filename = shift; + + my $saved_delim = $/; + undef $/; + my $cpp = $ENV{CPP}; + if (! defined $cpp) { + $cpp = "cpp" + } + my $data = `$cpp -xc $filename`; + $/ = $saved_delim; + + $self->YYData->{INPUT} = $data; + $self->YYData->{LINE} = 0; + $self->YYData->{LAST_TOKEN} = "NONE"; + return $self->YYParse( yylex => \&_Lexer, yyerror => \&_Error ); +} diff --git a/SAMBA_3_2_MERGE/source/build/pidl/packet-dcerpc-eparser.c b/SAMBA_3_2_MERGE/source/build/pidl/packet-dcerpc-eparser.c new file mode 100644 index 00000000000..ae559e878a6 --- /dev/null +++ b/SAMBA_3_2_MERGE/source/build/pidl/packet-dcerpc-eparser.c @@ -0,0 +1,177 @@ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "packet-dcerpc.h" +#include "packet-dcerpc-nt.h" +#include "packet-dcerpc-eparser.h" + +/* Create a ndr_pull structure from data stored in a tvb at a given offset. */ + +struct e_ndr_pull *ndr_pull_init(tvbuff_t *tvb, int offset, packet_info *pinfo, + proto_tree *tree, guint8 *drep) +{ + struct e_ndr_pull *ndr; + + ndr = (struct e_ndr_pull *)g_malloc(sizeof(*ndr)); + + ndr->tvb = tvb; + ndr->offset = offset; + ndr->pinfo = pinfo; + ndr->tree = tree; + ndr->drep = drep; + + return ndr; +} + +/* Dispose of a dynamically allocated ndr_pull structure */ + +void ndr_pull_free(struct e_ndr_pull *ndr) +{ + g_free(ndr); +} + +void ndr_pull_ptr(struct e_ndr_pull *e_ndr, int hf, guint32 *ptr) +{ + e_ndr->offset = dissect_ndr_uint32( + e_ndr->tvb, e_ndr->offset, e_ndr->pinfo, + e_ndr->tree, e_ndr->drep, hf, ptr); +} + +void ndr_pull_level(struct e_ndr_pull *e_ndr, int hf, int *ptr) +{ + e_ndr->offset = dissect_ndr_uint16( + e_ndr->tvb, e_ndr->offset, e_ndr->pinfo, + e_ndr->tree, e_ndr->drep, hf, ptr); +} + +void ndr_pull_NTSTATUS(struct e_ndr_pull *e_ndr, int hf) +{ + e_ndr->offset = dissect_ntstatus( + e_ndr->tvb, e_ndr->offset, e_ndr->pinfo, + e_ndr->tree, e_ndr->drep, hf, NULL); +} + +void ndr_pull_uint8(struct e_ndr_pull *e_ndr, int hf) +{ + e_ndr->offset = dissect_ndr_uint8( + e_ndr->tvb, e_ndr->offset, e_ndr->pinfo, + e_ndr->tree, e_ndr->drep, hf, NULL); +} + +void ndr_pull_uint16(struct e_ndr_pull *e_ndr, int hf) +{ + e_ndr->offset = dissect_ndr_uint16( + e_ndr->tvb, e_ndr->offset, e_ndr->pinfo, + e_ndr->tree, e_ndr->drep, hf, NULL); +} + +void ndr_pull_uint32(struct e_ndr_pull *e_ndr, int hf) +{ + e_ndr->offset = dissect_ndr_uint32( + e_ndr->tvb, e_ndr->offset, e_ndr->pinfo, + e_ndr->tree, e_ndr->drep, hf, NULL); +} + +void ndr_pull_int64(struct e_ndr_pull *e_ndr, int hf) +{ +} + +void ndr_pull_uint64(struct e_ndr_pull *e_ndr, int hf) +{ +} + +void ndr_pull_string(struct e_ndr_pull *e_ndr, int hf) +{ +} + +void ndr_pull_NTTIME(struct e_ndr_pull *e_ndr, int hf) +{ +} + +void ndr_pull_HYPER_T(struct e_ndr_pull *e_ndr, int hf) +{ +} + +void ndr_pull_dom_sid2(struct e_ndr_pull *e_ndr, int hf) +{ +} + +void ndr_pull_security_descriptor(struct e_ndr_pull *e_ndr, int hf) +{ +} + +void ndr_pull_policy_handle(struct e_ndr_pull *e_ndr, int hf) +{ + e_ndr->offset = dissect_nt_policy_hnd( + e_ndr->tvb, e_ndr->offset, e_ndr->pinfo, e_ndr->tree, + e_ndr->drep, hf, NULL, NULL, 0, 0); +} + +void ndr_pull_advance(struct e_ndr_pull *e_ndr, int offset) +{ + e_ndr->offset += offset; +} + +void ndr_pull_align(struct e_ndr_pull *ndr, int size) +{ + if (!(ndr->flags & LIBNDR_FLAG_NOALIGN)) { + ndr->offset = (ndr->offset + (size-1)) & ~(size-1); + } +} + +void ndr_pull_subcontext_flags_fn(struct e_ndr_pull *ndr, size_t sub_size, + void (*fn)(struct e_ndr_pull *, + int ndr_flags)) +{ + struct e_ndr_pull ndr2; + + ndr_pull_subcontext_header(ndr, sub_size, &ndr2); + fn(&ndr2, NDR_SCALARS|NDR_BUFFERS); + if (sub_size) { +// ndr_pull_advance(ndr, ndr2.data_size); + } else { + ndr_pull_advance(ndr, ndr2.offset); + } +} + +/* + mark the start of a structure +*/ +void ndr_pull_struct_start(struct e_ndr_pull *ndr) +{ + struct ndr_ofs_list *ofs; + ofs = g_malloc(sizeof(*ofs)); + ofs->offset = ndr->offset; + ofs->next = ndr->ofs_list; + ndr->ofs_list = ofs; +} + +/* + mark the end of a structure +*/ +void ndr_pull_struct_end(struct e_ndr_pull *ndr) +{ + struct ndr_ofs_list *ofs = ndr->ofs_list->next; + g_free(ndr->ofs_list); + ndr->ofs_list = ofs; +} + +void ndr_pull_subcontext_header(struct e_ndr_pull *ndr, + size_t sub_size, + struct e_ndr_pull *ndr2) +{ +} + +void ndr_pull_lsa_SidArray(struct e_ndr_pull *ndr, int ndr_flags) +{ +} + +void ndr_pull_samr_LogonHours(struct e_ndr_pull *ndr, int ndr_flags) +{ +} + +void ndr_pull_samr_Password(struct e_ndr_pull *ndr, int ndr_flags) +{ +} + diff --git a/SAMBA_3_2_MERGE/source/build/pidl/packet-dcerpc-eparser.h b/SAMBA_3_2_MERGE/source/build/pidl/packet-dcerpc-eparser.h new file mode 100644 index 00000000000..e8b89e66006 --- /dev/null +++ b/SAMBA_3_2_MERGE/source/build/pidl/packet-dcerpc-eparser.h @@ -0,0 +1,80 @@ +#define NDR_SCALARS 1 +#define NDR_BUFFERS 2 + +#define LIBNDR_FLAG_BIGENDIAN (1<<0) +#define LIBNDR_FLAG_NOALIGN (1<<1) + +#define LIBNDR_FLAG_STR_ASCII (1<<2) +#define LIBNDR_FLAG_STR_LEN4 (1<<3) +#define LIBNDR_FLAG_STR_SIZE4 (1<<4) +#define LIBNDR_FLAG_STR_NOTERM (1<<5) +#define LIBNDR_FLAG_STR_NULLTERM (1<<6) +#define LIBNDR_FLAG_STR_SIZE2 (1<<7) +#define LIBNDR_STRING_FLAGS (0xFC) + +#define LIBNDR_FLAG_REF_ALLOC (1<<10) +#define LIBNDR_FLAG_REMAINING (1<<11) +#define LIBNDR_FLAG_ALIGN2 (1<<12) +#define LIBNDR_FLAG_ALIGN4 (1<<13) +#define LIBNDR_FLAG_ALIGN8 (1<<14) + +#define LIBNDR_ALIGN_FLAGS (LIBNDR_FLAG_ALIGN2|LIBNDR_FLAG_ALIGN4|LIBNDR_FLAG_ALIGN8) + +#define LIBNDR_PRINT_ARRAY_HEX (1<<15) +#define LIBNDR_PRINT_SET_VALUES (1<<16) + +/* used to force a section of IDL to be little-endian */ +#define LIBNDR_FLAG_LITTLE_ENDIAN (1<<17) + +/* Ethereal version of struct ndr_pull */ + +struct e_ndr_pull { + tvbuff_t *tvb; + int offset; + packet_info *pinfo; + proto_tree *tree; + guint8 *drep; + struct ndr_ofs_list *ofs_list; + int flags; +}; + +/* offset lists are used to allow a push/pull function to find the + start of an encapsulating structure */ +struct ndr_ofs_list { + guint32 offset; + struct ndr_ofs_list *next; +}; + +/* Create a ndr_pull structure from data stored in a tvb at a given offset. */ + +struct e_ndr_pull *ndr_pull_init(tvbuff_t *tvb, int offset, packet_info *pinfo, + proto_tree *tree, guint8 *drep); +void ndr_pull_free(struct e_ndr_pull *ndr); +void ndr_pull_ptr(struct e_ndr_pull *ndr, int hf, guint32 *ptr); +void ndr_pull_level(struct e_ndr_pull *ndr, int hf, int *ptr); +void ndr_pull_NTSTATUS(struct e_ndr_pull *ndr, int hf); +void ndr_pull_uint8(struct e_ndr_pull *ndr, int hf); +void ndr_pull_uint16(struct e_ndr_pull *ndr, int hf); +void ndr_pull_uint32(struct e_ndr_pull *ndr, int hf); +void ndr_pull_policy_handle(struct e_ndr_pull *ndr, int hf); +void ndr_pull_advance(struct e_ndr_pull *ndr, int offset); +void ndr_pull_subcontext_flags_fn(struct e_ndr_pull *ndr, size_t sub_size, + void (*fn)(struct e_ndr_pull *, + int ndr_flags)); +void ndr_pull_subcontext_header(struct e_ndr_pull *ndr, + size_t sub_size, + struct e_ndr_pull *ndr2); +void ndr_pull_struct_start(struct e_ndr_pull *ndr); +void ndr_pull_struct_end(struct e_ndr_pull *ndr); +void ndr_pull_align(struct e_ndr_pull *ndr, int size); +void ndr_pull_NTTIME(struct e_ndr_pull *e_ndr, int hf); +void ndr_pull_HYPER_T(struct e_ndr_pull *e_ndr, int hf); +void ndr_pull_int64(struct e_ndr_pull *e_ndr, int hf); +void ndr_pull_uint64(struct e_ndr_pull *e_ndr, int hf); +void ndr_pull_string(struct e_ndr_pull *e_ndr, int hf); +void ndr_pull_dom_sid2(struct e_ndr_pull *e_ndr, int hf); +void ndr_pull_security_descriptor(struct e_ndr_pull *e_ndr, int hf); + +void ndr_pull_lsa_SidArray(struct e_ndr_pull *ndr, int ndr_flags); +void ndr_pull_samr_LogonHours(struct e_ndr_pull *ndr, int ndr_flags); +void ndr_pull_samr_Password(struct e_ndr_pull *ndr, int ndr_flags); diff --git a/SAMBA_3_2_MERGE/source/build/pidl/parser.pm b/SAMBA_3_2_MERGE/source/build/pidl/parser.pm new file mode 100644 index 00000000000..69b878e46e2 --- /dev/null +++ b/SAMBA_3_2_MERGE/source/build/pidl/parser.pm @@ -0,0 +1,1531 @@ +################################################### +# Samba4 parser generator for IDL structures +# Copyright tridge@samba.org 2000-2003 +# Copyright tpot@samba.org 2001 +# released under the GNU GPL + +package IdlParser; + +use strict; +use client; + +# the list of needed functions +my %needed; +my %structs; + +my $if_uuid; +my $if_version; +my $if_endpoints; + +sub pidl($) +{ + print OUT shift; +} + +##################################################################### +# parse a properties list +sub ParseProperties($) +{ + my($props) = shift; + foreach my $d (@{$props}) { + if (ref($d) ne "HASH") { + pidl "[$d] "; + } else { + foreach my $k (keys %{$d}) { + pidl "[$k($d->{$k})] "; + } + } + } +} + +################################### +# find a sibling var in a structure +sub find_sibling($$) +{ + my($e) = shift; + my($name) = shift; + my($fn) = $e->{PARENT}; + + if ($name =~ /\*(.*)/) { + $name = $1; + } + + if ($fn->{TYPE} eq "FUNCTION") { + for my $e2 (@{$fn->{DATA}}) { + if ($e2->{NAME} eq $name) { + return $e2; + } + } + } + + for my $e2 (@{$fn->{ELEMENTS}}) { + if ($e2->{NAME} eq $name) { + return $e2; + } + } + die "invalid sibling '$name'"; +} + +#################################################################### +# work out the name of a size_is() variable +sub find_size_var($$$) +{ + my($e) = shift; + my($size) = shift; + my($var_prefix) = shift; + + my($fn) = $e->{PARENT}; + + if (util::is_constant($size)) { + return $size; + } + + if ($size =~ /ndr->|\(/) { + return $size; + } + + my $prefix = ""; + + if ($size =~ /\*(.*)/) { + $size = $1; + $prefix = "*"; + } + + if ($fn->{TYPE} ne "FUNCTION") { + return $prefix . "r->$size"; + } + + my $e2 = find_sibling($e, $size); + + 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"; + } + + die "invalid variable in $size for element $e->{NAME} in $fn->{NAME}\n"; +} + + +##################################################################### +# 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->{DATA}, "public")) { + return ""; + } + } + + if ($fn->{TYPE} eq "FUNCTION") { + if (util::has_property($fn, "public")) { + return ""; + } + } + 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 "\t{ uint32_t _flags_save_$e->{TYPE} = ndr->flags;\n"; + pidl "\tndr->flags |= $flags;\n"; + } +} + +################################################################### +# 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 "\tndr->flags = _flags_save_$e->{TYPE};\n\t}\n"; + } +} + + +##################################################################### +# work out the correct alignment for a structure +sub struct_alignment +{ + my $s = shift; + + my $align = 1; + for my $e (@{$s->{ELEMENTS}}) { + my $a = 1; + + if (!util::need_wire_pointer($e) + && defined $structs{$e->{TYPE}}) { + if ($structs{$e->{TYPE}}->{DATA}->{TYPE} eq "STRUCT") { + $a = struct_alignment($structs{$e->{TYPE}}->{DATA}); + } elsif ($structs{$e->{TYPE}}->{DATA}->{TYPE} eq "UNION") { + if (defined $structs{$e->{TYPE}}->{DATA}) { + $a = union_alignment($structs{$e->{TYPE}}->{DATA}); + } + } + } else { + $a = util::type_align($e); + } + + if ($align < $a) { + $align = $a; + } + } + + return $align; +} + +##################################################################### +# work out the correct alignment for a union +sub union_alignment +{ + my $u = shift; + + my $align = 1; + + foreach my $e (@{$u->{DATA}}) { + my $a = 1; + + if ($e->{TYPE} eq "EMPTY") { + next; + } + + if (!util::need_wire_pointer($e) + && defined $structs{$e->{DATA}->{TYPE}}) { + my $s = $structs{$e->{DATA}->{TYPE}}; + if ($s->{DATA}->{TYPE} eq "STRUCT") { + $a = struct_alignment($s->{DATA}); + } elsif ($s->{DATA}->{TYPE} eq "UNION") { + $a = union_alignment($s->{DATA}); + } + } else { + $a = util::type_align($e->{DATA}); + } + + if ($align < $a) { + $align = $a; + } + } + + return $align; +} + +##################################################################### +# parse an array - push side +sub ParseArrayPush($$$) +{ + my $e = shift; + my $var_prefix = shift; + my $ndr_flags = shift; + + my $size = find_size_var($e, util::array_size($e), $var_prefix); + + if (defined $e->{CONFORMANT_SIZE}) { + # the conformant size has already been pushed + } elsif (!util::is_inline_array($e)) { + # we need to emit the array size + pidl "\t\tNDR_CHECK(ndr_push_uint32(ndr, $size));\n"; + } + + if (my $length = util::has_property($e, "length_is")) { + $length = find_size_var($e, $length, $var_prefix); + pidl "\t\tNDR_CHECK(ndr_push_uint32(ndr, 0));\n"; + pidl "\t\tNDR_CHECK(ndr_push_uint32(ndr, $length));\n"; + $size = $length; + } + + if (util::is_scalar_type($e->{TYPE})) { + pidl "\t\tNDR_CHECK(ndr_push_array_$e->{TYPE}(ndr, $ndr_flags, $var_prefix$e->{NAME}, $size));\n"; + } else { + pidl "\t\tNDR_CHECK(ndr_push_array(ndr, $ndr_flags, $var_prefix$e->{NAME}, sizeof($var_prefix$e->{NAME}\[0]), $size, (ndr_push_flags_fn_t)ndr_push_$e->{TYPE}));\n"; + } +} + +##################################################################### +# print an array +sub ParseArrayPrint($$) +{ + my $e = shift; + my $var_prefix = shift; + my $size = find_size_var($e, util::array_size($e), $var_prefix); + my $length = util::has_property($e, "length_is"); + + if (defined $length) { + $size = find_size_var($e, $length, $var_prefix); + } + + if (util::is_scalar_type($e->{TYPE})) { + pidl "\t\tndr_print_array_$e->{TYPE}(ndr, \"$e->{NAME}\", $var_prefix$e->{NAME}, $size);\n"; + } else { + pidl "\t\tndr_print_array(ndr, \"$e->{NAME}\", $var_prefix$e->{NAME}, sizeof($var_prefix$e->{NAME}\[0]), $size, (ndr_print_fn_t)ndr_print_$e->{TYPE});\n"; + } +} + +##################################################################### +# parse an array - pull side +sub ParseArrayPull($$$) +{ + my $e = shift; + my $var_prefix = shift; + my $ndr_flags = shift; + + my $size = find_size_var($e, util::array_size($e), $var_prefix); + my $alloc_size = $size; + + # if this is a conformant array then we use that size to allocate, and make sure + # we allocate enough to pull the elements + if (defined $e->{CONFORMANT_SIZE}) { + $alloc_size = $e->{CONFORMANT_SIZE}; + + pidl "\tif ($size > $alloc_size) {\n"; + pidl "\t\treturn ndr_pull_error(ndr, NDR_ERR_CONFORMANT_SIZE, \"Bad conformant size %u should be %u\", $alloc_size, $size);\n"; + pidl "\t}\n"; + } elsif (!util::is_inline_array($e)) { + if ($var_prefix =~ /^r->out/ && $size =~ /^\*r->in/) { + my $size2 = substr($size, 1); + pidl "if (ndr->flags & LIBNDR_FLAG_REF_ALLOC) { NDR_ALLOC(ndr, $size2); }\n"; + } + + # non fixed arrays encode the size just before the array + pidl "\t{\n"; + pidl "\t\tuint32_t _array_size;\n"; + pidl "\t\tNDR_CHECK(ndr_pull_uint32(ndr, &_array_size));\n"; + if ($size =~ /r->in/) { + pidl "\t\tif (!(ndr->flags & LIBNDR_FLAG_REF_ALLOC) && _array_size != $size) {\n"; + } else { + pidl "\t\tif ($size != _array_size) {\n"; + } + pidl "\t\t\treturn ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE, \"Bad array size %u should be %u\", _array_size, $size);\n"; + pidl "\t\t}\n"; + if ($size =~ /r->in/) { + pidl "else { $size = _array_size; }\n"; + } + pidl "\t}\n"; + } + + if ((util::need_alloc($e) && !util::is_fixed_array($e)) || + ($var_prefix eq "r->in." && util::has_property($e, "ref"))) { + if (!util::is_inline_array($e) || $ndr_flags eq "NDR_SCALARS") { + pidl "\t\tNDR_ALLOC_N(ndr, $var_prefix$e->{NAME}, MAX(1, $alloc_size));\n"; + } + } + + if (($var_prefix eq "r->out." && util::has_property($e, "ref"))) { + if (!util::is_inline_array($e) || $ndr_flags eq "NDR_SCALARS") { + pidl "\tif (ndr->flags & LIBNDR_FLAG_REF_ALLOC) {"; + pidl "\t\tNDR_ALLOC_N(ndr, $var_prefix$e->{NAME}, MAX(1, $alloc_size));\n"; + pidl "\t}\n"; + } + } + + pidl "\t{\n"; + + if (my $length = util::has_property($e, "length_is")) { + $length = find_size_var($e, $length, $var_prefix); + pidl "\t\tuint32_t _offset, _length;\n"; + pidl "\t\tNDR_CHECK(ndr_pull_uint32(ndr, &_offset));\n"; + pidl "\t\tNDR_CHECK(ndr_pull_uint32(ndr, &_length));\n"; + pidl "\t\tif (_offset != 0) return ndr_pull_error(ndr, NDR_ERR_OFFSET, \"Bad array offset 0x%08x\", _offset);\n"; + pidl "\t\tif (_length > $size || _length != $length) return ndr_pull_error(ndr, NDR_ERR_LENGTH, \"Bad array length 0x%08x > size 0x%08x\", _offset, $size);\n\n"; + $size = "_length"; + } + + if (util::is_scalar_type($e->{TYPE})) { + pidl "\t\tNDR_CHECK(ndr_pull_array_$e->{TYPE}(ndr, $ndr_flags, $var_prefix$e->{NAME}, $size));\n"; + } else { + pidl "\t\tNDR_CHECK(ndr_pull_array(ndr, $ndr_flags, (void **)$var_prefix$e->{NAME}, sizeof($var_prefix$e->{NAME}\[0]), $size, (ndr_pull_flags_fn_t)ndr_pull_$e->{TYPE}));\n"; + } + + pidl "\t}\n"; +} + + +##################################################################### +# parse scalars in a structure element +sub ParseElementPushScalar($$$) +{ + my($e) = shift; + my($var_prefix) = shift; + my($ndr_flags) = shift; + my $cprefix = util::c_push_prefix($e); + my $sub_size = util::has_property($e, "subcontext"); + + start_flags($e); + + if (my $value = util::has_property($e, "value")) { + pidl "\t$cprefix$var_prefix$e->{NAME} = $value;\n"; + } + + if (util::has_property($e, "relative")) { + pidl "\tNDR_CHECK(ndr_push_relative(ndr, NDR_SCALARS, $var_prefix$e->{NAME}, (ndr_push_const_fn_t) ndr_push_$e->{TYPE}));\n"; + } elsif (util::is_inline_array($e)) { + ParseArrayPush($e, "r->", "NDR_SCALARS"); + } elsif (util::need_wire_pointer($e)) { + pidl "\tNDR_CHECK(ndr_push_ptr(ndr, $var_prefix$e->{NAME}));\n"; + } elsif (util::need_alloc($e)) { + # no scalar component + } elsif (my $switch = util::has_property($e, "switch_is")) { + ParseElementPushSwitch($e, $var_prefix, $ndr_flags, $switch); + } elsif (defined $sub_size) { + if (util::is_builtin_type($e->{TYPE})) { + pidl "\tNDR_CHECK(ndr_push_subcontext_fn(ndr, $sub_size, $cprefix$var_prefix$e->{NAME}, (ndr_push_fn_t) ndr_push_$e->{TYPE}));\n"; + } else { + pidl "\tNDR_CHECK(ndr_push_subcontext_flags_fn(ndr, $sub_size, $cprefix$var_prefix$e->{NAME}, (ndr_push_flags_fn_t) ndr_push_$e->{TYPE}));\n"; + } + } elsif (util::is_builtin_type($e->{TYPE})) { + pidl "\tNDR_CHECK(ndr_push_$e->{TYPE}(ndr, $cprefix$var_prefix$e->{NAME}));\n"; + } else { + pidl "\tNDR_CHECK(ndr_push_$e->{TYPE}(ndr, $ndr_flags, $cprefix$var_prefix$e->{NAME}));\n"; + } + + end_flags($e); +} + +##################################################################### +# print scalars in a structure element +sub ParseElementPrintScalar($$) +{ + my($e) = shift; + my($var_prefix) = shift; + my $cprefix = util::c_push_prefix($e); + + if (util::has_property($e, "noprint")) { + return; + } + + if (my $value = util::has_property($e, "value")) { + pidl "\tif (ndr->flags & LIBNDR_PRINT_SET_VALUES) {\n"; + pidl "\t\t$cprefix$var_prefix$e->{NAME} = $value;\n"; + pidl "\t}\n"; + } + + if (util::is_fixed_array($e)) { + ParseElementPrintBuffer($e, $var_prefix); + } elsif (util::has_direct_buffers($e)) { + pidl "\tndr_print_ptr(ndr, \"$e->{NAME}\", $var_prefix$e->{NAME});\n"; + pidl "\tndr->depth++;\n"; + ParseElementPrintBuffer($e, $var_prefix); + pidl "\tndr->depth--;\n"; + } elsif (my $switch = util::has_property($e, "switch_is")) { + ParseElementPrintSwitch($e, $var_prefix, $switch); + } else { + pidl "\tndr_print_$e->{TYPE}(ndr, \"$e->{NAME}\", $cprefix$var_prefix$e->{NAME});\n"; + } +} + +##################################################################### +# parse scalars in a structure element - pull size +sub ParseElementPullSwitch($$$$) +{ + my($e) = shift; + my($var_prefix) = shift; + my($ndr_flags) = shift; + my $switch = shift; + my $switch_var = find_size_var($e, $switch, $var_prefix); + + my $cprefix = util::c_pull_prefix($e); + + my $utype = $structs{$e->{TYPE}}; + if (!defined $utype || + !util::has_property($utype->{DATA}, "nodiscriminant")) { + my $e2 = find_sibling($e, $switch); + pidl "\tif (($ndr_flags) & NDR_SCALARS) {\n"; + pidl "\t\t $e2->{TYPE} _level;\n"; + pidl "\t\tNDR_CHECK(ndr_pull_$e2->{TYPE}(ndr, &_level));\n"; + if ($switch_var =~ /r->in/) { + pidl "\t\tif (!(ndr->flags & LIBNDR_FLAG_REF_ALLOC) && _level != $switch_var) {\n"; + } else { + pidl "\t\tif (_level != $switch_var) {\n"; + } + pidl "\t\t\treturn ndr_pull_error(ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value %u in $e->{NAME}\");\t\t}\n"; + if ($switch_var =~ /r->/) { + pidl "else { $switch_var = _level; }\n"; + } + pidl "\t}\n"; + } + + my $sub_size = util::has_property($e, "subcontext"); + if (defined $sub_size) { + pidl "\tNDR_CHECK(ndr_pull_subcontext_union_fn(ndr, $sub_size, $switch_var, $cprefix$var_prefix$e->{NAME}, (ndr_pull_union_fn_t) ndr_pull_$e->{TYPE}));\n"; + } else { + pidl "\tNDR_CHECK(ndr_pull_$e->{TYPE}(ndr, $ndr_flags, $switch_var, $cprefix$var_prefix$e->{NAME}));\n"; + } + + +} + +##################################################################### +# push switch element +sub ParseElementPushSwitch($$$$) +{ + my($e) = shift; + my($var_prefix) = shift; + my($ndr_flags) = shift; + my $switch = shift; + my $switch_var = find_size_var($e, $switch, $var_prefix); + my $cprefix = util::c_push_prefix($e); + + my $utype = $structs{$e->{TYPE}}; + if (!defined $utype || + !util::has_property($utype->{DATA}, "nodiscriminant")) { + my $e2 = find_sibling($e, $switch); + pidl "\tif (($ndr_flags) & NDR_SCALARS) {\n"; + pidl "\t\tNDR_CHECK(ndr_push_$e2->{TYPE}(ndr, $switch_var));\n"; + pidl "\t}\n"; + } + + my $sub_size = util::has_property($e, "subcontext"); + if (defined $sub_size) { + pidl "\tNDR_CHECK(ndr_push_subcontext_union_fn(ndr, $sub_size, $switch_var, $cprefix$var_prefix$e->{NAME}, (ndr_push_union_fn_t) ndr_push_$e->{TYPE}));\n"; + } else { + pidl "\tNDR_CHECK(ndr_push_$e->{TYPE}(ndr, $ndr_flags, $switch_var, $cprefix$var_prefix$e->{NAME}));\n"; + } +} + +##################################################################### +# print scalars in a structure element +sub ParseElementPrintSwitch($$$) +{ + my($e) = shift; + my($var_prefix) = shift; + my $switch = shift; + my $switch_var = find_size_var($e, $switch, $var_prefix); + my $cprefix = util::c_push_prefix($e); + + pidl "\tndr_print_$e->{TYPE}(ndr, \"$e->{NAME}\", $switch_var, $cprefix$var_prefix$e->{NAME});\n"; +} + + +##################################################################### +# parse scalars in a structure element - pull size +sub ParseElementPullScalar($$$) +{ + my($e) = shift; + my($var_prefix) = shift; + my($ndr_flags) = shift; + my $cprefix = util::c_pull_prefix($e); + my $sub_size = util::has_property($e, "subcontext"); + + start_flags($e); + + if (util::has_property($e, "relative")) { + pidl "\tNDR_CHECK(ndr_pull_relative(ndr, (const void **)&$var_prefix$e->{NAME}, sizeof(*$var_prefix$e->{NAME}), (ndr_pull_flags_fn_t)ndr_pull_$e->{TYPE}));\n"; + } elsif (util::is_inline_array($e)) { + ParseArrayPull($e, "r->", "NDR_SCALARS"); + } elsif (util::need_wire_pointer($e)) { + pidl "\tNDR_CHECK(ndr_pull_uint32(ndr, &_ptr_$e->{NAME}));\n"; + pidl "\tif (_ptr_$e->{NAME}) {\n"; + pidl "\t\tNDR_ALLOC(ndr, $var_prefix$e->{NAME});\n"; + pidl "\t} else {\n"; + pidl "\t\t$var_prefix$e->{NAME} = NULL;\n"; + pidl "\t}\n"; + } elsif (util::need_alloc($e)) { + # no scalar component + } elsif (my $switch = util::has_property($e, "switch_is")) { + ParseElementPullSwitch($e, $var_prefix, $ndr_flags, $switch); + } elsif (defined $sub_size) { + if (util::is_builtin_type($e->{TYPE})) { + pidl "\tNDR_CHECK(ndr_pull_subcontext_fn(ndr, $sub_size, $cprefix$var_prefix$e->{NAME}, (ndr_pull_fn_t) ndr_pull_$e->{TYPE}));\n"; + } else { + pidl "\tNDR_CHECK(ndr_pull_subcontext_flags_fn(ndr, $sub_size, $cprefix$var_prefix$e->{NAME}, (ndr_pull_flags_fn_t) ndr_pull_$e->{TYPE}));\n"; + } + } elsif (util::is_builtin_type($e->{TYPE})) { + pidl "\tNDR_CHECK(ndr_pull_$e->{TYPE}(ndr, $cprefix$var_prefix$e->{NAME}));\n"; + } else { + pidl "\tNDR_CHECK(ndr_pull_$e->{TYPE}(ndr, $ndr_flags, $cprefix$var_prefix$e->{NAME}));\n"; + } + + end_flags($e); +} + +##################################################################### +# parse buffers in a structure element +sub ParseElementPushBuffer($$$) +{ + my($e) = shift; + my($var_prefix) = shift; + my($ndr_flags) = shift; + my $cprefix = util::c_push_prefix($e); + my $sub_size = util::has_property($e, "subcontext"); + + if (util::is_pure_scalar($e)) { + return; + } + + start_flags($e); + + if (util::need_wire_pointer($e)) { + pidl "\tif ($var_prefix$e->{NAME}) {\n"; + } + + if (util::has_property($e, "relative")) { + pidl "\tNDR_CHECK(ndr_push_relative(ndr, NDR_BUFFERS, $cprefix$var_prefix$e->{NAME}, (ndr_push_const_fn_t) ndr_push_$e->{TYPE}));\n"; + } elsif (util::is_inline_array($e)) { + ParseArrayPush($e, "r->", "NDR_BUFFERS"); + } elsif (util::array_size($e)) { + ParseArrayPush($e, "r->", "NDR_SCALARS|NDR_BUFFERS"); + } elsif (my $switch = util::has_property($e, "switch_is")) { + if ($e->{POINTERS}) { + ParseElementPushSwitch($e, $var_prefix, "NDR_BUFFERS|NDR_SCALARS", $switch); + } else { + ParseElementPushSwitch($e, $var_prefix, "NDR_BUFFERS", $switch); + } + } elsif (defined $sub_size) { + if ($e->{POINTERS}) { + if (util::is_builtin_type($e->{TYPE})) { + pidl "\tNDR_CHECK(ndr_push_subcontext_fn(ndr, $sub_size, $cprefix$var_prefix$e->{NAME}, (ndr_push_fn_t) ndr_push_$e->{TYPE}));\n"; + } else { + pidl "\tNDR_CHECK(ndr_push_subcontext_flags_fn(ndr, $sub_size, $cprefix$var_prefix$e->{NAME}, (ndr_push_flags_fn_t) ndr_push_$e->{TYPE}));\n"; + } + } + } elsif (util::is_builtin_type($e->{TYPE})) { + pidl "\t\tNDR_CHECK(ndr_push_$e->{TYPE}(ndr, $cprefix$var_prefix$e->{NAME}));\n"; + } elsif ($e->{POINTERS}) { + pidl "\t\tNDR_CHECK(ndr_push_$e->{TYPE}(ndr, NDR_SCALARS|NDR_BUFFERS, $cprefix$var_prefix$e->{NAME}));\n"; + } else { + pidl "\t\tNDR_CHECK(ndr_push_$e->{TYPE}(ndr, $ndr_flags, $cprefix$var_prefix$e->{NAME}));\n"; + } + + if (util::need_wire_pointer($e)) { + pidl "\t}\n"; + } + + end_flags($e); +} + +##################################################################### +# print buffers in a structure element +sub ParseElementPrintBuffer($$) +{ + my($e) = shift; + my($var_prefix) = shift; + my $cprefix = util::c_push_prefix($e); + + if (util::need_wire_pointer($e)) { + pidl "\tif ($var_prefix$e->{NAME}) {\n"; + } + + if (util::array_size($e)) { + ParseArrayPrint($e, $var_prefix); + } elsif (my $switch = util::has_property($e, "switch_is")) { + ParseElementPrintSwitch($e, $var_prefix, $switch); + } else { + pidl "\t\tndr_print_$e->{TYPE}(ndr, \"$e->{NAME}\", $cprefix$var_prefix$e->{NAME});\n"; + } + + if (util::need_wire_pointer($e)) { + pidl "\t}\n"; + } +} + + +##################################################################### +# parse buffers in a structure element - pull side +sub ParseElementPullBuffer($$$) +{ + my($e) = shift; + my($var_prefix) = shift; + my($ndr_flags) = shift; + my $cprefix = util::c_pull_prefix($e); + my $sub_size = util::has_property($e, "subcontext"); + + if (util::is_pure_scalar($e)) { + return; + } + + if (util::has_property($e, "relative")) { + return; + } + + start_flags($e); + + if (util::need_wire_pointer($e)) { + pidl "\tif ($var_prefix$e->{NAME}) {\n"; + } + + if (util::is_inline_array($e)) { + ParseArrayPull($e, "r->", "NDR_BUFFERS"); + } elsif (util::array_size($e)) { + ParseArrayPull($e, "r->", "NDR_SCALARS|NDR_BUFFERS"); + } elsif (my $switch = util::has_property($e, "switch_is")) { + if ($e->{POINTERS}) { + ParseElementPullSwitch($e, $var_prefix, "NDR_SCALARS|NDR_BUFFERS", $switch); + } else { + ParseElementPullSwitch($e, $var_prefix, "NDR_BUFFERS", $switch); + } + } elsif (defined $sub_size) { + if ($e->{POINTERS}) { + if (util::is_builtin_type($e->{TYPE})) { + pidl "\tNDR_CHECK(ndr_pull_subcontext_fn(ndr, $sub_size, $cprefix$var_prefix$e->{NAME}, (ndr_pull_fn_t) ndr_pull_$e->{TYPE}));\n"; + } else { + pidl "\tNDR_CHECK(ndr_pull_subcontext_flags_fn(ndr, $sub_size, $cprefix$var_prefix$e->{NAME}, (ndr_pull_flags_fn_t) ndr_pull_$e->{TYPE}));\n"; + } + } + } elsif (util::is_builtin_type($e->{TYPE})) { + pidl "\t\tNDR_CHECK(ndr_pull_$e->{TYPE}(ndr, $cprefix$var_prefix$e->{NAME}));\n"; + } elsif ($e->{POINTERS}) { + pidl "\t\tNDR_CHECK(ndr_pull_$e->{TYPE}(ndr, NDR_SCALARS|NDR_BUFFERS, $cprefix$var_prefix$e->{NAME}));\n"; + } else { + pidl "\t\tNDR_CHECK(ndr_pull_$e->{TYPE}(ndr, $ndr_flags, $cprefix$var_prefix$e->{NAME}));\n"; + } + + if (util::need_wire_pointer($e)) { + pidl "\t}\n"; + } + + end_flags($e); +} + +##################################################################### +# parse a struct +sub ParseStructPush($) +{ + my($struct) = shift; + my $conform_e; + + if (! defined $struct->{ELEMENTS}) { + return; + } + + start_flags($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 push 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 (defined $e->{ARRAY_LEN} && $e->{ARRAY_LEN} eq "*") { + my $size = find_size_var($e, util::array_size($e), "r->"); + $e->{CONFORMANT_SIZE} = $size; + $conform_e = $e; + pidl "\tNDR_CHECK(ndr_push_uint32(ndr, $size));\n"; + } + + pidl "\tif (!(ndr_flags & NDR_SCALARS)) goto buffers;\n"; + + pidl "\tNDR_CHECK(ndr_push_struct_start(ndr));\n"; + + my $align = struct_alignment($struct); + pidl "\tNDR_CHECK(ndr_push_align(ndr, $align));\n"; + + foreach my $e (@{$struct->{ELEMENTS}}) { + ParseElementPushScalar($e, "r->", "NDR_SCALARS"); + } + + pidl "buffers:\n"; + pidl "\tif (!(ndr_flags & NDR_BUFFERS)) goto done;\n"; + foreach my $e (@{$struct->{ELEMENTS}}) { + ParseElementPushBuffer($e, "r->", "NDR_BUFFERS"); + } + + pidl "\tndr_push_struct_end(ndr);\n"; + + pidl "done:\n"; + + end_flags($struct); +} + +##################################################################### +# generate a struct print function +sub ParseStructPrint($) +{ + my($struct) = shift; + + if (! defined $struct->{ELEMENTS}) { + return; + } + + start_flags($struct); + + pidl "\tndr->depth++;\n"; + foreach my $e (@{$struct->{ELEMENTS}}) { + ParseElementPrintScalar($e, "r->"); + } + pidl "\tndr->depth--;\n"; + + end_flags($struct); +} + +##################################################################### +# parse a struct - pull side +sub ParseStructPull($) +{ + my($struct) = shift; + my $conform_e; + + if (! defined $struct->{ELEMENTS}) { + return; + } + + # 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 (defined $e->{ARRAY_LEN} && $e->{ARRAY_LEN} eq "*") { + $conform_e = $e; + pidl "\tuint32_t _conformant_size;\n"; + $conform_e->{CONFORMANT_SIZE} = "_conformant_size"; + } + + # declare any internal pointers we need + foreach my $e (@{$struct->{ELEMENTS}}) { + if (util::need_wire_pointer($e) && + !util::has_property($e, "relative")) { + pidl "\tuint32_t _ptr_$e->{NAME};\n"; + } + } + + start_flags($struct); + + pidl "\tif (!(ndr_flags & NDR_SCALARS)) goto buffers;\n"; + + pidl "\tNDR_CHECK(ndr_pull_struct_start(ndr));\n"; + + if (defined $conform_e) { + pidl "\tNDR_CHECK(ndr_pull_uint32(ndr, &$conform_e->{CONFORMANT_SIZE}));\n"; + } + + my $align = struct_alignment($struct); + pidl "\tNDR_CHECK(ndr_pull_align(ndr, $align));\n"; + + foreach my $e (@{$struct->{ELEMENTS}}) { + ParseElementPullScalar($e, "r->", "NDR_SCALARS"); + } + + pidl "buffers:\n"; + pidl "\tif (!(ndr_flags & NDR_BUFFERS)) goto done;\n"; + foreach my $e (@{$struct->{ELEMENTS}}) { + ParseElementPullBuffer($e, "r->", "NDR_BUFFERS"); + } + + pidl "\tndr_pull_struct_end(ndr);\n"; + + pidl "done:\n"; + + end_flags($struct); +} + + +##################################################################### +# parse a union - push side +sub ParseUnionPush($) +{ + my $e = shift; + my $have_default = 0; + + start_flags($e); + + pidl "\tif (!(ndr_flags & NDR_SCALARS)) goto buffers;\n"; + + pidl "\tNDR_CHECK(ndr_push_struct_start(ndr));\n"; + +# my $align = union_alignment($e); +# pidl "\tNDR_CHECK(ndr_push_align(ndr, $align));\n"; + + pidl "\tswitch (level) {\n"; + foreach my $el (@{$e->{DATA}}) { + if ($el->{CASE} eq "default") { + pidl "\tdefault:\n"; + $have_default = 1; + } else { + pidl "\tcase $el->{CASE}:\n"; + } + if ($el->{TYPE} eq "UNION_ELEMENT") { + ParseElementPushScalar($el->{DATA}, "r->", "NDR_SCALARS"); + } + pidl "\tbreak;\n\n"; + } + if (! $have_default) { + pidl "\tdefault:\n"; + pidl "\t\treturn ndr_push_error(ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value \%u\", level);\n"; + } + pidl "\t}\n"; + pidl "buffers:\n"; + pidl "\tif (!(ndr_flags & NDR_BUFFERS)) goto done;\n"; + pidl "\tswitch (level) {\n"; + foreach my $el (@{$e->{DATA}}) { + if ($el->{CASE} eq "default") { + pidl "\tdefault:\n"; + } else { + pidl "\tcase $el->{CASE}:\n"; + } + if ($el->{TYPE} eq "UNION_ELEMENT") { + ParseElementPushBuffer($el->{DATA}, "r->", "NDR_BUFFERS"); + } + pidl "\tbreak;\n\n"; + } + if (! $have_default) { + pidl "\tdefault:\n"; + pidl "\t\treturn ndr_push_error(ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value \%u\", level);\n"; + } + pidl "\t}\n"; + pidl "\tndr_push_struct_end(ndr);\n"; + pidl "done:\n"; + end_flags($e); +} + +##################################################################### +# print a union +sub ParseUnionPrint($) +{ + my $e = shift; + my $have_default = 0; + + start_flags($e); + + pidl "\tswitch (level) {\n"; + foreach my $el (@{$e->{DATA}}) { + if ($el->{CASE} eq "default") { + $have_default = 1; + pidl "\tdefault:\n"; + } else { + pidl "\tcase $el->{CASE}:\n"; + } + if ($el->{TYPE} eq "UNION_ELEMENT") { + ParseElementPrintScalar($el->{DATA}, "r->"); + } + pidl "\tbreak;\n\n"; + } + if (! $have_default) { + pidl "\tdefault:\n\t\tndr_print_bad_level(ndr, name, level);\n"; + } + pidl "\t}\n"; + + end_flags($e); +} + +##################################################################### +# parse a union - pull side +sub ParseUnionPull($) +{ + my $e = shift; + my $have_default = 0; + + start_flags($e); + + pidl "\tif (!(ndr_flags & NDR_SCALARS)) goto buffers;\n"; + + pidl "\tNDR_CHECK(ndr_pull_struct_start(ndr));\n"; + +# my $align = union_alignment($e); +# pidl "\tNDR_CHECK(ndr_pull_align(ndr, $align));\n"; + + pidl "\tswitch (level) {\n"; + foreach my $el (@{$e->{DATA}}) { + if ($el->{CASE} eq "default") { + pidl "\tdefault: {\n"; + $have_default = 1; + } else { + pidl "\tcase $el->{CASE}: {\n"; + } + if ($el->{TYPE} eq "UNION_ELEMENT") { + my $e2 = $el->{DATA}; + if ($e2->{POINTERS}) { + pidl "\t\tuint32_t _ptr_$e2->{NAME};\n"; + } + ParseElementPullScalar($el->{DATA}, "r->", "NDR_SCALARS"); + } + pidl "\tbreak; }\n\n"; + } + if (! $have_default) { + pidl "\tdefault:\n"; + pidl "\t\treturn ndr_pull_error(ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value \%u\", level);\n"; + } + pidl "\t}\n"; + pidl "buffers:\n"; + pidl "\tif (!(ndr_flags & NDR_BUFFERS)) goto done;\n"; + pidl "\tswitch (level) {\n"; + foreach my $el (@{$e->{DATA}}) { + if ($el->{CASE} eq "default") { + pidl "\tdefault:\n"; + } else { + pidl "\tcase $el->{CASE}:\n"; + } + if ($el->{TYPE} eq "UNION_ELEMENT") { + ParseElementPullBuffer($el->{DATA}, "r->", "NDR_BUFFERS"); + } + pidl "\tbreak;\n\n"; + } + if (! $have_default) { + pidl "\tdefault:\n"; + pidl "\t\treturn ndr_pull_error(ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value \%u\", level);\n"; + } + pidl "\t}\n"; + pidl "\tndr_pull_struct_end(ndr);\n"; + pidl "done:\n"; + end_flags($e); +} + +##################################################################### +# parse a type +sub ParseTypePush($) +{ + my($data) = shift; + + if (ref($data) eq "HASH") { + ($data->{TYPE} eq "STRUCT") && + ParseStructPush($data); + ($data->{TYPE} eq "UNION") && + ParseUnionPush($data); + } +} + +##################################################################### +# generate a print function for a type +sub ParseTypePrint($) +{ + my($data) = shift; + + if (ref($data) eq "HASH") { + ($data->{TYPE} eq "STRUCT") && + ParseStructPrint($data); + ($data->{TYPE} eq "UNION") && + ParseUnionPrint($data); + } +} + +##################################################################### +# parse a type +sub ParseTypePull($) +{ + my($data) = shift; + + if (ref($data) eq "HASH") { + ($data->{TYPE} eq "STRUCT") && + ParseStructPull($data); + ($data->{TYPE} eq "UNION") && + ParseUnionPull($data); + } +} + +##################################################################### +# parse a typedef - push side +sub ParseTypedefPush($) +{ + my($e) = shift; + my $static = fn_prefix($e); + + if (! $needed{"push_$e->{NAME}"}) { +# print "push_$e->{NAME} not needed\n"; + return; + } + + if ($e->{DATA}->{TYPE} eq "STRUCT") { + pidl $static . "NTSTATUS ndr_push_$e->{NAME}(struct ndr_push *ndr, int ndr_flags, struct $e->{NAME} *r)"; + pidl "\n{\n"; + ParseTypePush($e->{DATA}); + pidl "\treturn NT_STATUS_OK;\n"; + pidl "}\n\n"; + } + + if ($e->{DATA}->{TYPE} eq "UNION") { + pidl $static . "NTSTATUS ndr_push_$e->{NAME}(struct ndr_push *ndr, int ndr_flags, uint16_t level, union $e->{NAME} *r)"; + pidl "\n{\n"; + ParseTypePush($e->{DATA}); + pidl "\treturn NT_STATUS_OK;\n"; + pidl "}\n\n"; + } +} + + +##################################################################### +# parse a typedef - pull side +sub ParseTypedefPull($) +{ + my($e) = shift; + my $static = fn_prefix($e); + + if (! $needed{"pull_$e->{NAME}"}) { +# print "pull_$e->{NAME} not needed\n"; + return; + } + + if ($e->{DATA}->{TYPE} eq "STRUCT") { + pidl $static . "NTSTATUS ndr_pull_$e->{NAME}(struct ndr_pull *ndr, int ndr_flags, struct $e->{NAME} *r)"; + pidl "\n{\n"; + ParseTypePull($e->{DATA}); + pidl "\treturn NT_STATUS_OK;\n"; + pidl "}\n\n"; + } + + if ($e->{DATA}->{TYPE} eq "UNION") { + pidl $static . "NTSTATUS ndr_pull_$e->{NAME}(struct ndr_pull *ndr, int ndr_flags, uint16_t level, union $e->{NAME} *r)"; + pidl "\n{\n"; + ParseTypePull($e->{DATA}); + pidl "\treturn NT_STATUS_OK;\n"; + pidl "}\n\n"; + } +} + + +##################################################################### +# parse a typedef - print side +sub ParseTypedefPrint($) +{ + my($e) = shift; + + if ($e->{DATA}->{TYPE} eq "STRUCT") { + pidl "void ndr_print_$e->{NAME}(struct ndr_print *ndr, const char *name, struct $e->{NAME} *r)"; + pidl "\n{\n"; + pidl "\tndr_print_struct(ndr, name, \"$e->{NAME}\");\n"; + ParseTypePrint($e->{DATA}); + pidl "}\n\n"; + } + + if ($e->{DATA}->{TYPE} eq "UNION") { + pidl "void ndr_print_$e->{NAME}(struct ndr_print *ndr, const char *name, uint16_t level, union $e->{NAME} *r)"; + pidl "\n{\n"; + pidl "\tndr_print_union(ndr, name, level, \"$e->{NAME}\");\n"; + ParseTypePrint($e->{DATA}); + pidl "}\n\n"; + } +} + +##################################################################### +# parse a function - print side +sub ParseFunctionPrint($) +{ + my($fn) = shift; + + pidl "void ndr_print_$fn->{NAME}(struct ndr_print *ndr, const char *name, int flags, struct $fn->{NAME} *r)"; + pidl "\n{\n"; + pidl "\tndr_print_struct(ndr, name, \"$fn->{NAME}\");\n"; + pidl "\tndr->depth++;\n"; + + pidl "\tif (flags & NDR_SET_VALUES) {\n"; + pidl "\t\tndr->flags |= LIBNDR_PRINT_SET_VALUES;\n"; + pidl "}\n"; + + pidl "\tif (flags & NDR_IN) {\n"; + pidl "\t\tndr_print_struct(ndr, \"in\", \"$fn->{NAME}\");\n"; + pidl "\tndr->depth++;\n"; + foreach my $e (@{$fn->{DATA}}) { + if (util::has_property($e, "in")) { + ParseElementPrintScalar($e, "r->in."); + } + } + pidl "\tndr->depth--;\n"; + pidl "\t}\n"; + + pidl "\tif (flags & NDR_OUT) {\n"; + pidl "\t\tndr_print_struct(ndr, \"out\", \"$fn->{NAME}\");\n"; + pidl "\tndr->depth++;\n"; + foreach my $e (@{$fn->{DATA}}) { + if (util::has_property($e, "out")) { + ParseElementPrintScalar($e, "r->out."); + } + } + if ($fn->{RETURN_TYPE} && $fn->{RETURN_TYPE} ne "void") { + if (util::is_scalar_type($fn->{RETURN_TYPE})) { + pidl "\tndr_print_$fn->{RETURN_TYPE}(ndr, \"result\", r->out.result);\n"; + } else { + pidl "\tndr_print_$fn->{RETURN_TYPE}(ndr, \"result\", &r->out.result);\n"; + } + } + pidl "\tndr->depth--;\n"; + pidl "\t}\n"; + + pidl "\tndr->depth--;\n"; + pidl "}\n\n"; +} + + +##################################################################### +# parse a function element +sub ParseFunctionElementPush($$) +{ + my $e = shift; + my $inout = shift; + + if (util::array_size($e)) { + if (util::need_wire_pointer($e)) { + pidl "\tNDR_CHECK(ndr_push_ptr(ndr, r->$inout.$e->{NAME}));\n"; + pidl "\tif (r->$inout.$e->{NAME}) {\n"; + ParseArrayPush($e, "r->$inout.", "NDR_SCALARS|NDR_BUFFERS"); + pidl "\t}\n"; + } else { + ParseArrayPush($e, "r->$inout.", "NDR_SCALARS|NDR_BUFFERS"); + } + } else { + ParseElementPushScalar($e, "r->$inout.", "NDR_SCALARS|NDR_BUFFERS"); + if ($e->{POINTERS}) { + ParseElementPushBuffer($e, "r->$inout.", "NDR_SCALARS|NDR_BUFFERS"); + } + } +} + +##################################################################### +# parse a function +sub ParseFunctionPush($) +{ + my($fn) = shift; + my $static = fn_prefix($fn); + + pidl $static . "NTSTATUS ndr_push_$fn->{NAME}(struct ndr_push *ndr, int flags, struct $fn->{NAME} *r)\n{\n"; + + pidl "\n\tif (!(flags & NDR_IN)) goto ndr_out;\n\n"; + foreach my $e (@{$fn->{DATA}}) { + if (util::has_property($e, "in")) { + ParseFunctionElementPush($e, "in"); + } + } + + pidl "\nndr_out:\n"; + pidl "\tif (!(flags & NDR_OUT)) goto done;\n\n"; + foreach my $e (@{$fn->{DATA}}) { + if (util::has_property($e, "out")) { + ParseFunctionElementPush($e, "out"); + } + } + + if ($fn->{RETURN_TYPE} && $fn->{RETURN_TYPE} ne "void") { + pidl "\tNDR_CHECK(ndr_push_$fn->{RETURN_TYPE}(ndr, r->out.result));\n"; + } + + pidl "\ndone:\n"; + pidl "\n\treturn NT_STATUS_OK;\n}\n\n"; +} + +##################################################################### +# parse a function element +sub ParseFunctionElementPull($$) +{ + my $e = shift; + my $inout = shift; + + if (util::array_size($e)) { + if (util::need_wire_pointer($e)) { + pidl "\tNDR_CHECK(ndr_pull_uint32(ndr, &_ptr_$e->{NAME}));\n"; + pidl "\tif (_ptr_$e->{NAME}) {\n"; + } elsif ($inout eq "out" && util::has_property($e, "ref")) { + pidl "\tif (r->$inout.$e->{NAME}) {\n"; + } else { + pidl "\t{\n"; + } + ParseArrayPull($e, "r->$inout.", "NDR_SCALARS|NDR_BUFFERS"); + pidl "\t}\n"; + } else { + if ($inout eq "out" && util::has_property($e, "ref")) { + pidl "\tif (ndr->flags & LIBNDR_FLAG_REF_ALLOC) {\n"; + pidl "\tNDR_ALLOC(ndr, r->out.$e->{NAME});\n"; + pidl "\t}\n"; + } + if ($inout eq "in" && util::has_property($e, "ref")) { + pidl "\tNDR_ALLOC(ndr, r->in.$e->{NAME});\n"; + } + + ParseElementPullScalar($e, "r->$inout.", "NDR_SCALARS|NDR_BUFFERS"); + if ($e->{POINTERS}) { + ParseElementPullBuffer($e, "r->$inout.", "NDR_SCALARS|NDR_BUFFERS"); + } + } +} + + +############################################################ +# allocate ref variables +sub AllocateRefVars($) +{ + my $e = shift; + my $asize = util::array_size($e); + + # note that if the variable is also an "in" + # variable then we copy the initial value from + # the in side + + if (!defined $asize) { + # its a simple variable + pidl "\tNDR_ALLOC(ndr, r->out.$e->{NAME});\n"; + if (util::has_property($e, "in")) { + pidl "\t*r->out.$e->{NAME} = *r->in.$e->{NAME};\n"; + } else { + pidl "\tZERO_STRUCTP(r->out.$e->{NAME});\n"; + } + return; + } + + # its an array + my $size = find_size_var($e, $asize, "r->out."); + pidl "\tNDR_ALLOC_N(ndr, r->out.$e->{NAME}, MAX(1, $size));\n"; + if (util::has_property($e, "in")) { + pidl "\tmemcpy(r->out.$e->{NAME},r->in.$e->{NAME},$size * sizeof(*r->in.$e->{NAME}));\n"; + } else { + pidl "\tmemset(r->out.$e->{NAME}, 0, $size * sizeof(*r->out.$e->{NAME}));\n"; + } +} + + +##################################################################### +# parse a function +sub ParseFunctionPull($) +{ + my($fn) = shift; + my $static = fn_prefix($fn); + + # pull function args + pidl $static . "NTSTATUS ndr_pull_$fn->{NAME}(struct ndr_pull *ndr, int flags, struct $fn->{NAME} *r)\n{\n"; + + # declare any internal pointers we need + foreach my $e (@{$fn->{DATA}}) { + if (util::need_wire_pointer($e)) { + pidl "\tuint32_t _ptr_$e->{NAME};\n"; + } + } + + pidl "\n\tif (!(flags & NDR_IN)) goto ndr_out;\n\n"; + + # 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->{DATA}}) { + if (util::has_property($e, "out")) { + pidl "\tZERO_STRUCT(r->out);\n\n"; + last; + } + } + + foreach my $e (@{$fn->{DATA}}) { + 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); + } + } + + pidl "\nndr_out:\n"; + pidl "\tif (!(flags & NDR_OUT)) goto done;\n\n"; + foreach my $e (@{$fn->{DATA}}) { + if (util::has_property($e, "out")) { + ParseFunctionElementPull($e, "out"); + } + } + + if ($fn->{RETURN_TYPE} && $fn->{RETURN_TYPE} ne "void") { + pidl "\tNDR_CHECK(ndr_pull_$fn->{RETURN_TYPE}(ndr, &r->out.result));\n"; + } + + pidl "\ndone:\n"; + pidl "\n\treturn NT_STATUS_OK;\n}\n\n"; +} + +##################################################################### +# produce a function call table +sub FunctionTable($) +{ + my($interface) = shift; + my($data) = $interface->{DATA}; + my $count = 0; + my $uname = uc $interface->{NAME}; + + foreach my $d (@{$data}) { + if ($d->{TYPE} eq "FUNCTION") { $count++; } + } + + if ($count == 0) { + return; + } + + pidl "static const struct dcerpc_interface_call $interface->{NAME}\_calls[] = {\n"; + foreach my $d (@{$data}) { + if ($d->{TYPE} eq "FUNCTION") { + pidl "\t{\n"; + pidl "\t\t\"$d->{NAME}\",\n"; + pidl "\t\tsizeof(struct $d->{NAME}),\n"; + pidl "\t\t(ndr_push_flags_fn_t) ndr_push_$d->{NAME},\n"; + pidl "\t\t(ndr_pull_flags_fn_t) ndr_pull_$d->{NAME},\n"; + pidl "\t\t(ndr_print_function_t) ndr_print_$d->{NAME}\n"; + pidl "\t},\n"; + } + } + pidl "\t{ NULL, 0, NULL, NULL }\n};\n\n"; + + my $endpoints; + + if (! defined $if_endpoints) { + $if_endpoints = $interface->{NAME}; + } + + my @e = split / /, $if_endpoints; + my $endpoint_count = $#e + 1; + + pidl "static const char * const $interface->{NAME}\_endpoint_strings[] = {\n\t"; + for (my $i=0; $i < $#e; $i++) { + pidl "\"$e[$i]\", "; + } + pidl "\"$e[$#e]\"\n"; + pidl "};\n\n"; + + pidl "static const struct dcerpc_endpoint_list $interface->{NAME}\_endpoints = {\n"; + pidl "\t$endpoint_count, $interface->{NAME}\_endpoint_strings\n"; + pidl "};\n\n"; + + pidl "\nconst struct dcerpc_interface_table dcerpc_table_$interface->{NAME} = {\n"; + pidl "\t\"$interface->{NAME}\",\n"; + pidl "\tDCERPC_$uname\_UUID,\n"; + pidl "\tDCERPC_$uname\_VERSION,\n"; + pidl "\t$count,\n"; + pidl "\t$interface->{NAME}\_calls,\n"; + pidl "\t&$interface->{NAME}\_endpoints\n"; + pidl "};\n\n"; +} + + +##################################################################### +# parse the interface definitions +sub ParseInterface($) +{ + my($interface) = shift; + my($data) = $interface->{DATA}; + + foreach my $d (@{$data}) { + if ($d->{TYPE} eq "TYPEDEF") { + $structs{$d->{NAME}} = $d; + } + } + + + + foreach my $d (@{$data}) { + ($d->{TYPE} eq "TYPEDEF") && + ParseTypedefPush($d); + ($d->{TYPE} eq "FUNCTION") && + ParseFunctionPush($d); + } + foreach my $d (@{$data}) { + ($d->{TYPE} eq "TYPEDEF") && + ParseTypedefPull($d); + ($d->{TYPE} eq "FUNCTION") && + ParseFunctionPull($d); + } + foreach my $d (@{$data}) { + if ($d->{TYPE} eq "TYPEDEF" && + !util::has_property($d->{DATA}, "noprint")) { + ParseTypedefPrint($d); + } + if ($d->{TYPE} eq "FUNCTION" && + !util::has_property($d, "noprint")) { + ParseFunctionPrint($d); + } + } + + FunctionTable($interface); + +} + +sub NeededFunction($) +{ + my $fn = shift; + $needed{"pull_$fn->{NAME}"} = 1; + $needed{"push_$fn->{NAME}"} = 1; + foreach my $e (@{$fn->{DATA}}) { + $e->{PARENT} = $fn; + $needed{"pull_$e->{TYPE}"} = 1; + $needed{"push_$e->{TYPE}"} = 1; + } +} + +sub NeededTypedef($) +{ + my $t = shift; + if (util::has_property($t->{DATA}, "public")) { + $needed{"pull_$t->{NAME}"} = 1; + $needed{"push_$t->{NAME}"} = 1; + } + if ($t->{DATA}->{TYPE} eq "STRUCT") { + for my $e (@{$t->{DATA}->{ELEMENTS}}) { + $e->{PARENT} = $t->{DATA}; + if ($needed{"pull_$t->{NAME}"}) { + $needed{"pull_$e->{TYPE}"} = 1; + } + if ($needed{"push_$t->{NAME}"}) { + $needed{"push_$e->{TYPE}"} = 1; + } + } + } + if ($t->{DATA}->{TYPE} eq "UNION") { + for my $e (@{$t->{DATA}->{DATA}}) { + $e->{PARENT} = $t->{DATA}; + if ($e->{TYPE} eq "UNION_ELEMENT") { + if ($needed{"pull_$t->{NAME}"}) { + $needed{"pull_$e->{DATA}->{TYPE}"} = 1; + } + if ($needed{"push_$t->{NAME}"}) { + $needed{"push_$e->{DATA}->{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); + } +} + +##################################################################### +# parse the interface definitions +sub ModuleHeader($) +{ + my($h) = shift; + + $if_uuid = $h->{PROPERTIES}->{uuid}; + $if_version = $h->{PROPERTIES}->{version}; + $if_endpoints = $h->{PROPERTIES}->{endpoints}; +} + +##################################################################### +# parse a parsed IDL structure back into an IDL file +sub Parse($$) +{ + my($idl) = shift; + my($filename) = shift; + + open(OUT, ">$filename") || die "can't open $filename"; + + pidl "/* parser auto-generated by pidl */\n\n"; + pidl "#include \"includes.h\"\n\n"; + foreach my $x (@{$idl}) { + ($x->{TYPE} eq "MODULEHEADER") && + ModuleHeader($x); + + if ($x->{TYPE} eq "INTERFACE") { + BuildNeeded($x); + ParseInterface($x); + } + } + + pidl IdlClient::Parse($idl); + + close(OUT); +} + +1; diff --git a/SAMBA_3_2_MERGE/source/build/pidl/pidl.pl b/SAMBA_3_2_MERGE/source/build/pidl/pidl.pl new file mode 100755 index 00000000000..1c122932ba4 --- /dev/null +++ b/SAMBA_3_2_MERGE/source/build/pidl/pidl.pl @@ -0,0 +1,166 @@ +#!/usr/bin/perl -w + +################################################### +# package to parse IDL files and generate code for +# rpc functions in Samba +# Copyright tridge@samba.org 2000-2003 +# released under the GNU GPL + +use strict; + +use FindBin qw($RealBin); +use lib "$RealBin"; +use lib "$RealBin/lib"; +use Getopt::Long; +use File::Basename; +use idl; +use dump; +use header; +use server; +use parser; +use eparser; +use validator; +use util; +use template; + +my($opt_help) = 0; +my($opt_parse) = 0; +my($opt_dump) = 0; +my($opt_diff) = 0; +my($opt_header) = 0; +my($opt_template) = 0; +my($opt_server) = 0; +my($opt_parser) = 0; +my($opt_eparser) = 0; +my($opt_keep) = 0; +my($opt_output); + +my $idl_parser = new idl; + +##################################################################### +# parse an IDL file returning a structure containing all the data +sub IdlParse($) +{ + my $filename = shift; + my $idl = $idl_parser->parse_idl($filename); + util::CleanData($idl); + return $idl; +} + + +######################################### +# display help text +sub ShowHelp() +{ + print " + perl IDL parser and code generator + Copyright (C) tridge\@samba.org + + Usage: pidl.pl [options] + + Options: + --help this help page + --output OUTNAME put output in OUTNAME.* + --parse parse a idl file to a .pidl file + --dump dump a pidl file back to idl + --header create a C header file + --parser create a C parser + --server create server boilerplate + --template print a template for a pipe + --eparser create an ethereal parser + --diff run diff on the idl and dumped output + --keep keep the .pidl file + \n"; + exit(0); +} + +# main program +GetOptions ( + 'help|h|?' => \$opt_help, + 'output=s' => \$opt_output, + 'parse' => \$opt_parse, + 'dump' => \$opt_dump, + 'header' => \$opt_header, + 'server' => \$opt_server, + 'template' => \$opt_template, + 'parser' => \$opt_parser, + 'eparser' => \$opt_eparser, + 'diff' => \$opt_diff, + 'keep' => \$opt_keep + ); + +if ($opt_help) { + ShowHelp(); + exit(0); +} + +sub process_file($) +{ + my $idl_file = shift; + my $output; + my $pidl; + + my $basename = basename($idl_file, ".idl"); + + if (!defined($opt_output)) { + $output = $idl_file; + } else { + $output = $opt_output . $basename; + } + + my($pidl_file) = util::ChangeExtension($output, ".pidl"); + + print "Compiling $idl_file\n"; + + if ($opt_parse) { + $pidl = IdlParse($idl_file); + defined $pidl || die "Failed to parse $idl_file"; + IdlValidator::Validate($pidl); + if ($opt_keep && !util::SaveStructure($pidl_file, $pidl)) { + die "Failed to save $pidl_file\n"; + } + } else { + $pidl = util::LoadStructure($pidl_file); + defined $pidl || die "Failed to load $pidl_file - maybe you need --parse\n"; + } + + if ($opt_dump) { + print IdlDump::Dump($pidl); + } + + if ($opt_header) { + my($header) = util::ChangeExtension($output, ".h"); + util::FileSave($header, IdlHeader::Parse($pidl)); + } + + if ($opt_server) { + my($server) = util::ChangeExtension($output, "_s.c"); + util::FileSave($server, IdlServer::Parse($pidl)); + } + + if ($opt_parser) { + my($parser) = util::ChangeExtension($output, ".c"); + IdlParser::Parse($pidl, $parser); + } + + if ($opt_eparser) { + my($parser) = dirname($output) . "/packet-dcerpc-$basename.c"; + IdlEParser::Parse($pidl, $parser); + } + + if ($opt_diff) { + my($tempfile) = util::ChangeExtension($output, ".tmp"); + util::FileSave($tempfile, IdlDump::Dump($pidl)); + system("diff -wu $idl_file $tempfile"); + unlink($tempfile); + } + + if ($opt_template) { + print IdlTemplate::Parse($pidl); + } +} + + +foreach my $filename (@ARGV) { + process_file($filename); +} diff --git a/SAMBA_3_2_MERGE/source/build/pidl/server.pm b/SAMBA_3_2_MERGE/source/build/pidl/server.pm new file mode 100644 index 00000000000..72ebc22379f --- /dev/null +++ b/SAMBA_3_2_MERGE/source/build/pidl/server.pm @@ -0,0 +1,224 @@ +################################################### +# server boilerplate generator +# Copyright tridge@samba.org 2003 +# Copyright metze@samba.org 2004 +# released under the GNU GPL + +package IdlServer; + +use strict; + +my($res); + +sub pidl($) +{ + $res .= shift; +} + + +##################################################### +# generate the switch statement for function dispatch +sub gen_dispatch_switch($) +{ + my $data = shift; + + my $count = 0; + foreach my $d (@{$data}) { + next if ($d->{TYPE} ne "FUNCTION"); + + pidl "\tcase $count: {\n"; + pidl "\t\tstruct $d->{NAME} *r2 = r;\n"; + pidl "\t\tif (DEBUGLEVEL > 10) {\n"; + pidl "\t\t\tNDR_PRINT_IN_DEBUG($d->{NAME}, r2);\n"; + pidl "\t\t}\n"; + if ($d->{RETURN_TYPE} && $d->{RETURN_TYPE} ne "void") { + pidl "\t\tr2->out.result = $d->{NAME}(dce_call, mem_ctx, r2);\n"; + } else { + pidl "\t\t$d->{NAME}(dce_call, mem_ctx, r2);\n"; + } + pidl "\t\tif (DEBUGLEVEL > 10 && dce_call->fault_code == 0) {\n"; + pidl "\t\t\tNDR_PRINT_OUT_DEBUG($d->{NAME}, r2);\n"; + pidl "\t\t}\n"; + pidl "\t\tif (dce_call->fault_code != 0) {\n"; + pidl "\t\t\tDEBUG(2,(\"dcerpc_fault 0x%x in $d->{NAME}\\n\", dce_call->fault_code));\n"; + pidl "\t\t}\n"; + pidl "\t\tbreak;\n\t}\n"; + $count++; + } +} + + +##################################################################### +# produce boilerplate code for a interface +sub Boilerplate_Iface($) +{ + my($interface) = shift; + my($data) = $interface->{DATA}; + my $count = 0; + my $name = $interface->{NAME}; + my $uname = uc $name; + + foreach my $d (@{$data}) { + if ($d->{TYPE} eq "FUNCTION") { $count++; } + } + + if ($count == 0) { + return; + } + + pidl " +static NTSTATUS $name\__op_bind(struct dcesrv_call_state *dce_call, const struct dcesrv_interface *iface) +{ +#ifdef DCESRV_INTERFACE_$uname\_BIND + return DCESRV_INTERFACE_$uname\_BIND(dce_call,iface); +#else + return NT_STATUS_OK; +#endif +} + +static void $name\__op_unbind(struct dcesrv_connection *dce_conn, const struct dcesrv_interface *iface) +{ +#ifdef DCESRV_INTERFACE_$uname\_UNBIND + DCESRV_INTERFACE_$uname\_UNBIND(dce_conn,iface); +#else + return; +#endif +} + +static NTSTATUS $name\__op_dispatch(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, void *r) +{ + uint16 opnum = dce_call->pkt.u.request.opnum; + + dce_call->fault_code = 0; + + switch (opnum) { +"; + gen_dispatch_switch($data); + +pidl " + default: + dce_call->fault_code = DCERPC_FAULT_OP_RNG_ERROR; + break; + } + + if (dce_call->fault_code != 0) { + return NT_STATUS_NET_WRITE_FAULT; + } + return NT_STATUS_OK; +} + +static const struct dcesrv_interface $name\_interface = { + &dcerpc_table_$name, + $name\__op_bind, + $name\__op_unbind, + $name\__op_dispatch +}; + +"; +} + +##################################################################### +# produce boilerplate code for an endpoint server +sub Boilerplate_Ep_Server($) +{ + my($interface) = shift; + my($data) = $interface->{DATA}; + my $count = 0; + my $name = $interface->{NAME}; + my $uname = uc $name; + + foreach my $d (@{$data}) { + if ($d->{TYPE} eq "FUNCTION") { $count++; } + } + + if ($count == 0) { + return; + } + + pidl " +static NTSTATUS $name\__op_init_server(struct dcesrv_context *dce_ctx, const struct dcesrv_endpoint_server *ep_server) +{ + int i; + + for (i=0;i<$name\_interface.ndr->endpoints->count;i++) { + NTSTATUS ret; + const char *name = $name\_interface.ndr->endpoints->names[i]; + + ret = dcesrv_interface_register(dce_ctx, name, &$name\_interface, NULL); + if (!NT_STATUS_IS_OK(ret)) { + DEBUG(1,(\"$name\_op_init_server: failed to register endpoint \'%s\'\\n\",name)); + return ret; + } + } + + return NT_STATUS_OK; +} + +static BOOL $name\__op_interface_by_uuid(struct dcesrv_interface *iface, const char *uuid, uint32 if_version) +{ + if ($name\_interface.ndr->if_version == if_version && + strcmp($name\_interface.ndr->uuid, uuid)==0) { + memcpy(iface,&$name\_interface, sizeof(*iface)); + return True; + } + + return False; +} + +static BOOL $name\__op_interface_by_name(struct dcesrv_interface *iface, const char *name) +{ + if (strcmp($name\_interface.ndr->name, name)==0) { + memcpy(iface,&$name\_interface, sizeof(*iface)); + return True; + } + + return False; +} + +NTSTATUS dcerpc_$name\_init(void) +{ + NTSTATUS ret; + struct dcesrv_endpoint_server ep_server; + + /* fill in our name */ + ep_server.name = \"$name\"; + + /* fill in all the operations */ + ep_server.init_server = $name\__op_init_server; + + ep_server.interface_by_uuid = $name\__op_interface_by_uuid; + ep_server.interface_by_name = $name\__op_interface_by_name; + + /* register ourselves with the DCERPC subsystem. */ + ret = register_backend(\"dcerpc\", &ep_server); + + if (!NT_STATUS_IS_OK(ret)) { + DEBUG(0,(\"Failed to register \'$name\' endpoint server!\\n\")); + return ret; + } + + return ret; +} + +"; +} + + +##################################################################### +# parse a parsed IDL structure back into an IDL file +sub Parse($) +{ + my($idl) = shift; + $res = "/* dcerpc server boilerplate generated by pidl */\n\n"; + foreach my $x (@{$idl}) { + if ($x->{TYPE} eq "INTERFACE") { + Boilerplate_Iface($x); + Boilerplate_Ep_Server($x); + } + } + + return $res; +} + +1; + diff --git a/SAMBA_3_2_MERGE/source/build/pidl/tables.pl b/SAMBA_3_2_MERGE/source/build/pidl/tables.pl new file mode 100755 index 00000000000..5f760d4403f --- /dev/null +++ b/SAMBA_3_2_MERGE/source/build/pidl/tables.pl @@ -0,0 +1,97 @@ +#!/usr/bin/perl -w + +################################################### +# package to produce a table of all idl parsers +# Copyright tridge@samba.org 2003 +# released under the GNU GPL + +use strict; + +use Getopt::Long; +use File::Basename; + +my($opt_output); +my($opt_help) = 0; + + +######################################### +# display help text +sub ShowHelp() +{ + print " + perl IDL table generator + Copyright (C) tridge\@samba.org + + Usage: tables.pl [options] + + Options: + --output OUTNAME put output in OUTNAME.* + \n"; + exit(0); +} + +# main program +GetOptions ( + 'help|h|?' => \$opt_help, + 'output=s' => \$opt_output, + ); + +if ($opt_help) { + ShowHelp(); + exit(0); +} + + +################################### +# extract table entries from 1 file +sub process_file($) +{ + my $filename = shift; + open(FILE, $filename) || die "unable to open $filename\n"; + + print TABLEH "#include \"$filename\"\n"; + + while (my $line = ) { + if ($line =~ /extern const struct dcerpc_interface_table (\w+);/) { + print TABLEC "\t&$1,\n"; + } + } + + close(FILE); +} + +print "Creating $opt_output.[ch]\n"; +open(TABLEH, ">$opt_output.h") || die "failed to open $opt_output.h\n"; +open(TABLEC, ">$opt_output.c") || die "failed to open $opt_output.c\n"; + +#include "includes.h" + +#define NDR_BASE_MARSHALL_SIZE 1024 + +print TABLEC " +#include \"includes.h\" + +/* + generated by pidl IDL table generator +*/ +const struct dcerpc_interface_table * const dcerpc_pipes[] = { +"; + +print TABLEH " +/* + table headers generated by pidl IDL table generator +*/ + +extern const struct dcerpc_interface_table * const dcerpc_pipes[]; + +"; + +foreach my $filename (@ARGV) { + process_file($filename); +} + + +print TABLEC "\tNULL\n};\n"; + +close(TABLEH); +close(TABLEC); diff --git a/SAMBA_3_2_MERGE/source/build/pidl/template.pm b/SAMBA_3_2_MERGE/source/build/pidl/template.pm new file mode 100644 index 00000000000..2942c6f7131 --- /dev/null +++ b/SAMBA_3_2_MERGE/source/build/pidl/template.pm @@ -0,0 +1,86 @@ +################################################### +# server template function generator +# Copyright tridge@samba.org 2003 +# released under the GNU GPL + +package IdlTemplate; + +use strict; + +my($res); + +##################################################################### +# produce boilerplate code for a interface +sub Template($) +{ + my($interface) = shift; + my($data) = $interface->{DATA}; + my $name = $interface->{NAME}; + + $res .= +"/* + Unix SMB/CIFS implementation. + + endpoint server for the $name pipe + + Copyright (C) YOUR NAME HERE XXXX + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include \"includes.h\" + +"; + + foreach my $d (@{$data}) { + if ($d->{TYPE} eq "FUNCTION") { + my $fname = $d->{NAME}; + $res .= +" +/* + $fname +*/ +static $d->{RETURN_TYPE} $fname(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, + struct $fname *r) +{ + DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR); +} + +"; + } + } + + $res .= +" +/* include the generated boilerplate */ +#include \"librpc/gen_ndr/ndr_$name\_s.c\" +" +} + + +##################################################################### +# parse a parsed IDL structure back into an IDL file +sub Parse($) +{ + my($idl) = shift; + $res = ""; + foreach my $x (@{$idl}) { + ($x->{TYPE} eq "INTERFACE") && + Template($x); + } + return $res; +} + +1; diff --git a/SAMBA_3_2_MERGE/source/build/pidl/util.pm b/SAMBA_3_2_MERGE/source/build/pidl/util.pm new file mode 100644 index 00000000000..f822222b454 --- /dev/null +++ b/SAMBA_3_2_MERGE/source/build/pidl/util.pm @@ -0,0 +1,379 @@ +################################################### +# utility functions to support pidl +# Copyright tridge@samba.org 2000 +# released under the GNU GPL +package util; + +##################################################################### +# load a data structure from a file (as saved with SaveStructure) +sub LoadStructure($) +{ + my $f = shift; + my $contents = FileLoad($f); + defined $contents || return undef; + return eval "$contents"; +} + +use strict; + +##################################################################### +# flatten an array of arrays into a single array +sub FlattenArray2($) +{ + my $a = shift; + my @b; + for my $d (@{$a}) { + for my $d1 (@{$d}) { + push(@b, $d1); + } + } + return \@b; +} + +##################################################################### +# flatten an array of arrays into a single array +sub FlattenArray($) +{ + my $a = shift; + my @b; + for my $d (@{$a}) { + for my $d1 (@{$d}) { + push(@b, $d1); + } + } + return \@b; +} + +##################################################################### +# flatten an array of hashes into a single hash +sub FlattenHash($) +{ + my $a = shift; + my %b; + for my $d (@{$a}) { + for my $k (keys %{$d}) { + $b{$k} = $d->{$k}; + } + } + return \%b; +} + + +##################################################################### +# traverse a perl data structure removing any empty arrays or +# hashes and any hash elements that map to undef +sub CleanData($) +{ + sub CleanData($); + my($v) = shift; + if (ref($v) eq "ARRAY") { + foreach my $i (0 .. $#{$v}) { + CleanData($v->[$i]); + if (ref($v->[$i]) eq "ARRAY" && $#{$v->[$i]}==-1) { + $v->[$i] = undef; + next; + } + } + # this removes any undefined elements from the array + @{$v} = grep { defined $_ } @{$v}; + } elsif (ref($v) eq "HASH") { + foreach my $x (keys %{$v}) { + CleanData($v->{$x}); + if (!defined $v->{$x}) { delete($v->{$x}); next; } + if (ref($v->{$x}) eq "ARRAY" && $#{$v->{$x}}==-1) { delete($v->{$x}); next; } + } + } +} + + +##################################################################### +# return the modification time of a file +sub FileModtime($) +{ + my($filename) = shift; + return (stat($filename))[9]; +} + + +##################################################################### +# read a file into a string +sub FileLoad($) +{ + my($filename) = shift; + local(*INPUTFILE); + open(INPUTFILE, $filename) || return undef; + my($saved_delim) = $/; + undef $/; + my($data) = ; + close(INPUTFILE); + $/ = $saved_delim; + return $data; +} + +##################################################################### +# write a string into a file +sub FileSave($$) +{ + my($filename) = shift; + my($v) = shift; + local(*FILE); + open(FILE, ">$filename") || die "can't open $filename"; + print FILE $v; + close(FILE); +} + +##################################################################### +# return a filename with a changed extension +sub ChangeExtension($$) +{ + my($fname) = shift; + my($ext) = shift; + if ($fname =~ /^(.*)\.(.*?)$/) { + return "$1$ext"; + } + return "$fname$ext"; +} + +##################################################################### +# a dumper wrapper to prevent dependence on the Data::Dumper module +# unless we actually need it +sub MyDumper($) +{ + require Data::Dumper; + my $s = shift; + return Data::Dumper::Dumper($s); +} + +##################################################################### +# save a data structure into a file +sub SaveStructure($$) +{ + my($filename) = shift; + my($v) = shift; + FileSave($filename, MyDumper($v)); +} + +##################################################################### +# see if a pidl property list contains a give property +sub has_property($$) +{ + my($e) = shift; + my($p) = shift; + + if (!defined $e->{PROPERTIES}) { + return undef; + } + + return $e->{PROPERTIES}->{$p}; +} + + +sub is_scalar_type($) +{ + my($type) = shift; + + if ($type =~ /^u?int\d+/) { + return 1; + } + if ($type =~ /char|short|long|NTTIME| + time_t|error_status_t|boolean32|unsigned32| + HYPER_T|wchar_t|DATA_BLOB/x) { + return 1; + } + + return 0; +} + +# return the NDR alignment for a type +sub type_align($) +{ + my($e) = shift; + my $type = $e->{TYPE}; + + if (need_wire_pointer($e)) { + return 4; + } + + return 4, if ($type eq "uint32"); + return 4, if ($type eq "long"); + return 2, if ($type eq "short"); + return 1, if ($type eq "char"); + return 1, if ($type eq "uint8"); + return 2, if ($type eq "uint16"); + return 4, if ($type eq "NTTIME"); + return 4, if ($type eq "time_t"); + return 8, if ($type eq "HYPER_T"); + return 2, if ($type eq "wchar_t"); + return 4, if ($type eq "DATA_BLOB"); + + # it must be an external type - all we can do is guess + return 4; +} + +# this is used to determine if the ndr push/pull functions will need +# a ndr_flags field to split by buffers/scalars +sub is_builtin_type($) +{ + my($type) = shift; + + return 1, if (is_scalar_type($type)); + + return 0; +} + +# determine if an element needs a reference pointer on the wire +# in its NDR representation +sub need_wire_pointer($) +{ + my $e = shift; + if ($e->{POINTERS} && + !has_property($e, "ref")) { + return $e->{POINTERS}; + } + return undef; +} + +# determine if an element is a pass-by-reference structure +sub is_ref_struct($) +{ + my $e = shift; + if (!is_scalar_type($e->{TYPE}) && + has_property($e, "ref")) { + return 1; + } + return 0; +} + +# determine if an element is a pure scalar. pure scalars do not +# have a "buffers" section in NDR +sub is_pure_scalar($) +{ + my $e = shift; + if (has_property($e, "ref")) { + return 1; + } + if (is_scalar_type($e->{TYPE}) && + !$e->{POINTERS} && + !array_size($e)) { + return 1; + } + return 0; +} + +# determine the array size (size_is() or ARRAY_LEN) +sub array_size($) +{ + my $e = shift; + my $size = has_property($e, "size_is"); + if ($size) { + return $size; + } + $size = $e->{ARRAY_LEN}; + if ($size) { + return $size; + } + return undef; +} + +# see if a variable needs to be allocated by the NDR subsystem on pull +sub need_alloc($) +{ + my $e = shift; + + if (has_property($e, "ref")) { + return 0; + } + + if ($e->{POINTERS} || array_size($e)) { + return 1; + } + + return 0; +} + +# 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; + + if ($e->{TYPE} =~ "string") { + return ""; + } + + if (is_scalar_type($e->{TYPE}) && + $e->{POINTERS}) { + return "*"; + } + if (!is_scalar_type($e->{TYPE}) && + !$e->{POINTERS} && + !array_size($e)) { + return "&"; + } + return ""; +} + + +# determine the C prefix used to refer to a variable when passing to a pull +# return '&' or '' +sub c_pull_prefix($) +{ + my $e = shift; + + if (!$e->{POINTERS} && !array_size($e)) { + return "&"; + } + + if ($e->{TYPE} =~ "string") { + return "&"; + } + + return ""; +} + +# determine if an element has a direct buffers component +sub has_direct_buffers($) +{ + my $e = shift; + if ($e->{POINTERS} || array_size($e)) { + return 1; + } + return 0; +} + +# return 1 if the string is a C constant +sub is_constant($) +{ + my $s = shift; + if ($s =~ /^\d/) { + return 1; + } + return 0; +} + +# return 1 if this is a fixed array +sub is_fixed_array($) +{ + my $e = shift; + my $len = $e->{"ARRAY_LEN"}; + if (defined $len && is_constant($len)) { + return 1; + } + return 0; +} + +# return 1 if this is a inline array +sub is_inline_array($) +{ + my $e = shift; + my $len = $e->{"ARRAY_LEN"}; + if (is_fixed_array($e) || + defined $len && $len ne "*") { + return 1; + } + return 0; +} + +1; + diff --git a/SAMBA_3_2_MERGE/source/build/pidl/validator.pm b/SAMBA_3_2_MERGE/source/build/pidl/validator.pm new file mode 100644 index 00000000000..ee1c33ef4cf --- /dev/null +++ b/SAMBA_3_2_MERGE/source/build/pidl/validator.pm @@ -0,0 +1,138 @@ +################################################### +# check that a parsed IDL file is valid +# Copyright tridge@samba.org 2003 +# released under the GNU GPL + +package IdlValidator; + +use strict; + +##################################################################### +# signal a fatal validation error +sub fatal($) +{ + my $s = shift; + print "$s\n"; + die "IDL is not valid\n"; +} + +sub el_name($) +{ + my $e = shift; + + if ($e->{PARENT} && $e->{PARENT}->{NAME}) { + return "$e->{PARENT}->{NAME}.$e->{NAME}"; + } + + if ($e->{PARENT} && $e->{PARENT}->{PARENT}->{NAME}) { + return "$e->{PARENT}->{PARENT}->{NAME}.$e->{NAME}"; + } + + if ($e->{PARENT}) { + return "$e->{PARENT}->{NAME}.$e->{NAME}"; + } + return $e->{NAME}; +} + +##################################################################### +# parse a struct +sub ValidElement($) +{ + my $e = shift; + if ($e->{POINTERS} && $e->{POINTERS} > 1) { + fatal(el_name($e) . " : pidl cannot handle multiple pointer levels. Use a sub-structure containing a pointer instead\n"); + } + + if ($e->{POINTERS} && $e->{ARRAY_LEN}) { + fatal(el_name($e) . " : pidl cannot handle pointers to arrays. Use a substructure instead\n"); + } +} + +##################################################################### +# parse a struct +sub ValidStruct($) +{ + my($struct) = shift; + + foreach my $e (@{$struct->{ELEMENTS}}) { + $e->{PARENT} = $struct; + ValidElement($e); + } +} + + +##################################################################### +# parse a union +sub ValidUnion($) +{ + my($union) = shift; + foreach my $e (@{$union->{DATA}}) { + $e->{PARENT} = $union; + ValidElement($e); + } +} + +##################################################################### +# parse a typedef +sub ValidTypedef($) +{ + my($typedef) = shift; + my $data = $typedef->{DATA}; + + $data->{PARENT} = $typedef; + + if (ref($data) eq "HASH") { + if ($data->{TYPE} eq "STRUCT") { + ValidStruct($data); + } + + if ($data->{TYPE} eq "UNION") { + ValidUnion($data); + } + } +} + +##################################################################### +# parse a function +sub ValidFunction($) +{ + my($fn) = shift; + + foreach my $e (@{$fn->{DATA}}) { + $e->{PARENT} = $fn; + if (util::has_property($e, "ref") && !$e->{POINTERS}) { + fatal "[ref] variables must be pointers ($fn->{NAME}/$e->{NAME})\n"; + } + ValidElement($e); + } +} + +##################################################################### +# parse the interface definitions +sub ValidInterface($) +{ + my($interface) = shift; + my($data) = $interface->{DATA}; + + foreach my $d (@{$data}) { + ($d->{TYPE} eq "TYPEDEF") && + ValidTypedef($d); + ($d->{TYPE} eq "FUNCTION") && + ValidFunction($d); + } + +} + +##################################################################### +# parse a parsed IDL into a C header +sub Validate($) +{ + my($idl) = shift; + + foreach my $x (@{$idl}) { + ($x->{TYPE} eq "INTERFACE") && + ValidInterface($x); + } +} + +1; -- 2.11.4.GIT