diff options
author | Jelmer Vernooij <jelmer@samba.org> | 2008-09-17 17:12:27 +0200 |
---|---|---|
committer | Jelmer Vernooij <jelmer@samba.org> | 2008-09-17 17:12:27 +0200 |
commit | 79190992b3820cd028c961c48bdea9b35baf13c9 (patch) | |
tree | 0de851669d98f04e947d20349d96723462cd1eb0 /source4/pidl/lib/Parse/Pidl/Samba4/NDR | |
parent | 3b5330e9094ecf0be94d3dbea744de140ec55e19 (diff) | |
download | samba-79190992b3820cd028c961c48bdea9b35baf13c9.tar.gz samba-79190992b3820cd028c961c48bdea9b35baf13c9.tar.bz2 samba-79190992b3820cd028c961c48bdea9b35baf13c9.zip |
Move pidl to top-level directory.
Diffstat (limited to 'source4/pidl/lib/Parse/Pidl/Samba4/NDR')
-rw-r--r-- | source4/pidl/lib/Parse/Pidl/Samba4/NDR/Client.pm | 156 | ||||
-rw-r--r-- | source4/pidl/lib/Parse/Pidl/Samba4/NDR/Parser.pm | 2695 | ||||
-rw-r--r-- | source4/pidl/lib/Parse/Pidl/Samba4/NDR/Server.pm | 328 |
3 files changed, 0 insertions, 3179 deletions
diff --git a/source4/pidl/lib/Parse/Pidl/Samba4/NDR/Client.pm b/source4/pidl/lib/Parse/Pidl/Samba4/NDR/Client.pm deleted file mode 100644 index f8209be654..0000000000 --- a/source4/pidl/lib/Parse/Pidl/Samba4/NDR/Client.pm +++ /dev/null @@ -1,156 +0,0 @@ -################################################### -# client calls generator -# Copyright tridge@samba.org 2003 -# Copyright jelmer@samba.org 2005-2006 -# released under the GNU GPL - -package Parse::Pidl::Samba4::NDR::Client; - -use Parse::Pidl::Samba4 qw(choose_header is_intree); -use Parse::Pidl::Util qw(has_property); - -use vars qw($VERSION); -$VERSION = '0.01'; - -use strict; - -my($res,$res_hdr); - -sub ParseFunctionSend($$$) -{ - my ($interface, $fn, $name) = @_; - my $uname = uc $name; - - my $proto = "struct rpc_request *dcerpc_$name\_send(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, struct $name *r)"; - - $res_hdr .= "\n$proto;\n"; - - $res .= "$proto\n{\n"; - - if (has_property($fn, "todo")) { - $res .= "\treturn NULL;\n"; - } else { - $res .= " - if (p->conn->flags & DCERPC_DEBUG_PRINT_IN) { - NDR_PRINT_IN_DEBUG($name, r); - } - - return dcerpc_ndr_request_send(p, NULL, &ndr_table_$interface->{NAME}, NDR_$uname, mem_ctx, r); -"; - } - - $res .= "}\n\n"; -} - -sub ParseFunctionSync($$$) -{ - my ($interface, $fn, $name) = @_; - - my $proto = "NTSTATUS dcerpc_$name(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, struct $name *r)"; - - $res_hdr .= "\n$proto;\n"; - $res .= "$proto\n{\n"; - - if (has_property($fn, "todo")) { - $res .= "\treturn NT_STATUS_NOT_IMPLEMENTED;\n"; - } else { - $res .= " - struct rpc_request *req; - NTSTATUS status; - - req = dcerpc_$name\_send(p, mem_ctx, r); - if (req == NULL) return NT_STATUS_NO_MEMORY; - - status = dcerpc_ndr_request_recv(req); - - if (NT_STATUS_IS_OK(status) && (p->conn->flags & DCERPC_DEBUG_PRINT_OUT)) { - NDR_PRINT_OUT_DEBUG($name, r); - } -"; - - if (defined($fn->{RETURN_TYPE}) and $fn->{RETURN_TYPE} eq "NTSTATUS") { - $res .= "\tif (NT_STATUS_IS_OK(status)) status = r->out.result;\n"; - } - $res .= -" - return status; -"; - } - - $res .= "}\n\n"; -} - -##################################################################### -# parse a function -sub ParseFunction($$) -{ - my ($interface, $fn) = @_; - - ParseFunctionSend($interface, $fn, $fn->{NAME}); - ParseFunctionSync($interface, $fn, $fn->{NAME}); -} - -my %done; - -##################################################################### -# parse the interface definitions -sub ParseInterface($) -{ - my($interface) = shift; - - $res_hdr .= "#ifndef _HEADER_RPC_$interface->{NAME}\n"; - $res_hdr .= "#define _HEADER_RPC_$interface->{NAME}\n\n"; - - if (defined $interface->{PROPERTIES}->{uuid}) { - $res_hdr .= "extern const struct ndr_interface_table ndr_table_$interface->{NAME};\n"; - } - - $res .= "/* $interface->{NAME} - client functions generated by pidl */\n\n"; - - foreach my $fn (@{$interface->{FUNCTIONS}}) { - next if not defined($fn->{OPNUM}); - next if defined($done{$fn->{NAME}}); - ParseFunction($interface, $fn); - $done{$fn->{NAME}} = 1; - } - - $res_hdr .= "#endif /* _HEADER_RPC_$interface->{NAME} */\n"; - - return $res; -} - -sub Parse($$$$) -{ - my($ndr,$header,$ndr_header,$client_header) = @_; - - $res = ""; - $res_hdr = ""; - - $res .= "/* client functions auto-generated by pidl */\n"; - $res .= "\n"; - if (is_intree()) { - $res .= "#include \"includes.h\"\n"; - } else { - $res .= "#define _GNU_SOURCE\n"; - $res .= "#include <stdio.h>\n"; - $res .= "#include <stdbool.h>\n"; - $res .= "#include <stdlib.h>\n"; - $res .= "#include <stdint.h>\n"; - $res .= "#include <stdarg.h>\n"; - $res .= "#include <core/ntstatus.h>\n"; - } - $res .= "#include \"$ndr_header\"\n"; - $res .= "#include \"$client_header\"\n"; - $res .= "\n"; - - $res_hdr .= choose_header("librpc/rpc/dcerpc.h", "dcerpc.h")."\n"; - $res_hdr .= "#include \"$header\"\n"; - - foreach my $x (@{$ndr}) { - ($x->{TYPE} eq "INTERFACE") && ParseInterface($x); - } - - return ($res,$res_hdr); -} - -1; diff --git a/source4/pidl/lib/Parse/Pidl/Samba4/NDR/Parser.pm b/source4/pidl/lib/Parse/Pidl/Samba4/NDR/Parser.pm deleted file mode 100644 index fb73075f1a..0000000000 --- a/source4/pidl/lib/Parse/Pidl/Samba4/NDR/Parser.pm +++ /dev/null @@ -1,2695 +0,0 @@ -################################################### -# Samba4 NDR parser generator for IDL structures -# Copyright tridge@samba.org 2000-2003 -# Copyright tpot@samba.org 2001 -# Copyright jelmer@samba.org 2004-2006 -# released under the GNU GPL - -package Parse::Pidl::Samba4::NDR::Parser; - -require Exporter; -@ISA = qw(Exporter); -@EXPORT_OK = qw(check_null_pointer NeededFunction NeededElement NeededType $res NeededInterface TypeFunctionName ParseElementPrint); - -use strict; -use Parse::Pidl::Typelist qw(hasType getType mapTypeName typeHasBody); -use Parse::Pidl::Util qw(has_property ParseExpr ParseExprExt print_uuid unmake_str); -use Parse::Pidl::CUtil qw(get_pointer_to get_value_of get_array_element); -use Parse::Pidl::NDR qw(GetPrevLevel GetNextLevel ContainsDeferred is_charset_array); -use Parse::Pidl::Samba4 qw(is_intree choose_header); -use Parse::Pidl::Samba4::Header qw(GenerateFunctionInEnv GenerateFunctionOutEnv EnvSubstituteValue GenerateStructEnv); -use Parse::Pidl qw(warning); - -use vars qw($VERSION); -$VERSION = '0.01'; - -# list of known types -my %typefamily; - -sub new($$) { - my ($class) = @_; - my $self = { res => "", res_hdr => "", deferred => [], tabs => "", defer_tabs => "" }; - bless($self, $class); -} - -sub get_typefamily($) -{ - my $n = shift; - return $typefamily{$n}; -} - -sub append_prefix($$) -{ - my ($e, $var_name) = @_; - my $pointers = 0; - my $arrays = 0; - - foreach my $l (@{$e->{LEVELS}}) { - if ($l->{TYPE} eq "POINTER") { - $pointers++; - } elsif ($l->{TYPE} eq "ARRAY") { - $arrays++; - if (($pointers == 0) and - (not $l->{IS_FIXED}) and - (not $l->{IS_INLINE})) { - return get_value_of($var_name); - } - } elsif ($l->{TYPE} eq "DATA") { - if (Parse::Pidl::Typelist::scalar_is_reference($l->{DATA_TYPE})) { - return get_value_of($var_name) unless ($pointers or $arrays); - } - } - } - - return $var_name; -} - -sub has_fast_array($$) -{ - my ($e,$l) = @_; - - return 0 if ($l->{TYPE} ne "ARRAY"); - - my $nl = GetNextLevel($e,$l); - return 0 unless ($nl->{TYPE} eq "DATA"); - return 0 unless (hasType($nl->{DATA_TYPE})); - - my $t = getType($nl->{DATA_TYPE}); - - # Only uint8 and string have fast array functions at the moment - return ($t->{NAME} eq "uint8") or ($t->{NAME} eq "string"); -} - - -#################################### -# pidl() is our basic output routine -sub pidl($$) -{ - my ($self, $d) = @_; - if ($d) { - $self->{res} .= $self->{tabs}; - $self->{res} .= $d; - } - $self->{res} .="\n"; -} - -sub pidl_hdr($$) { my ($self, $d) = @_; $self->{res_hdr} .= "$d\n"; } - -#################################### -# defer() is like pidl(), but adds to -# a deferred buffer which is then added to the -# output buffer at the end of the structure/union/function -# This is needed to cope with code that must be pushed back -# to the end of a block of elements -sub defer_indent($) { my ($self) = @_; $self->{defer_tabs}.="\t"; } -sub defer_deindent($) { my ($self) = @_; $self->{defer_tabs}=substr($self->{defer_tabs}, 0, -1); } - -sub defer($$) -{ - my ($self, $d) = @_; - if ($d) { - push(@{$self->{deferred}}, $self->{defer_tabs}.$d); - } -} - -######################################## -# add the deferred content to the current -# output -sub add_deferred($) -{ - my ($self) = @_; - $self->pidl($_) foreach (@{$self->{deferred}}); - $self->{deferred} = []; - $self->{defer_tabs} = ""; -} - -sub indent($) -{ - my ($self) = @_; - $self->{tabs} .= "\t"; -} - -sub deindent($) -{ - my ($self) = @_; - $self->{tabs} = substr($self->{tabs}, 0, -1); -} - -##################################################################### -# declare a function public or static, depending on its attributes -sub fn_declare($$$$) -{ - my ($self,$type,$fn,$decl) = @_; - - if (has_property($fn, "no$type")) { - $self->pidl_hdr("$decl;"); - return 0; - } - - if (has_property($fn, "public")) { - $self->pidl_hdr("$decl;"); - $self->pidl("_PUBLIC_ $decl"); - } else { - $self->pidl("static $decl"); - } - - return 1; -} - -################################################################### -# setup any special flags for an element or structure -sub start_flags($$$) -{ - my ($self, $e, $ndr) = @_; - my $flags = has_property($e, "flag"); - if (defined $flags) { - $self->pidl("{"); - $self->indent; - $self->pidl("uint32_t _flags_save_$e->{TYPE} = $ndr->flags;"); - $self->pidl("ndr_set_flags(&$ndr->flags, $flags);"); - } -} - -################################################################### -# end any special flags for an element or structure -sub end_flags($$$) -{ - my ($self, $e, $ndr) = @_; - my $flags = has_property($e, "flag"); - if (defined $flags) { - $self->pidl("$ndr->flags = _flags_save_$e->{TYPE};"); - $self->deindent; - $self->pidl("}"); - } -} - -##################################################################### -# parse the data of an array - push side -sub ParseArrayPushHeader($$$$$$) -{ - my ($self,$e,$l,$ndr,$var_name,$env) = @_; - - my $size; - my $length; - - if ($l->{IS_ZERO_TERMINATED}) { - if (has_property($e, "charset")) { - $size = $length = "ndr_charset_length($var_name, CH_$e->{PROPERTIES}->{charset})"; - } else { - $size = $length = "ndr_string_length($var_name, sizeof(*$var_name))"; - } - } else { - $size = ParseExpr($l->{SIZE_IS}, $env, $e); - $length = ParseExpr($l->{LENGTH_IS}, $env, $e); - } - - if ((!$l->{IS_SURROUNDING}) and $l->{IS_CONFORMANT}) { - $self->pidl("NDR_CHECK(ndr_push_uint32($ndr, NDR_SCALARS, $size));"); - } - - if ($l->{IS_VARYING}) { - $self->pidl("NDR_CHECK(ndr_push_uint32($ndr, NDR_SCALARS, 0));"); # array offset - $self->pidl("NDR_CHECK(ndr_push_uint32($ndr, NDR_SCALARS, $length));"); - } - - return $length; -} - -sub check_fully_dereferenced($$) -{ - my ($element, $env) = @_; - - return sub ($) { - my $origvar = shift; - my $check = 0; - - # Figure out the number of pointers in $ptr - my $expandedvar = $origvar; - $expandedvar =~ s/^(\**)//; - my $ptr = $1; - - my $var = undef; - foreach (keys %$env) { - if ($env->{$_} eq $expandedvar) { - $var = $_; - last; - } - } - - return($origvar) unless (defined($var)); - my $e; - foreach (@{$element->{PARENT}->{ELEMENTS}}) { - if ($_->{NAME} eq $var) { - $e = $_; - last; - } - } - - $e or die("Environment doesn't match siblings"); - - # See if pointer at pointer level $level - # needs to be checked. - my $nump = 0; - foreach (@{$e->{LEVELS}}) { - if ($_->{TYPE} eq "POINTER") { - $nump = $_->{POINTER_INDEX}+1; - } - } - warning($element->{ORIGINAL}, "Got pointer for `$e->{NAME}', expected fully derefenced variable") if ($nump > length($ptr)); - return ($origvar); - } -} - -sub check_null_pointer($$$$) -{ - my ($element, $env, $print_fn, $return) = @_; - - return sub ($) { - my $expandedvar = shift; - my $check = 0; - - # Figure out the number of pointers in $ptr - $expandedvar =~ s/^(\**)//; - my $ptr = $1; - - my $var = undef; - foreach (keys %$env) { - if ($env->{$_} eq $expandedvar) { - $var = $_; - last; - } - } - - if (defined($var)) { - my $e; - # lookup ptr in $e - foreach (@{$element->{PARENT}->{ELEMENTS}}) { - if ($_->{NAME} eq $var) { - $e = $_; - last; - } - } - - $e or die("Environment doesn't match siblings"); - - # See if pointer at pointer level $level - # needs to be checked. - foreach my $l (@{$e->{LEVELS}}) { - if ($l->{TYPE} eq "POINTER" and - $l->{POINTER_INDEX} == length($ptr)) { - # No need to check ref pointers - $check = ($l->{POINTER_TYPE} ne "ref"); - last; - } - - if ($l->{TYPE} eq "DATA") { - warning($element, "too much dereferences for `$var'"); - } - } - } else { - warning($element, "unknown dereferenced expression `$expandedvar'"); - $check = 1; - } - - $print_fn->("if ($ptr$expandedvar == NULL) $return") if $check; - } -} - -##################################################################### -# parse an array - pull side -sub ParseArrayPullHeader($$$$$$) -{ - my ($self,$e,$l,$ndr,$var_name,$env) = @_; - - my $length; - my $size; - - if ($l->{IS_CONFORMANT}) { - $length = $size = "ndr_get_array_size($ndr, " . get_pointer_to($var_name) . ")"; - } elsif ($l->{IS_ZERO_TERMINATED}) { # Noheader arrays - $length = $size = "ndr_get_string_size($ndr, sizeof(*$var_name))"; - } else { - $length = $size = ParseExprExt($l->{SIZE_IS}, $env, $e->{ORIGINAL}, - check_null_pointer($e, $env, sub { $self->pidl(shift); }, - "return ndr_pull_error($ndr, NDR_ERR_INVALID_POINTER, \"NULL Pointer for size_is()\");"), - check_fully_dereferenced($e, $env)); - } - - if ((!$l->{IS_SURROUNDING}) and $l->{IS_CONFORMANT}) { - $self->pidl("NDR_CHECK(ndr_pull_array_size($ndr, " . get_pointer_to($var_name) . "));"); - } - - if ($l->{IS_VARYING}) { - $self->pidl("NDR_CHECK(ndr_pull_array_length($ndr, " . get_pointer_to($var_name) . "));"); - $length = "ndr_get_array_length($ndr, " . get_pointer_to($var_name) .")"; - } - - if ($length ne $size) { - $self->pidl("if ($length > $size) {"); - $self->indent; - $self->pidl("return ndr_pull_error($ndr, NDR_ERR_ARRAY_SIZE, \"Bad array size %u should exceed array length %u\", $size, $length);"); - $self->deindent; - $self->pidl("}"); - } - - if ($l->{IS_CONFORMANT} and not $l->{IS_ZERO_TERMINATED}) { - $self->defer("if ($var_name) {"); - $self->defer_indent; - my $size = ParseExprExt($l->{SIZE_IS}, $env, $e->{ORIGINAL}, - check_null_pointer($e, $env, sub { $self->defer(shift); }, - "return ndr_pull_error($ndr, NDR_ERR_INVALID_POINTER, \"NULL Pointer for size_is()\");"), - check_fully_dereferenced($e, $env)); - $self->defer("NDR_CHECK(ndr_check_array_size($ndr, (void*)" . get_pointer_to($var_name) . ", $size));"); - $self->defer_deindent; - $self->defer("}"); - } - - if ($l->{IS_VARYING} and not $l->{IS_ZERO_TERMINATED}) { - $self->defer("if ($var_name) {"); - $self->defer_indent; - my $length = ParseExprExt($l->{LENGTH_IS}, $env, $e->{ORIGINAL}, - check_null_pointer($e, $env, sub { $self->defer(shift); }, - "return ndr_pull_error($ndr, NDR_ERR_INVALID_POINTER, \"NULL Pointer for length_is()\");"), - check_fully_dereferenced($e, $env)); - $self->defer("NDR_CHECK(ndr_check_array_length($ndr, (void*)" . get_pointer_to($var_name) . ", $length));"); - $self->defer_deindent; - $self->defer("}"); - } - - if (not $l->{IS_FIXED} and not is_charset_array($e, $l)) { - $self->AllocateArrayLevel($e,$l,$ndr,$var_name,$size); - } - - return $length; -} - -sub compression_alg($$) -{ - my ($e, $l) = @_; - my ($alg, $clen, $dlen) = split(/,/, $l->{COMPRESSION}); - - return $alg; -} - -sub compression_clen($$$) -{ - my ($e, $l, $env) = @_; - my ($alg, $clen, $dlen) = split(/,/, $l->{COMPRESSION}); - - return ParseExpr($clen, $env, $e->{ORIGINAL}); -} - -sub compression_dlen($$$) -{ - my ($e,$l,$env) = @_; - my ($alg, $clen, $dlen) = split(/,/, $l->{COMPRESSION}); - - return ParseExpr($dlen, $env, $e->{ORIGINAL}); -} - -sub ParseCompressionPushStart($$$$$) -{ - my ($self,$e,$l,$ndr,$env) = @_; - my $comndr = "$ndr\_compressed"; - my $alg = compression_alg($e, $l); - my $dlen = compression_dlen($e, $l, $env); - - $self->pidl("{"); - $self->indent; - $self->pidl("struct ndr_push *$comndr;"); - $self->pidl("NDR_CHECK(ndr_push_compression_start($ndr, &$comndr, $alg, $dlen));"); - - return $comndr; -} - -sub ParseCompressionPushEnd($$$$$) -{ - my ($self,$e,$l,$ndr,$env) = @_; - my $comndr = "$ndr\_compressed"; - my $alg = compression_alg($e, $l); - my $dlen = compression_dlen($e, $l, $env); - - $self->pidl("NDR_CHECK(ndr_push_compression_end($ndr, $comndr, $alg, $dlen));"); - $self->deindent; - $self->pidl("}"); -} - -sub ParseCompressionPullStart($$$$$) -{ - my ($self,$e,$l,$ndr,$env) = @_; - my $comndr = "$ndr\_compressed"; - my $alg = compression_alg($e, $l); - my $dlen = compression_dlen($e, $l, $env); - - $self->pidl("{"); - $self->indent; - $self->pidl("struct ndr_pull *$comndr;"); - $self->pidl("NDR_CHECK(ndr_pull_compression_start($ndr, &$comndr, $alg, $dlen));"); - - return $comndr; -} - -sub ParseCompressionPullEnd($$$$$) -{ - my ($self,$e,$l,$ndr,$env) = @_; - my $comndr = "$ndr\_compressed"; - my $alg = compression_alg($e, $l); - my $dlen = compression_dlen($e, $l, $env); - - $self->pidl("NDR_CHECK(ndr_pull_compression_end($ndr, $comndr, $alg, $dlen));"); - $self->deindent; - $self->pidl("}"); -} - -sub ParseSubcontextPushStart($$$$$) -{ - my ($self,$e,$l,$ndr,$env) = @_; - my $subndr = "_ndr_$e->{NAME}"; - my $subcontext_size = ParseExpr($l->{SUBCONTEXT_SIZE}, $env, $e->{ORIGINAL}); - - $self->pidl("{"); - $self->indent; - $self->pidl("struct ndr_push *$subndr;"); - $self->pidl("NDR_CHECK(ndr_push_subcontext_start($ndr, &$subndr, $l->{HEADER_SIZE}, $subcontext_size));"); - - if (defined $l->{COMPRESSION}) { - $subndr = $self->ParseCompressionPushStart($e, $l, $subndr, $env); - } - - return $subndr; -} - -sub ParseSubcontextPushEnd($$$$$) -{ - my ($self,$e,$l,$ndr,$env) = @_; - my $subndr = "_ndr_$e->{NAME}"; - my $subcontext_size = ParseExpr($l->{SUBCONTEXT_SIZE}, $env, $e->{ORIGINAL}); - - if (defined $l->{COMPRESSION}) { - $self->ParseCompressionPushEnd($e, $l, $subndr, $env); - } - - $self->pidl("NDR_CHECK(ndr_push_subcontext_end($ndr, $subndr, $l->{HEADER_SIZE}, $subcontext_size));"); - $self->deindent; - $self->pidl("}"); -} - -sub ParseSubcontextPullStart($$$$$) -{ - my ($self,$e,$l,$ndr,$env) = @_; - my $subndr = "_ndr_$e->{NAME}"; - my $subcontext_size = ParseExpr($l->{SUBCONTEXT_SIZE}, $env, $e->{ORIGINAL}); - - $self->pidl("{"); - $self->indent; - $self->pidl("struct ndr_pull *$subndr;"); - $self->pidl("NDR_CHECK(ndr_pull_subcontext_start($ndr, &$subndr, $l->{HEADER_SIZE}, $subcontext_size));"); - - if (defined $l->{COMPRESSION}) { - $subndr = $self->ParseCompressionPullStart($e, $l, $subndr, $env); - } - - return $subndr; -} - -sub ParseSubcontextPullEnd($$$$$) -{ - my ($self,$e,$l,$ndr,$env) = @_; - my $subndr = "_ndr_$e->{NAME}"; - my $subcontext_size = ParseExpr($l->{SUBCONTEXT_SIZE}, $env, $e->{ORIGINAL}); - - if (defined $l->{COMPRESSION}) { - $self->ParseCompressionPullEnd($e, $l, $subndr, $env); - } - - $self->pidl("NDR_CHECK(ndr_pull_subcontext_end($ndr, $subndr, $l->{HEADER_SIZE}, $subcontext_size));"); - $self->deindent; - $self->pidl("}"); -} - -sub ParseElementPushLevel -{ - my ($self,$e,$l,$ndr,$var_name,$env,$primitives,$deferred) = @_; - - my $ndr_flags = CalcNdrFlags($l, $primitives, $deferred); - - if ($l->{TYPE} eq "ARRAY" and ($l->{IS_CONFORMANT} or $l->{IS_VARYING})) { - $var_name = get_pointer_to($var_name); - } - - if (defined($ndr_flags)) { - if ($l->{TYPE} eq "SUBCONTEXT") { - my $subndr = $self->ParseSubcontextPushStart($e, $l, $ndr, $env); - $self->ParseElementPushLevel($e, GetNextLevel($e, $l), $subndr, $var_name, $env, 1, 1); - $self->ParseSubcontextPushEnd($e, $l, $ndr, $env); - } elsif ($l->{TYPE} eq "POINTER") { - $self->ParsePtrPush($e, $l, $ndr, $var_name); - } elsif ($l->{TYPE} eq "ARRAY") { - my $length = $self->ParseArrayPushHeader($e, $l, $ndr, $var_name, $env); - - my $nl = GetNextLevel($e, $l); - - # Allow speedups for arrays of scalar types - if (is_charset_array($e,$l)) { - $self->pidl("NDR_CHECK(ndr_push_charset($ndr, $ndr_flags, $var_name, $length, sizeof(" . mapTypeName($nl->{DATA_TYPE}) . "), CH_$e->{PROPERTIES}->{charset}));"); - return; - } elsif (has_fast_array($e,$l)) { - $self->pidl("NDR_CHECK(ndr_push_array_$nl->{DATA_TYPE}($ndr, $ndr_flags, $var_name, $length));"); - return; - } - } elsif ($l->{TYPE} eq "SWITCH") { - $self->ParseSwitchPush($e, $l, $ndr, $var_name, $env); - } elsif ($l->{TYPE} eq "DATA") { - $self->ParseDataPush($e, $l, $ndr, $var_name, $primitives, $deferred); - } elsif ($l->{TYPE} eq "TYPEDEF") { - $typefamily{$e->{DATA}->{TYPE}}->{PUSH_FN_BODY}->($self, $e->{DATA}, $ndr, $var_name); - } - } - - if ($l->{TYPE} eq "POINTER" and $deferred) { - if ($l->{POINTER_TYPE} ne "ref") { - $self->pidl("if ($var_name) {"); - $self->indent; - if ($l->{POINTER_TYPE} eq "relative") { - $self->pidl("NDR_CHECK(ndr_push_relative_ptr2($ndr, $var_name));"); - } - } - $var_name = get_value_of($var_name); - $self->ParseElementPushLevel($e, GetNextLevel($e, $l), $ndr, $var_name, $env, 1, 1); - - if ($l->{POINTER_TYPE} ne "ref") { - $self->deindent; - $self->pidl("}"); - } - } elsif ($l->{TYPE} eq "ARRAY" and not has_fast_array($e,$l) and - not is_charset_array($e, $l)) { - my $length = ParseExpr($l->{LENGTH_IS}, $env, $e->{ORIGINAL}); - my $counter = "cntr_$e->{NAME}_$l->{LEVEL_INDEX}"; - - $var_name = get_array_element($var_name, $counter); - - if (($primitives and not $l->{IS_DEFERRED}) or ($deferred and $l->{IS_DEFERRED})) { - $self->pidl("for ($counter = 0; $counter < $length; $counter++) {"); - $self->indent; - $self->ParseElementPushLevel($e, GetNextLevel($e, $l), $ndr, $var_name, $env, 1, 0); - $self->deindent; - $self->pidl("}"); - } - - if ($deferred and ContainsDeferred($e, $l)) { - $self->pidl("for ($counter = 0; $counter < $length; $counter++) {"); - $self->indent; - $self->ParseElementPushLevel($e, GetNextLevel($e, $l), $ndr, $var_name, $env, 0, 1); - $self->deindent; - $self->pidl("}"); - } - } elsif ($l->{TYPE} eq "SWITCH") { - $self->ParseElementPushLevel($e, GetNextLevel($e, $l), $ndr, $var_name, $env, $primitives, $deferred); - } -} - -##################################################################### -# parse scalars in a structure element -sub ParseElementPush($$$$$$) -{ - my ($self,$e,$ndr,$env,$primitives,$deferred) = @_; - my $subndr = undef; - - my $var_name = $env->{$e->{NAME}}; - - return unless $primitives or ($deferred and ContainsDeferred($e, $e->{LEVELS}[0])); - - # Representation type is different from transmit_as - if ($e->{REPRESENTATION_TYPE} ne $e->{TYPE}) { - $self->pidl("{"); - $self->indent; - my $transmit_name = "_transmit_$e->{NAME}"; - $self->pidl(mapTypeName($e->{TYPE}) ." $transmit_name;"); - $self->pidl("NDR_CHECK(ndr_$e->{REPRESENTATION_TYPE}_to_$e->{TYPE}($var_name, " . get_pointer_to($transmit_name) . "));"); - $var_name = $transmit_name; - } - - $var_name = append_prefix($e, $var_name); - - $self->start_flags($e, $ndr); - - if (defined(my $value = has_property($e, "value"))) { - $var_name = ParseExpr($value, $env, $e->{ORIGINAL}); - } - - $self->ParseElementPushLevel($e, $e->{LEVELS}[0], $ndr, $var_name, $env, $primitives, $deferred); - - $self->end_flags($e, $ndr); - - if ($e->{REPRESENTATION_TYPE} ne $e->{TYPE}) { - $self->deindent; - $self->pidl("}"); - } -} - -##################################################################### -# parse a pointer in a struct element or function -sub ParsePtrPush($$$$$) -{ - my ($self,$e,$l,$ndr,$var_name) = @_; - - if ($l->{POINTER_TYPE} eq "ref") { - $self->pidl("if ($var_name == NULL) {"); - $self->indent; - $self->pidl("return ndr_push_error($ndr, NDR_ERR_INVALID_POINTER, \"NULL [ref] pointer\");"); - $self->deindent; - $self->pidl("}"); - if ($l->{LEVEL} eq "EMBEDDED") { - $self->pidl("NDR_CHECK(ndr_push_ref_ptr(ndr));"); - } - } elsif ($l->{POINTER_TYPE} eq "relative") { - $self->pidl("NDR_CHECK(ndr_push_relative_ptr1($ndr, $var_name));"); - } elsif ($l->{POINTER_TYPE} eq "unique") { - $self->pidl("NDR_CHECK(ndr_push_unique_ptr($ndr, $var_name));"); - } elsif ($l->{POINTER_TYPE} eq "full") { - $self->pidl("NDR_CHECK(ndr_push_full_ptr($ndr, $var_name));"); - } else { - die("Unhandled pointer type $l->{POINTER_TYPE}"); - } -} - -sub need_pointer_to($$$) -{ - my ($e, $l, $scalar_only) = @_; - - my $t; - if (ref($l->{DATA_TYPE})) { - $t = "$l->{DATA_TYPE}->{TYPE}_$l->{DATA_TYPE}->{NAME}"; - } else { - $t = $l->{DATA_TYPE}; - } - - if (not Parse::Pidl::Typelist::is_scalar($t)) { - return 1 if $scalar_only; - } - - my $arrays = 0; - - foreach my $tl (@{$e->{LEVELS}}) { - last if $l == $tl; - if ($tl->{TYPE} eq "ARRAY") { - $arrays++; - } - } - - if (Parse::Pidl::Typelist::scalar_is_reference($t)) { - return 1 unless $arrays; - } - - return 0; -} - -sub ParseDataPrint($$$$$) -{ - my ($self, $e, $l, $ndr, $var_name) = @_; - - if (not ref($l->{DATA_TYPE}) or defined($l->{DATA_TYPE}->{NAME})) { - - if (need_pointer_to($e, $l, 1)) { - $var_name = get_pointer_to($var_name); - } - - $self->pidl(TypeFunctionName("ndr_print", $l->{DATA_TYPE})."($ndr, \"$e->{NAME}\", $var_name);"); - } else { - $self->ParseTypePrint($l->{DATA_TYPE}, $ndr, $var_name); - } -} - -##################################################################### -# print scalars in a structure element -sub ParseElementPrint($$$$$) -{ - my($self, $e, $ndr, $var_name, $env) = @_; - - return if (has_property($e, "noprint")); - - if ($e->{REPRESENTATION_TYPE} ne $e->{TYPE}) { - $self->pidl("ndr_print_$e->{REPRESENTATION_TYPE}($ndr, \"$e->{NAME}\", $var_name);"); - return; - } - - $var_name = append_prefix($e, $var_name); - - if (defined(my $value = has_property($e, "value"))) { - $var_name = "($ndr->flags & LIBNDR_PRINT_SET_VALUES)?" . ParseExpr($value,$env, $e->{ORIGINAL}) . ":$var_name"; - } - - foreach my $l (@{$e->{LEVELS}}) { - if ($l->{TYPE} eq "POINTER") { - $self->pidl("ndr_print_ptr($ndr, \"$e->{NAME}\", $var_name);"); - $self->pidl("$ndr->depth++;"); - if ($l->{POINTER_TYPE} ne "ref") { - $self->pidl("if ($var_name) {"); - $self->indent; - } - $var_name = get_value_of($var_name); - } elsif ($l->{TYPE} eq "ARRAY") { - my $length; - - if ($l->{IS_CONFORMANT} or $l->{IS_VARYING}) { - $var_name = get_pointer_to($var_name); - } - - if ($l->{IS_ZERO_TERMINATED}) { - $length = "ndr_string_length($var_name, sizeof(*$var_name))"; - } else { - $length = ParseExprExt($l->{LENGTH_IS}, $env, $e->{ORIGINAL}, - check_null_pointer($e, $env, sub { $self->pidl(shift); }, "return;"), check_fully_dereferenced($e, $env)); - } - - if (is_charset_array($e,$l)) { - $self->pidl("ndr_print_string($ndr, \"$e->{NAME}\", $var_name);"); - last; - } elsif (has_fast_array($e, $l)) { - my $nl = GetNextLevel($e, $l); - $self->pidl("ndr_print_array_$nl->{DATA_TYPE}($ndr, \"$e->{NAME}\", $var_name, $length);"); - last; - } else { - my $counter = "cntr_$e->{NAME}_$l->{LEVEL_INDEX}"; - - $self->pidl("$ndr->print($ndr, \"\%s: ARRAY(\%d)\", \"$e->{NAME}\", (int)$length);"); - $self->pidl("$ndr->depth++;"); - $self->pidl("for ($counter=0;$counter<$length;$counter++) {"); - $self->indent; - $self->pidl("char *idx_$l->{LEVEL_INDEX}=NULL;"); - $self->pidl("if (asprintf(&idx_$l->{LEVEL_INDEX}, \"[\%d]\", $counter) != -1) {"); - $self->indent; - - $var_name = get_array_element($var_name, $counter); - } - } elsif ($l->{TYPE} eq "DATA") { - $self->ParseDataPrint($e, $l, $ndr, $var_name); - } elsif ($l->{TYPE} eq "SWITCH") { - my $switch_var = ParseExprExt($l->{SWITCH_IS}, $env, $e->{ORIGINAL}, - check_null_pointer($e, $env, sub { $self->pidl(shift); }, "return;"), check_fully_dereferenced($e, $env)); - $self->pidl("ndr_print_set_switch_value($ndr, " . get_pointer_to($var_name) . ", $switch_var);"); - } - } - - foreach my $l (reverse @{$e->{LEVELS}}) { - if ($l->{TYPE} eq "POINTER") { - if ($l->{POINTER_TYPE} ne "ref") { - $self->deindent; - $self->pidl("}"); - } - $self->pidl("$ndr->depth--;"); - } elsif (($l->{TYPE} eq "ARRAY") - and not is_charset_array($e,$l) - and not has_fast_array($e,$l)) { - $self->pidl("free(idx_$l->{LEVEL_INDEX});"); - $self->deindent; - $self->pidl("}"); - $self->deindent; - $self->pidl("}"); - $self->pidl("$ndr->depth--;"); - } - } -} - -##################################################################### -# parse scalars in a structure element - pull size -sub ParseSwitchPull($$$$$$) -{ - my($self,$e,$l,$ndr,$var_name,$env) = @_; - my $switch_var = ParseExprExt($l->{SWITCH_IS}, $env, $e->{ORIGINAL}, - check_null_pointer($e, $env, sub { $self->pidl(shift); }, - "return ndr_pull_error($ndr, NDR_ERR_INVALID_POINTER, \"NULL Pointer for switch_is()\");"), - check_fully_dereferenced($e, $env)); - - $var_name = get_pointer_to($var_name); - $self->pidl("NDR_CHECK(ndr_pull_set_switch_value($ndr, $var_name, $switch_var));"); -} - -##################################################################### -# push switch element -sub ParseSwitchPush($$$$$$) -{ - my($self,$e,$l,$ndr,$var_name,$env) = @_; - my $switch_var = ParseExprExt($l->{SWITCH_IS}, $env, $e->{ORIGINAL}, - check_null_pointer($e, $env, sub { $self->pidl(shift); }, - "return ndr_push_error($ndr, NDR_ERR_INVALID_POINTER, \"NULL Pointer for switch_is()\");"), - check_fully_dereferenced($e, $env)); - - $var_name = get_pointer_to($var_name); - $self->pidl("NDR_CHECK(ndr_push_set_switch_value($ndr, $var_name, $switch_var));"); -} - -sub ParseDataPull($$$$$$$) -{ - my ($self,$e,$l,$ndr,$var_name,$primitives,$deferred) = @_; - - if (not ref($l->{DATA_TYPE}) or defined($l->{DATA_TYPE}->{NAME})) { - - my $ndr_flags = CalcNdrFlags($l, $primitives, $deferred); - - if (need_pointer_to($e, $l, 0)) { - $var_name = get_pointer_to($var_name); - } - - $var_name = get_pointer_to($var_name); - - $self->pidl("NDR_CHECK(".TypeFunctionName("ndr_pull", $l->{DATA_TYPE})."($ndr, $ndr_flags, $var_name));"); - - if (my $range = has_property($e, "range")) { - $var_name = get_value_of($var_name); - my ($low, $high) = split(/,/, $range, 2); - $self->pidl("if ($var_name < $low || $var_name > $high) {"); - $self->pidl("\treturn ndr_pull_error($ndr, NDR_ERR_RANGE, \"value out of range\");"); - $self->pidl("}"); - } - } else { - $self->ParseTypePull($l->{DATA_TYPE}, $ndr, $var_name, $primitives, $deferred); - } -} - -sub ParseDataPush($$$$$$$) -{ - my ($self,$e,$l,$ndr,$var_name,$primitives,$deferred) = @_; - - if (not ref($l->{DATA_TYPE}) or defined($l->{DATA_TYPE}->{NAME})) { - - my $ndr_flags = CalcNdrFlags($l, $primitives, $deferred); - - # strings are passed by value rather than reference - if (need_pointer_to($e, $l, 1)) { - $var_name = get_pointer_to($var_name); - } - - $self->pidl("NDR_CHECK(".TypeFunctionName("ndr_push", $l->{DATA_TYPE})."($ndr, $ndr_flags, $var_name));"); - } else { - $self->ParseTypePush($l->{DATA_TYPE}, $ndr, $var_name, $primitives, $deferred); - } -} - -sub CalcNdrFlags($$$) -{ - my ($l,$primitives,$deferred) = @_; - - my $scalars = 0; - my $buffers = 0; - - # Add NDR_SCALARS if this one is deferred - # and deferreds may be pushed - $scalars = 1 if ($l->{IS_DEFERRED} and $deferred); - - # Add NDR_SCALARS if this one is not deferred and - # primitives may be pushed - $scalars = 1 if (!$l->{IS_DEFERRED} and $primitives); - - # Add NDR_BUFFERS if this one contains deferred stuff - # and deferreds may be pushed - $buffers = 1 if ($l->{CONTAINS_DEFERRED} and $deferred); - - return "NDR_SCALARS|NDR_BUFFERS" if ($scalars and $buffers); - return "NDR_SCALARS" if ($scalars); - return "NDR_BUFFERS" if ($buffers); - return undef; -} - -sub ParseMemCtxPullFlags($$$$) -{ - my ($self, $e, $l) = @_; - - return undef unless ($l->{TYPE} eq "POINTER" or $l->{TYPE} eq "ARRAY"); - - return undef if ($l->{TYPE} eq "ARRAY" and $l->{IS_FIXED}); - return undef if has_fast_array($e, $l); - return undef if is_charset_array($e, $l); - - my $mem_flags = "0"; - - if (($l->{TYPE} eq "POINTER") and ($l->{POINTER_TYPE} eq "ref")) { - my $nl = GetNextLevel($e, $l); - my $next_is_array = ($nl->{TYPE} eq "ARRAY"); - my $next_is_string = (($nl->{TYPE} eq "DATA") and - ($nl->{DATA_TYPE} eq "string")); - if ($next_is_array or $next_is_string) { - return undef; - } elsif ($l->{LEVEL} eq "TOP") { - $mem_flags = "LIBNDR_FLAG_REF_ALLOC"; - } - } - - return $mem_flags; -} - -sub ParseMemCtxPullStart($$$$$) -{ - my ($self, $e, $l, $ndr, $ptr_name) = @_; - - my $mem_r_ctx = "_mem_save_$e->{NAME}_$l->{LEVEL_INDEX}"; - my $mem_c_ctx = $ptr_name; - my $mem_c_flags = $self->ParseMemCtxPullFlags($e, $l); - - return unless defined($mem_c_flags); - - $self->pidl("$mem_r_ctx = NDR_PULL_GET_MEM_CTX($ndr);"); - $self->pidl("NDR_PULL_SET_MEM_CTX($ndr, $mem_c_ctx, $mem_c_flags);"); -} - -sub ParseMemCtxPullEnd($$$$) -{ - my ($self, $e, $l, $ndr) = @_; - - my $mem_r_ctx = "_mem_save_$e->{NAME}_$l->{LEVEL_INDEX}"; - my $mem_r_flags = $self->ParseMemCtxPullFlags($e, $l); - - return unless defined($mem_r_flags); - - $self->pidl("NDR_PULL_SET_MEM_CTX($ndr, $mem_r_ctx, $mem_r_flags);"); -} - -sub CheckStringTerminator($$$$$) -{ - my ($self,$ndr,$e,$l,$length) = @_; - my $nl = GetNextLevel($e, $l); - - # Make sure last element is zero! - $self->pidl("NDR_CHECK(ndr_check_string_terminator($ndr, $length, sizeof($nl->{DATA_TYPE}_t)));"); -} - -sub ParseElementPullLevel -{ - my($self,$e,$l,$ndr,$var_name,$env,$primitives,$deferred) = @_; - - my $ndr_flags = CalcNdrFlags($l, $primitives, $deferred); - - if ($l->{TYPE} eq "ARRAY" and ($l->{IS_VARYING} or $l->{IS_CONFORMANT})) { - $var_name = get_pointer_to($var_name); - } - - # Only pull something if there's actually something to be pulled - if (defined($ndr_flags)) { - if ($l->{TYPE} eq "SUBCONTEXT") { - my $subndr = $self->ParseSubcontextPullStart($e, $l, $ndr, $env); - $self->ParseElementPullLevel($e, GetNextLevel($e,$l), $subndr, $var_name, $env, 1, 1); - $self->ParseSubcontextPullEnd($e, $l, $ndr, $env); - } elsif ($l->{TYPE} eq "ARRAY") { - my $length = $self->ParseArrayPullHeader($e, $l, $ndr, $var_name, $env); - - my $nl = GetNextLevel($e, $l); - - if (is_charset_array($e,$l)) { - if ($l->{IS_ZERO_TERMINATED}) { - $self->CheckStringTerminator($ndr, $e, $l, $length); - } - $self->pidl("NDR_CHECK(ndr_pull_charset($ndr, $ndr_flags, ".get_pointer_to($var_name).", $length, sizeof(" . mapTypeName($nl->{DATA_TYPE}) . "), CH_$e->{PROPERTIES}->{charset}));"); - return; - } elsif (has_fast_array($e, $l)) { - if ($l->{IS_ZERO_TERMINATED}) { - $self->CheckStringTerminator($ndr,$e,$l,$length); - } - $self->pidl("NDR_CHECK(ndr_pull_array_$nl->{DATA_TYPE}($ndr, $ndr_flags, $var_name, $length));"); - return; - } - } elsif ($l->{TYPE} eq "POINTER") { - $self->ParsePtrPull($e, $l, $ndr, $var_name); - } elsif ($l->{TYPE} eq "SWITCH") { - $self->ParseSwitchPull($e, $l, $ndr, $var_name, $env); - } elsif ($l->{TYPE} eq "DATA") { - $self->ParseDataPull($e, $l, $ndr, $var_name, $primitives, $deferred); - } elsif ($l->{TYPE} eq "TYPEDEF") { - $typefamily{$e->{DATA}->{TYPE}}->{PULL_FN_BODY}->($self, $e->{DATA}, $ndr, $var_name); - } - } - - # add additional constructions - if ($l->{TYPE} eq "POINTER" and $deferred) { - if ($l->{POINTER_TYPE} ne "ref") { - $self->pidl("if ($var_name) {"); - $self->indent; - - if ($l->{POINTER_TYPE} eq "relative") { - $self->pidl("uint32_t _relative_save_offset;"); - $self->pidl("_relative_save_offset = $ndr->offset;"); - $self->pidl("NDR_CHECK(ndr_pull_relative_ptr2($ndr, $var_name));"); - } - } - - $self->ParseMemCtxPullStart($e, $l, $ndr, $var_name); - - $var_name = get_value_of($var_name); - $self->ParseElementPullLevel($e, GetNextLevel($e,$l), $ndr, $var_name, $env, 1, 1); - - $self->ParseMemCtxPullEnd($e, $l, $ndr); - - if ($l->{POINTER_TYPE} ne "ref") { - if ($l->{POINTER_TYPE} eq "relative") { - $self->pidl("$ndr->offset = _relative_save_offset;"); - } - $self->deindent; - $self->pidl("}"); - } - } elsif ($l->{TYPE} eq "ARRAY" and - not has_fast_array($e,$l) and not is_charset_array($e, $l)) { - my $length = ParseExpr($l->{LENGTH_IS}, $env, $e->{ORIGINAL}); - my $counter = "cntr_$e->{NAME}_$l->{LEVEL_INDEX}"; - my $array_name = $var_name; - - $var_name = get_array_element($var_name, $counter); - - $self->ParseMemCtxPullStart($e, $l, $ndr, $array_name); - - if (($primitives and not $l->{IS_DEFERRED}) or ($deferred and $l->{IS_DEFERRED})) { - my $nl = GetNextLevel($e,$l); - - if ($l->{IS_ZERO_TERMINATED}) { - $self->CheckStringTerminator($ndr,$e,$l,$length); - } - - $self->pidl("for ($counter = 0; $counter < $length; $counter++) {"); - $self->indent; - $self->ParseElementPullLevel($e, $nl, $ndr, $var_name, $env, 1, 0); - $self->deindent; - $self->pidl("}"); - } - - if ($deferred and ContainsDeferred($e, $l)) { - $self->pidl("for ($counter = 0; $counter < $length; $counter++) {"); - $self->indent; - $self->ParseElementPullLevel($e,GetNextLevel($e,$l), $ndr, $var_name, $env, 0, 1); - $self->deindent; - $self->pidl("}"); - } - - $self->ParseMemCtxPullEnd($e, $l, $ndr); - - } elsif ($l->{TYPE} eq "SWITCH") { - $self->ParseElementPullLevel($e, GetNextLevel($e,$l), $ndr, $var_name, $env, $primitives, $deferred); - } -} - -##################################################################### -# parse scalars in a structure element - pull size -sub ParseElementPull($$$$$$) -{ - my($self,$e,$ndr,$env,$primitives,$deferred) = @_; - - my $var_name = $env->{$e->{NAME}}; - my $represent_name; - my $transmit_name; - - return unless $primitives or ($deferred and ContainsDeferred($e, $e->{LEVELS}[0])); - - if ($e->{REPRESENTATION_TYPE} ne $e->{TYPE}) { - $self->pidl("{"); - $self->indent; - $represent_name = $var_name; - $transmit_name = "_transmit_$e->{NAME}"; - $var_name = $transmit_name; - $self->pidl(mapTypeName($e->{TYPE})." $var_name;"); - } - - $var_name = append_prefix($e, $var_name); - - $self->start_flags($e, $ndr); - - $self->ParseElementPullLevel($e,$e->{LEVELS}[0],$ndr,$var_name,$env,$primitives,$deferred); - - $self->end_flags($e, $ndr); - - # Representation type is different from transmit_as - if ($e->{REPRESENTATION_TYPE} ne $e->{TYPE}) { - $self->pidl("NDR_CHECK(ndr_$e->{TYPE}_to_$e->{REPRESENTATION_TYPE}($transmit_name, ".get_pointer_to($represent_name)."));"); - $self->deindent; - $self->pidl("}"); - } -} - -##################################################################### -# parse a pointer in a struct element or function -sub ParsePtrPull($$$$$) -{ - my($self, $e,$l,$ndr,$var_name) = @_; - - my $nl = GetNextLevel($e, $l); - my $next_is_array = ($nl->{TYPE} eq "ARRAY"); - my $next_is_string = (($nl->{TYPE} eq "DATA") and - ($nl->{DATA_TYPE} eq "string")); - - if ($l->{POINTER_TYPE} eq "ref" and $l->{LEVEL} eq "TOP") { - - if (!$next_is_array and !$next_is_string) { - $self->pidl("if ($ndr->flags & LIBNDR_FLAG_REF_ALLOC) {"); - $self->pidl("\tNDR_PULL_ALLOC($ndr, $var_name);"); - $self->pidl("}"); - } - - return; - } elsif ($l->{POINTER_TYPE} eq "ref" and $l->{LEVEL} eq "EMBEDDED") { - $self->pidl("NDR_CHECK(ndr_pull_ref_ptr($ndr, &_ptr_$e->{NAME}));"); - } elsif (($l->{POINTER_TYPE} eq "unique") or - ($l->{POINTER_TYPE} eq "relative") or - ($l->{POINTER_TYPE} eq "full")) { - $self->pidl("NDR_CHECK(ndr_pull_generic_ptr($ndr, &_ptr_$e->{NAME}));"); - } else { - die("Unhandled pointer type $l->{POINTER_TYPE}"); - } - - $self->pidl("if (_ptr_$e->{NAME}) {"); - $self->indent; - - # Don't do this for arrays, they're allocated at the actual level - # of the array - unless ($next_is_array or $next_is_string) { - $self->pidl("NDR_PULL_ALLOC($ndr, $var_name);"); - } else { - # FIXME: Yes, this is nasty. - # We allocate an array twice - # - once just to indicate that it's there, - # - then the real allocation... - $self->pidl("NDR_PULL_ALLOC($ndr, $var_name);"); - } - - #$self->pidl("memset($var_name, 0, sizeof($var_name));"); - if ($l->{POINTER_TYPE} eq "relative") { - $self->pidl("NDR_CHECK(ndr_pull_relative_ptr1($ndr, $var_name, _ptr_$e->{NAME}));"); - } - $self->deindent; - $self->pidl("} else {"); - $self->pidl("\t$var_name = NULL;"); - $self->pidl("}"); -} - -sub ParseStructPushPrimitives($$$$$) -{ - my ($self, $struct, $ndr, $varname, $env) = @_; - - # 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) - if (defined($struct->{SURROUNDING_ELEMENT})) { - my $e = $struct->{SURROUNDING_ELEMENT}; - - if (defined($e->{LEVELS}[0]) and - $e->{LEVELS}[0]->{TYPE} eq "ARRAY") { - my $size; - - if ($e->{LEVELS}[0]->{IS_ZERO_TERMINATED}) { - if (has_property($e, "charset")) { - $size = "ndr_charset_length($varname->$e->{NAME}, CH_$e->{PROPERTIES}->{charset})"; - } else { - $size = "ndr_string_length($varname->$e->{NAME}, sizeof(*$varname->$e->{NAME}))"; - } - } else { - $size = ParseExpr($e->{LEVELS}[0]->{SIZE_IS}, $env, $e->{ORIGINAL}); - } - - $self->pidl("NDR_CHECK(ndr_push_uint32($ndr, NDR_SCALARS, $size));"); - } else { - $self->pidl("NDR_CHECK(ndr_push_uint32($ndr, NDR_SCALARS, ndr_string_array_size($ndr, $varname->$e->{NAME})));"); - } - } - - $self->pidl("NDR_CHECK(ndr_push_align($ndr, $struct->{ALIGN}));"); - - if (defined($struct->{PROPERTIES}{relative_base})) { - # set the current offset as base for relative pointers - # and store it based on the toplevel struct/union - $self->pidl("NDR_CHECK(ndr_push_setup_relative_base_offset1($ndr, $varname, $ndr->offset));"); - } - - $self->ParseElementPush($_, $ndr, $env, 1, 0) foreach (@{$struct->{ELEMENTS}}); -} - -sub ParseStructPushDeferred($$$$) -{ - my ($self, $struct, $ndr, $varname, $env) = @_; - if (defined($struct->{PROPERTIES}{relative_base})) { - # retrieve the current offset as base for relative pointers - # based on the toplevel struct/union - $self->pidl("NDR_CHECK(ndr_push_setup_relative_base_offset2($ndr, $varname));"); - } - $self->ParseElementPush($_, $ndr, $env, 0, 1) foreach (@{$struct->{ELEMENTS}}); -} - -##################################################################### -# parse a struct -sub ParseStructPush($$$$) -{ - my ($self, $struct, $ndr, $varname) = @_; - - return unless defined($struct->{ELEMENTS}); - - my $env = GenerateStructEnv($struct, $varname); - - EnvSubstituteValue($env, $struct); - - $self->DeclareArrayVariables($_) foreach (@{$struct->{ELEMENTS}}); - - $self->start_flags($struct, $ndr); - - $self->pidl("if (ndr_flags & NDR_SCALARS) {"); - $self->indent; - $self->ParseStructPushPrimitives($struct, $ndr, $varname, $env); - $self->deindent; - $self->pidl("}"); - - $self->pidl("if (ndr_flags & NDR_BUFFERS) {"); - $self->indent; - $self->ParseStructPushDeferred($struct, $ndr, $varname, $env); - $self->deindent; - $self->pidl("}"); - - $self->end_flags($struct, $ndr); -} - -##################################################################### -# generate a push function for an enum -sub ParseEnumPush($$$$) -{ - my($self,$enum,$ndr,$varname) = @_; - my($type_fn) = $enum->{BASE_TYPE}; - - $self->start_flags($enum, $ndr); - $self->pidl("NDR_CHECK(ndr_push_$type_fn($ndr, NDR_SCALARS, $varname));"); - $self->end_flags($enum, $ndr); -} - -##################################################################### -# generate a pull function for an enum -sub ParseEnumPull($$$$) -{ - my($self,$enum,$ndr,$varname) = @_; - my($type_fn) = $enum->{BASE_TYPE}; - my($type_v_decl) = mapTypeName($type_fn); - - $self->pidl("$type_v_decl v;"); - $self->start_flags($enum, $ndr); - $self->pidl("NDR_CHECK(ndr_pull_$type_fn($ndr, NDR_SCALARS, &v));"); - $self->pidl("*$varname = v;"); - - $self->end_flags($enum, $ndr); -} - -##################################################################### -# generate a print function for an enum -sub ParseEnumPrint($$$$$) -{ - my($self,$enum,$ndr,$name,$varname) = @_; - - $self->pidl("const char *val = NULL;"); - $self->pidl(""); - - $self->start_flags($enum, $ndr); - - $self->pidl("switch ($varname) {"); - $self->indent; - my $els = \@{$enum->{ELEMENTS}}; - foreach my $i (0 .. $#{$els}) { - my $e = ${$els}[$i]; - chomp $e; - if ($e =~ /^(.*)=/) { - $e = $1; - } - $self->pidl("case $e: val = \"$e\"; break;"); - } - - $self->deindent; - $self->pidl("}"); - - $self->pidl("ndr_print_enum($ndr, name, \"$enum->{TYPE}\", val, $varname);"); - - $self->end_flags($enum, $ndr); -} - -sub DeclEnum($$$$) -{ - my ($e,$t,$name,$varname) = @_; - return "enum $name " . - ($t eq "pull"?"*":"") . $varname; -} - -$typefamily{ENUM} = { - DECL => \&DeclEnum, - PUSH_FN_BODY => \&ParseEnumPush, - PULL_FN_BODY => \&ParseEnumPull, - PRINT_FN_BODY => \&ParseEnumPrint, -}; - -##################################################################### -# generate a push function for a bitmap -sub ParseBitmapPush($$$$) -{ - my($self,$bitmap,$ndr,$varname) = @_; - my($type_fn) = $bitmap->{BASE_TYPE}; - - $self->start_flags($bitmap, $ndr); - - $self->pidl("NDR_CHECK(ndr_push_$type_fn($ndr, NDR_SCALARS, $varname));"); - - $self->end_flags($bitmap, $ndr); -} - -##################################################################### -# generate a pull function for an bitmap -sub ParseBitmapPull($$$$) -{ - my($self,$bitmap,$ndr,$varname) = @_; - my $type_fn = $bitmap->{BASE_TYPE}; - my($type_decl) = mapTypeName($bitmap->{BASE_TYPE}); - - $self->pidl("$type_decl v;"); - $self->start_flags($bitmap, $ndr); - $self->pidl("NDR_CHECK(ndr_pull_$type_fn($ndr, NDR_SCALARS, &v));"); - $self->pidl("*$varname = v;"); - - $self->end_flags($bitmap, $ndr); -} - -##################################################################### -# generate a print function for an bitmap -sub ParseBitmapPrintElement($$$$$$) -{ - my($self,$e,$bitmap,$ndr,$name,$varname) = @_; - my($type_decl) = mapTypeName($bitmap->{BASE_TYPE}); - my($type_fn) = $bitmap->{BASE_TYPE}; - my($flag); - - if ($e =~ /^(\w+) .*$/) { - $flag = "$1"; - } else { - die "Bitmap: \"$name\" invalid Flag: \"$e\""; - } - - $self->pidl("ndr_print_bitmap_flag($ndr, sizeof($type_decl), \"$flag\", $flag, $varname);"); -} - -##################################################################### -# generate a print function for an bitmap -sub ParseBitmapPrint($$$$$) -{ - my($self,$bitmap,$ndr,$name,$varname) = @_; - my($type_decl) = mapTypeName($bitmap->{TYPE}); - my($type_fn) = $bitmap->{BASE_TYPE}; - - $self->start_flags($bitmap, $ndr); - - $self->pidl("ndr_print_$type_fn($ndr, name, $varname);"); - - $self->pidl("$ndr->depth++;"); - foreach my $e (@{$bitmap->{ELEMENTS}}) { - $self->ParseBitmapPrintElement($e, $bitmap, $ndr, $name, $varname); - } - $self->pidl("$ndr->depth--;"); - - $self->end_flags($bitmap, $ndr); -} - -sub DeclBitmap($$$$) -{ - my ($e,$t,$name,$varname) = @_; - return mapTypeName(Parse::Pidl::Typelist::bitmap_type_fn($e)) . - ($t eq "pull"?" *":" ") . $varname; -} - -$typefamily{BITMAP} = { - DECL => \&DeclBitmap, - PUSH_FN_BODY => \&ParseBitmapPush, - PULL_FN_BODY => \&ParseBitmapPull, - PRINT_FN_BODY => \&ParseBitmapPrint, -}; - -##################################################################### -# generate a struct print function -sub ParseStructPrint($$$$$) -{ - my($self,$struct,$ndr,$name,$varname) = @_; - - return unless defined $struct->{ELEMENTS}; - - my $env = GenerateStructEnv($struct, $varname); - - $self->DeclareArrayVariables($_) foreach (@{$struct->{ELEMENTS}}); - - $self->pidl("ndr_print_struct($ndr, name, \"$name\");"); - - $self->start_flags($struct, $ndr); - - $self->pidl("$ndr->depth++;"); - - $self->ParseElementPrint($_, $ndr, $env->{$_->{NAME}}, $env) - foreach (@{$struct->{ELEMENTS}}); - $self->pidl("$ndr->depth--;"); - - $self->end_flags($struct, $ndr); -} - -sub DeclarePtrVariables($$) -{ - my ($self,$e) = @_; - foreach my $l (@{$e->{LEVELS}}) { - if ($l->{TYPE} eq "POINTER" and - not ($l->{POINTER_TYPE} eq "ref" and $l->{LEVEL} eq "TOP")) { - $self->pidl("uint32_t _ptr_$e->{NAME};"); - last; - } - } -} - -sub DeclareArrayVariables($$) -{ - my ($self,$e) = @_; - - foreach my $l (@{$e->{LEVELS}}) { - next if has_fast_array($e,$l); - next if is_charset_array($e,$l); - if ($l->{TYPE} eq "ARRAY") { - $self->pidl("uint32_t cntr_$e->{NAME}_$l->{LEVEL_INDEX};"); - } - } -} - -sub DeclareMemCtxVariables($$) -{ - my ($self,$e) = @_; - foreach my $l (@{$e->{LEVELS}}) { - my $mem_flags = $self->ParseMemCtxPullFlags($e, $l); - if (defined($mem_flags)) { - $self->pidl("TALLOC_CTX *_mem_save_$e->{NAME}_$l->{LEVEL_INDEX};"); - } - } -} - -sub ParseStructPullPrimitives($$$$$) -{ - my($self,$struct,$ndr,$varname,$env) = @_; - - if (defined $struct->{SURROUNDING_ELEMENT}) { - $self->pidl("NDR_CHECK(ndr_pull_array_size($ndr, &$varname->$struct->{SURROUNDING_ELEMENT}->{NAME}));"); - } - - $self->pidl("NDR_CHECK(ndr_pull_align($ndr, $struct->{ALIGN}));"); - - if (defined($struct->{PROPERTIES}{relative_base})) { - # set the current offset as base for relative pointers - # and store it based on the toplevel struct/union - $self->pidl("NDR_CHECK(ndr_pull_setup_relative_base_offset1($ndr, $varname, $ndr->offset));"); - } - - $self->ParseElementPull($_, $ndr, $env, 1, 0) foreach (@{$struct->{ELEMENTS}}); - - $self->add_deferred(); -} - -sub ParseStructPullDeferred($$$$$) -{ - my ($self,$struct,$ndr,$varname,$env) = @_; - - if (defined($struct->{PROPERTIES}{relative_base})) { - # retrieve the current offset as base for relative pointers - # based on the toplevel struct/union - $self->pidl("NDR_CHECK(ndr_pull_setup_relative_base_offset2($ndr, $varname));"); - } - foreach my $e (@{$struct->{ELEMENTS}}) { - $self->ParseElementPull($e, $ndr, $env, 0, 1); - } - - $self->add_deferred(); -} - -##################################################################### -# parse a struct - pull side -sub ParseStructPull($$$$) -{ - my($self,$struct,$ndr,$varname) = @_; - - return unless defined $struct->{ELEMENTS}; - - # declare any internal pointers we need - foreach my $e (@{$struct->{ELEMENTS}}) { - $self->DeclarePtrVariables($e); - $self->DeclareArrayVariables($e); - $self->DeclareMemCtxVariables($e); - } - - $self->start_flags($struct, $ndr); - - my $env = GenerateStructEnv($struct, $varname); - - $self->pidl("if (ndr_flags & NDR_SCALARS) {"); - $self->indent; - $self->ParseStructPullPrimitives($struct,$ndr,$varname,$env); - $self->deindent; - $self->pidl("}"); - $self->pidl("if (ndr_flags & NDR_BUFFERS) {"); - $self->indent; - $self->ParseStructPullDeferred($struct,$ndr,$varname,$env); - $self->deindent; - $self->pidl("}"); - - $self->end_flags($struct, $ndr); -} - -##################################################################### -# calculate size of ndr struct -sub ParseStructNdrSize($$$$) -{ - my ($self,$t, $name, $varname) = @_; - my $sizevar; - - if (my $flags = has_property($t, "flag")) { - $self->pidl("flags |= $flags;"); - } - $self->pidl("return ndr_size_struct($varname, flags, (ndr_push_flags_fn_t)ndr_push_$name);"); -} - -sub DeclStruct($$$$) -{ - my ($e,$t,$name,$varname) = @_; - return ($t ne "pull"?"const ":"") . "struct $name *$varname"; -} - -sub ArgsStructNdrSize($$$) -{ - my ($d, $name, $varname) = @_; - return "const struct $name *$varname, int flags"; -} - -$typefamily{STRUCT} = { - PUSH_FN_BODY => \&ParseStructPush, - DECL => \&DeclStruct, - PULL_FN_BODY => \&ParseStructPull, - PRINT_FN_BODY => \&ParseStructPrint, - SIZE_FN_BODY => \&ParseStructNdrSize, - SIZE_FN_ARGS => \&ArgsStructNdrSize, -}; - -##################################################################### -# calculate size of ndr struct -sub ParseUnionNdrSize($$$) -{ - my ($self, $t, $name, $varname) = @_; - my $sizevar; - - if (my $flags = has_property($t, "flag")) { - $self->pidl("flags |= $flags;"); - } - - $self->pidl("return ndr_size_union($varname, flags, level, (ndr_push_flags_fn_t)ndr_push_$name);"); -} - -sub ParseUnionPushPrimitives($$$$) -{ - my ($self, $e, $ndr ,$varname) = @_; - - my $have_default = 0; - - $self->pidl("int level = ndr_push_get_switch_value($ndr, $varname);"); - - if (defined($e->{SWITCH_TYPE})) { - $self->pidl("NDR_CHECK(ndr_push_$e->{SWITCH_TYPE}($ndr, NDR_SCALARS, level));"); - } - - $self->pidl("switch (level) {"); - $self->indent; - foreach my $el (@{$e->{ELEMENTS}}) { - if ($el->{CASE} eq "default") { - $have_default = 1; - } - $self->pidl("$el->{CASE}: {"); - - if ($el->{TYPE} ne "EMPTY") { - $self->indent; - if (defined($e->{PROPERTIES}{relative_base})) { - $self->pidl("NDR_CHECK(ndr_push_align($ndr, $el->{ALIGN}));"); - # set the current offset as base for relative pointers - # and store it based on the toplevel struct/union - $self->pidl("NDR_CHECK(ndr_push_setup_relative_base_offset1($ndr, $varname, $ndr->offset));"); - } - $self->DeclareArrayVariables($el); - $self->ParseElementPush($el, $ndr, {$el->{NAME} => "$varname->$el->{NAME}"}, 1, 0); - $self->deindent; - } - $self->pidl("break; }"); - $self->pidl(""); - } - if (! $have_default) { - $self->pidl("default:"); - $self->pidl("\treturn ndr_push_error($ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value \%u\", level);"); - } - $self->deindent; - $self->pidl("}"); -} - -sub ParseUnionPushDeferred($$$$) -{ - my ($self,$e,$ndr,$varname) = @_; - - my $have_default = 0; - - $self->pidl("int level = ndr_push_get_switch_value($ndr, $varname);"); - if (defined($e->{PROPERTIES}{relative_base})) { - # retrieve the current offset as base for relative pointers - # based on the toplevel struct/union - $self->pidl("NDR_CHECK(ndr_push_setup_relative_base_offset2($ndr, $varname));"); - } - $self->pidl("switch (level) {"); - $self->indent; - foreach my $el (@{$e->{ELEMENTS}}) { - if ($el->{CASE} eq "default") { - $have_default = 1; - } - - $self->pidl("$el->{CASE}:"); - if ($el->{TYPE} ne "EMPTY") { - $self->indent; - $self->ParseElementPush($el, $ndr, {$el->{NAME} => "$varname->$el->{NAME}"}, 0, 1); - $self->deindent; - } - $self->pidl("break;"); - $self->pidl(""); - } - if (! $have_default) { - $self->pidl("default:"); - $self->pidl("\treturn ndr_push_error($ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value \%u\", level);"); - } - $self->deindent; - $self->pidl("}"); -} - -##################################################################### -# parse a union - push side -sub ParseUnionPush($$$$) -{ - my ($self,$e,$ndr,$varname) = @_; - my $have_default = 0; - - $self->start_flags($e, $ndr); - - $self->pidl("if (ndr_flags & NDR_SCALARS) {"); - $self->indent; - $self->ParseUnionPushPrimitives($e, $ndr, $varname); - $self->deindent; - $self->pidl("}"); - $self->pidl("if (ndr_flags & NDR_BUFFERS) {"); - $self->indent; - $self->ParseUnionPushDeferred($e, $ndr, $varname); - $self->deindent; - $self->pidl("}"); - $self->end_flags($e, $ndr); -} - -##################################################################### -# print a union -sub ParseUnionPrint($$$$$) -{ - my ($self,$e,$ndr,$name,$varname) = @_; - my $have_default = 0; - - $self->pidl("int level;"); - foreach my $el (@{$e->{ELEMENTS}}) { - $self->DeclareArrayVariables($el); - } - - $self->start_flags($e, $ndr); - - $self->pidl("level = ndr_print_get_switch_value($ndr, $varname);"); - - $self->pidl("ndr_print_union($ndr, name, level, \"$name\");"); - - $self->pidl("switch (level) {"); - $self->indent; - foreach my $el (@{$e->{ELEMENTS}}) { - if ($el->{CASE} eq "default") { - $have_default = 1; - } - $self->pidl("$el->{CASE}:"); - if ($el->{TYPE} ne "EMPTY") { - $self->indent; - $self->ParseElementPrint($el, $ndr, "$varname->$el->{NAME}", {}); - $self->deindent; - } - $self->pidl("break;"); - $self->pidl(""); - } - if (! $have_default) { - $self->pidl("default:"); - $self->pidl("\tndr_print_bad_level($ndr, name, level);"); - } - $self->deindent; - $self->pidl("}"); - - $self->end_flags($e, $ndr); -} - -sub ParseUnionPullPrimitives($$$$$) -{ - my ($self,$e,$ndr,$varname,$switch_type) = @_; - my $have_default = 0; - - if (defined($switch_type)) { - $self->pidl("NDR_CHECK(ndr_pull_$switch_type($ndr, NDR_SCALARS, &_level));"); - $self->pidl("if (_level != level) {"); - $self->pidl("\treturn ndr_pull_error($ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value %u for $varname\", _level);"); - $self->pidl("}"); - } - - $self->pidl("switch (level) {"); - $self->indent; - foreach my $el (@{$e->{ELEMENTS}}) { - if ($el->{CASE} eq "default") { - $have_default = 1; - } - $self->pidl("$el->{CASE}: {"); - - if ($el->{TYPE} ne "EMPTY") { - $self->indent; - $self->DeclarePtrVariables($el); - $self->DeclareArrayVariables($el); - if (defined($e->{PROPERTIES}{relative_base})) { - $self->pidl("NDR_CHECK(ndr_pull_align($ndr, $el->{ALIGN}));"); - # set the current offset as base for relative pointers - # and store it based on the toplevel struct/union - $self->pidl("NDR_CHECK(ndr_pull_setup_relative_base_offset1($ndr, $varname, $ndr->offset));"); - } - $self->ParseElementPull($el, $ndr, {$el->{NAME} => "$varname->$el->{NAME}"}, 1, 0); - $self->deindent; - } - $self->pidl("break; }"); - $self->pidl(""); - } - if (! $have_default) { - $self->pidl("default:"); - $self->pidl("\treturn ndr_pull_error($ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value \%u\", level);"); - } - $self->deindent; - $self->pidl("}"); -} - -sub ParseUnionPullDeferred($$$$) -{ - my ($self,$e,$ndr,$varname) = @_; - my $have_default = 0; - - if (defined($e->{PROPERTIES}{relative_base})) { - # retrieve the current offset as base for relative pointers - # based on the toplevel struct/union - $self->pidl("NDR_CHECK(ndr_pull_setup_relative_base_offset2($ndr, $varname));"); - } - $self->pidl("switch (level) {"); - $self->indent; - foreach my $el (@{$e->{ELEMENTS}}) { - if ($el->{CASE} eq "default") { - $have_default = 1; - } - - $self->pidl("$el->{CASE}:"); - if ($el->{TYPE} ne "EMPTY") { - $self->indent; - $self->ParseElementPull($el, $ndr, {$el->{NAME} => "$varname->$el->{NAME}"}, 0, 1); - $self->deindent; - } - $self->pidl("break;"); - $self->pidl(""); - } - if (! $have_default) { - $self->pidl("default:"); - $self->pidl("\treturn ndr_pull_error($ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value \%u\", level);"); - } - $self->deindent; - $self->pidl("}"); - - -} - -##################################################################### -# parse a union - pull side -sub ParseUnionPull($$$$) -{ - my ($self,$e,$ndr,$varname) = @_; - my $switch_type = $e->{SWITCH_TYPE}; - - $self->pidl("int level;"); - if (defined($switch_type)) { - if (Parse::Pidl::Typelist::typeIs($switch_type, "ENUM")) { - $switch_type = Parse::Pidl::Typelist::enum_type_fn(getType($switch_type)->{DATA}); - } - $self->pidl(mapTypeName($switch_type) . " _level;"); - } - - my %double_cases = (); - foreach my $el (@{$e->{ELEMENTS}}) { - next if ($el->{TYPE} eq "EMPTY"); - next if ($double_cases{"$el->{NAME}"}); - $self->DeclareMemCtxVariables($el); - $double_cases{"$el->{NAME}"} = 1; - } - - $self->start_flags($e, $ndr); - - $self->pidl("level = ndr_pull_get_switch_value($ndr, $varname);"); - - $self->pidl("if (ndr_flags & NDR_SCALARS) {"); - $self->indent; - $self->ParseUnionPullPrimitives($e,$ndr,$varname,$switch_type); - $self->deindent; - $self->pidl("}"); - - $self->pidl("if (ndr_flags & NDR_BUFFERS) {"); - $self->indent; - $self->ParseUnionPullDeferred($e,$ndr,$varname); - $self->deindent; - $self->pidl("}"); - - $self->add_deferred(); - - $self->end_flags($e, $ndr); -} - -sub DeclUnion($$$$) -{ - my ($e,$t,$name,$varname) = @_; - return ($t ne "pull"?"const ":"") . "union $name *$varname"; -} - -sub ArgsUnionNdrSize($$) -{ - my ($d,$name) = @_; - return "const union $name *r, uint32_t level, int flags"; -} - -$typefamily{UNION} = { - PUSH_FN_BODY => \&ParseUnionPush, - DECL => \&DeclUnion, - PULL_FN_BODY => \&ParseUnionPull, - PRINT_FN_BODY => \&ParseUnionPrint, - SIZE_FN_ARGS => \&ArgsUnionNdrSize, - SIZE_FN_BODY => \&ParseUnionNdrSize, -}; - -##################################################################### -# parse a typedef - push side -sub ParseTypedefPush($$$$) -{ - my($self,$e,$ndr,$varname) = @_; - - my $env; - - $env->{$e->{NAME}} = $varname; - - $self->ParseElementPushLevel($e, $e->{LEVELS}[0], $ndr, $varname, $env, 1, 1); -} - -##################################################################### -# parse a typedef - pull side -sub ParseTypedefPull($$$$) -{ - my($self,$e,$ndr,$varname) = @_; - - my $env; - - $env->{$e->{NAME}} = $varname; - - $self->ParseElementPullLevel($e, $e->{LEVELS}[0], $ndr, $varname, $env, 1, 1); -} - -##################################################################### -# parse a typedef - print side -sub ParseTypedefPrint($$$$$) -{ - my($self,$e,$ndr,$name,$varname) = @_; - - $typefamily{$e->{DATA}->{TYPE}}->{PRINT_FN_BODY}->($self, $e->{DATA}, $ndr, $name, $varname); -} - -##################################################################### -## calculate the size of a structure -sub ParseTypedefNdrSize($$$$) -{ - my($self,$t,$name,$varname) = @_; - - $typefamily{$t->{DATA}->{TYPE}}->{SIZE_FN_BODY}->($self, $t->{DATA}, $name, $varname); -} - -sub DeclTypedef($$$$) -{ - my ($e, $t, $name, $varname) = @_; - - return $typefamily{$e->{DATA}->{TYPE}}->{DECL}->($e->{DATA}, $t, $name, $varname); -} - -sub ArgsTypedefNdrSize($$$) -{ - my ($d, $name, $varname) = @_; - return $typefamily{$d->{DATA}->{TYPE}}->{SIZE_FN_ARGS}->($d->{DATA}, $name, $varname); -} - -$typefamily{TYPEDEF} = { - PUSH_FN_BODY => \&ParseTypedefPush, - DECL => \&DeclTypedef, - PULL_FN_BODY => \&ParseTypedefPull, - PRINT_FN_BODY => \&ParseTypedefPrint, - SIZE_FN_ARGS => \&ArgsTypedefNdrSize, - SIZE_FN_BODY => \&ParseTypedefNdrSize, -}; - -##################################################################### -# parse a function - print side -sub ParseFunctionPrint($$) -{ - my($self, $fn) = @_; - my $ndr = "ndr"; - - $self->pidl_hdr("void ndr_print_$fn->{NAME}(struct ndr_print *$ndr, const char *name, int flags, const struct $fn->{NAME} *r);"); - - return if has_property($fn, "noprint"); - - $self->pidl("_PUBLIC_ void ndr_print_$fn->{NAME}(struct ndr_print *$ndr, const char *name, int flags, const struct $fn->{NAME} *r)"); - $self->pidl("{"); - $self->indent; - - foreach my $e (@{$fn->{ELEMENTS}}) { - $self->DeclareArrayVariables($e); - } - - $self->pidl("ndr_print_struct($ndr, name, \"$fn->{NAME}\");"); - $self->pidl("$ndr->depth++;"); - - $self->pidl("if (flags & NDR_SET_VALUES) {"); - $self->pidl("\t$ndr->flags |= LIBNDR_PRINT_SET_VALUES;"); - $self->pidl("}"); - - $self->pidl("if (flags & NDR_IN) {"); - $self->indent; - $self->pidl("ndr_print_struct($ndr, \"in\", \"$fn->{NAME}\");"); - $self->pidl("$ndr->depth++;"); - - my $env = GenerateFunctionInEnv($fn); - - foreach my $e (@{$fn->{ELEMENTS}}) { - if (grep(/in/,@{$e->{DIRECTION}})) { - $self->ParseElementPrint($e, $ndr, $env->{$e->{NAME}}, $env); - } - } - $self->pidl("$ndr->depth--;"); - $self->deindent; - $self->pidl("}"); - - $self->pidl("if (flags & NDR_OUT) {"); - $self->indent; - $self->pidl("ndr_print_struct($ndr, \"out\", \"$fn->{NAME}\");"); - $self->pidl("$ndr->depth++;"); - - $env = GenerateFunctionOutEnv($fn); - foreach my $e (@{$fn->{ELEMENTS}}) { - if (grep(/out/,@{$e->{DIRECTION}})) { - $self->ParseElementPrint($e, $ndr, $env->{$e->{NAME}}, $env); - } - } - if ($fn->{RETURN_TYPE}) { - $self->pidl("ndr_print_$fn->{RETURN_TYPE}($ndr, \"result\", r->out.result);"); - } - $self->pidl("$ndr->depth--;"); - $self->deindent; - $self->pidl("}"); - - $self->pidl("$ndr->depth--;"); - $self->deindent; - $self->pidl("}"); - $self->pidl(""); -} - -##################################################################### -# parse a function -sub ParseFunctionPush($$) -{ - my($self, $fn) = @_; - my $ndr = "ndr"; - - $self->fn_declare("push", $fn, "enum ndr_err_code ndr_push_$fn->{NAME}(struct ndr_push *$ndr, int flags, const struct $fn->{NAME} *r)") or return; - - return if has_property($fn, "nopush"); - - $self->pidl("{"); - $self->indent; - - foreach my $e (@{$fn->{ELEMENTS}}) { - $self->DeclareArrayVariables($e); - } - - $self->pidl("if (flags & NDR_IN) {"); - $self->indent; - - my $env = GenerateFunctionInEnv($fn); - - EnvSubstituteValue($env, $fn); - - foreach my $e (@{$fn->{ELEMENTS}}) { - if (grep(/in/,@{$e->{DIRECTION}})) { - $self->ParseElementPush($e, $ndr, $env, 1, 1); - } - } - - $self->deindent; - $self->pidl("}"); - - $self->pidl("if (flags & NDR_OUT) {"); - $self->indent; - - $env = GenerateFunctionOutEnv($fn); - foreach my $e (@{$fn->{ELEMENTS}}) { - if (grep(/out/,@{$e->{DIRECTION}})) { - $self->ParseElementPush($e, $ndr, $env, 1, 1); - } - } - - if ($fn->{RETURN_TYPE}) { - $self->pidl("NDR_CHECK(ndr_push_$fn->{RETURN_TYPE}($ndr, NDR_SCALARS, r->out.result));"); - } - - $self->deindent; - $self->pidl("}"); - $self->pidl("return NDR_ERR_SUCCESS;"); - $self->deindent; - $self->pidl("}"); - $self->pidl(""); -} - -sub AllocateArrayLevel($$$$$$) -{ - my ($self,$e,$l,$ndr,$var,$size) = @_; - - my $pl = GetPrevLevel($e, $l); - if (defined($pl) and - $pl->{TYPE} eq "POINTER" and - $pl->{POINTER_TYPE} eq "ref" - and not $l->{IS_ZERO_TERMINATED}) { - $self->pidl("if ($ndr->flags & LIBNDR_FLAG_REF_ALLOC) {"); - $self->pidl("\tNDR_PULL_ALLOC_N($ndr, $var, $size);"); - $self->pidl("}"); - if (grep(/in/,@{$e->{DIRECTION}}) and - grep(/out/,@{$e->{DIRECTION}})) { - $self->pidl("memcpy(r->out.$e->{NAME}, r->in.$e->{NAME}, $size * sizeof(*r->in.$e->{NAME}));"); - } - return; - } - - $self->pidl("NDR_PULL_ALLOC_N($ndr, $var, $size);"); -} - -##################################################################### -# parse a function -sub ParseFunctionPull($$) -{ - my($self,$fn) = @_; - my $ndr = "ndr"; - - # pull function args - $self->fn_declare("pull", $fn, "enum ndr_err_code ndr_pull_$fn->{NAME}(struct ndr_pull *$ndr, int flags, struct $fn->{NAME} *r)") or return; - - $self->pidl("{"); - $self->indent; - - # declare any internal pointers we need - foreach my $e (@{$fn->{ELEMENTS}}) { - $self->DeclarePtrVariables($e); - $self->DeclareArrayVariables($e); - } - - my %double_cases = (); - foreach my $e (@{$fn->{ELEMENTS}}) { - next if ($e->{TYPE} eq "EMPTY"); - next if ($double_cases{"$e->{NAME}"}); - $self->DeclareMemCtxVariables($e); - $double_cases{"$e->{NAME}"} = 1; - } - - $self->pidl("if (flags & NDR_IN) {"); - $self->indent; - - # auto-init the out section of a structure. I originally argued that - # this was a bad idea as it hides bugs, but coping correctly - # with initialisation and not wiping ref vars is turning - # out to be too tricky (tridge) - foreach my $e (@{$fn->{ELEMENTS}}) { - next unless grep(/out/, @{$e->{DIRECTION}}); - $self->pidl("ZERO_STRUCT(r->out);"); - $self->pidl(""); - last; - } - - my $env = GenerateFunctionInEnv($fn); - - foreach my $e (@{$fn->{ELEMENTS}}) { - next unless (grep(/in/, @{$e->{DIRECTION}})); - $self->ParseElementPull($e, $ndr, $env, 1, 1); - } - - # allocate the "simple" out ref variables. FIXME: Shouldn't this have it's - # own flag rather than be in NDR_IN ? - - foreach my $e (@{$fn->{ELEMENTS}}) { - next unless (grep(/out/, @{$e->{DIRECTION}})); - next unless ($e->{LEVELS}[0]->{TYPE} eq "POINTER" and - $e->{LEVELS}[0]->{POINTER_TYPE} eq "ref"); - next if (($e->{LEVELS}[1]->{TYPE} eq "DATA") and - ($e->{LEVELS}[1]->{DATA_TYPE} eq "string")); - next if (($e->{LEVELS}[1]->{TYPE} eq "ARRAY") - and $e->{LEVELS}[1]->{IS_ZERO_TERMINATED}); - - if ($e->{LEVELS}[1]->{TYPE} eq "ARRAY") { - my $size = ParseExprExt($e->{LEVELS}[1]->{SIZE_IS}, $env, $e->{ORIGINAL}, - check_null_pointer($e, $env, sub { $self->pidl(shift); }, - "return ndr_pull_error($ndr, NDR_ERR_INVALID_POINTER, \"NULL Pointer for size_is()\");"), - check_fully_dereferenced($e, $env)); - $self->pidl("NDR_PULL_ALLOC_N($ndr, r->out.$e->{NAME}, $size);"); - - if (grep(/in/, @{$e->{DIRECTION}})) { - $self->pidl("memcpy(r->out.$e->{NAME}, r->in.$e->{NAME}, ($size) * sizeof(*r->in.$e->{NAME}));"); - } else { - $self->pidl("memset(r->out.$e->{NAME}, 0, ($size) * sizeof(*r->out.$e->{NAME}));"); - } - } else { - $self->pidl("NDR_PULL_ALLOC($ndr, r->out.$e->{NAME});"); - - if (grep(/in/, @{$e->{DIRECTION}})) { - $self->pidl("*r->out.$e->{NAME} = *r->in.$e->{NAME};"); - } else { - $self->pidl("ZERO_STRUCTP(r->out.$e->{NAME});"); - } - } - } - - $self->add_deferred(); - $self->deindent; - $self->pidl("}"); - - $self->pidl("if (flags & NDR_OUT) {"); - $self->indent; - - $env = GenerateFunctionOutEnv($fn); - foreach my $e (@{$fn->{ELEMENTS}}) { - next unless grep(/out/, @{$e->{DIRECTION}}); - $self->ParseElementPull($e, $ndr, $env, 1, 1); - } - - if ($fn->{RETURN_TYPE}) { - $self->pidl("NDR_CHECK(ndr_pull_$fn->{RETURN_TYPE}($ndr, NDR_SCALARS, &r->out.result));"); - } - - $self->add_deferred(); - $self->deindent; - $self->pidl("}"); - - $self->pidl("return NDR_ERR_SUCCESS;"); - $self->deindent; - $self->pidl("}"); - $self->pidl(""); -} - -sub AuthServiceStruct($$$) -{ - my ($self, $ifacename, $authservice) = @_; - my @a = split /,/, $authservice; - my $authservice_count = $#a + 1; - - $self->pidl("static const char * const $ifacename\_authservice_strings[] = {"); - foreach my $ap (@a) { - $self->pidl("\t$ap, "); - } - $self->pidl("};"); - $self->pidl(""); - - $self->pidl("static const struct ndr_interface_string_array $ifacename\_authservices = {"); - $self->pidl("\t.count\t= $authservice_count,"); - $self->pidl("\t.names\t= $ifacename\_authservice_strings"); - $self->pidl("};"); - $self->pidl(""); -} - -sub FunctionCallEntry($$) -{ - my ($self, $d) = @_; - return if not defined($d->{OPNUM}); - $self->pidl("\t{"); - $self->pidl("\t\t\"$d->{NAME}\","); - $self->pidl("\t\tsizeof(struct $d->{NAME}),"); - $self->pidl("\t\t(ndr_push_flags_fn_t) ndr_push_$d->{NAME},"); - $self->pidl("\t\t(ndr_pull_flags_fn_t) ndr_pull_$d->{NAME},"); - $self->pidl("\t\t(ndr_print_function_t) ndr_print_$d->{NAME},"); - $self->pidl("\t\t".($d->{ASYNC}?"true":"false").","); - $self->pidl("\t},"); -} - -##################################################################### -# produce a function call table -sub FunctionTable($$) -{ - my($self,$interface) = @_; - my $count = 0; - my $uname = uc $interface->{NAME}; - - return if ($#{$interface->{FUNCTIONS}}+1 == 0); - return unless defined ($interface->{PROPERTIES}->{uuid}); - - $self->pidl("static const struct ndr_interface_call $interface->{NAME}\_calls[] = {"); - - foreach my $d (@{$interface->{INHERITED_FUNCTIONS}},@{$interface->{FUNCTIONS}}) { - $self->FunctionCallEntry($d); - $count++; - } - $self->pidl("\t{ NULL, 0, NULL, NULL, NULL, false }"); - $self->pidl("};"); - $self->pidl(""); - - $self->pidl("static const char * const $interface->{NAME}\_endpoint_strings[] = {"); - foreach my $ep (@{$interface->{ENDPOINTS}}) { - $self->pidl("\t$ep, "); - } - my $endpoint_count = $#{$interface->{ENDPOINTS}}+1; - - $self->pidl("};"); - $self->pidl(""); - - $self->pidl("static const struct ndr_interface_string_array $interface->{NAME}\_endpoints = {"); - $self->pidl("\t.count\t= $endpoint_count,"); - $self->pidl("\t.names\t= $interface->{NAME}\_endpoint_strings"); - $self->pidl("};"); - $self->pidl(""); - - if (! defined $interface->{PROPERTIES}->{authservice}) { - $interface->{PROPERTIES}->{authservice} = "\"host\""; - } - - $self->AuthServiceStruct($interface->{NAME}, - $interface->{PROPERTIES}->{authservice}); - - $self->pidl("\nconst struct ndr_interface_table ndr_table_$interface->{NAME} = {"); - $self->pidl("\t.name\t\t= \"$interface->{NAME}\","); - $self->pidl("\t.syntax_id\t= {"); - $self->pidl("\t\t" . print_uuid($interface->{UUID}) .","); - $self->pidl("\t\tNDR_$uname\_VERSION"); - $self->pidl("\t},"); - $self->pidl("\t.helpstring\t= NDR_$uname\_HELPSTRING,"); - $self->pidl("\t.num_calls\t= $count,"); - $self->pidl("\t.calls\t\t= $interface->{NAME}\_calls,"); - $self->pidl("\t.endpoints\t= &$interface->{NAME}\_endpoints,"); - $self->pidl("\t.authservices\t= &$interface->{NAME}\_authservices"); - $self->pidl("};"); - $self->pidl(""); - -} - -##################################################################### -# generate include statements for imported idl files -sub HeaderImport -{ - my $self = shift; - my @imports = @_; - foreach (@imports) { - $_ = unmake_str($_); - s/\.idl$//; - $self->pidl(choose_header("librpc/gen_ndr/ndr_$_\.h", "gen_ndr/ndr_$_.h")); - } -} - -##################################################################### -# generate include statements for included header files -sub HeaderInclude -{ - my $self = shift; - my @includes = @_; - foreach (@includes) { - $self->pidl_hdr("#include $_"); - } -} - -##################################################################### -# generate prototypes and defines for the interface definitions -# FIXME: these prototypes are for the DCE/RPC client functions, not the -# NDR parser and so do not belong here, technically speaking -sub HeaderInterface($$$) -{ - my($self,$interface,$needed) = @_; - - my $count = 0; - - if ($needed->{"compression"}) { - $self->pidl(choose_header("librpc/ndr/ndr_compression.h", "ndr/compression.h")); - } - - if (has_property($interface, "object")) { - $self->pidl(choose_header("librpc/gen_ndr/ndr_orpc.h", "ndr/orpc.h")); - } - - if (defined $interface->{PROPERTIES}->{helper}) { - $self->HeaderInclude(split /,/, $interface->{PROPERTIES}->{helper}); - } - - if (defined $interface->{PROPERTIES}->{uuid}) { - my $name = uc $interface->{NAME}; - $self->pidl_hdr("#define NDR_$name\_UUID " . - Parse::Pidl::Util::make_str(lc($interface->{PROPERTIES}->{uuid}))); - - if(!defined $interface->{PROPERTIES}->{version}) { $interface->{PROPERTIES}->{version} = "0.0"; } - $self->pidl_hdr("#define NDR_$name\_VERSION $interface->{PROPERTIES}->{version}"); - - $self->pidl_hdr("#define NDR_$name\_NAME \"$interface->{NAME}\""); - - if(!defined $interface->{PROPERTIES}->{helpstring}) { $interface->{PROPERTIES}->{helpstring} = "NULL"; } - $self->pidl_hdr("#define NDR_$name\_HELPSTRING $interface->{PROPERTIES}->{helpstring}"); - - $self->pidl_hdr("extern const struct ndr_interface_table ndr_table_$interface->{NAME};"); - } - - foreach (@{$interface->{FUNCTIONS}}) { - next if has_property($_, "noopnum"); - next if grep(/^$_->{NAME}$/,@{$interface->{INHERITED_FUNCTIONS}}); - my $u_name = uc $_->{NAME}; - - my $val = sprintf("0x%02x", $count); - if (defined($interface->{BASE})) { - $val .= " + NDR_" . uc $interface->{BASE} . "_CALL_COUNT"; - } - - $self->pidl_hdr("#define NDR_$u_name ($val)"); - - $self->pidl_hdr(""); - $count++; - } - - my $val = $count; - - if (defined($interface->{BASE})) { - $val .= " + NDR_" . uc $interface->{BASE} . "_CALL_COUNT"; - } - - $self->pidl_hdr("#define NDR_" . uc $interface->{NAME} . "_CALL_COUNT ($val)"); - -} - -sub ParseTypePush($$$$$$) -{ - my ($self,$e, $ndr, $varname, $primitives, $deferred) = @_; - - # save the old relative_base_offset - $self->pidl("uint32_t _save_relative_base_offset = ndr_push_get_relative_base_offset($ndr);") if defined(has_property($e, "relative_base")); - $typefamily{$e->{TYPE}}->{PUSH_FN_BODY}->($self, $e, $ndr, $varname); - # restore the old relative_base_offset - $self->pidl("ndr_push_restore_relative_base_offset($ndr, _save_relative_base_offset);") if defined(has_property($e, "relative_base")); -} - -sub ParseTypePushFunction($$$) -{ - my ($self, $e, $varname) = @_; - my $ndr = "ndr"; - - my $args = $typefamily{$e->{TYPE}}->{DECL}->($e, "push", $e->{NAME}, $varname); - - $self->fn_declare("push", $e, "enum ndr_err_code ".TypeFunctionName("ndr_push", $e)."(struct ndr_push *$ndr, int ndr_flags, $args)") or return; - - $self->pidl("{"); - $self->indent; - $self->ParseTypePush($e, $ndr, $varname, 1, 1); - $self->pidl("return NDR_ERR_SUCCESS;"); - $self->deindent; - $self->pidl("}"); - $self->pidl("");; -} - -sub ParseTypePull($$$$$$) -{ - my ($self, $e, $ndr, $varname, $primitives, $deferred) = @_; - - # save the old relative_base_offset - $self->pidl("uint32_t _save_relative_base_offset = ndr_pull_get_relative_base_offset($ndr);") if defined(has_property($e, "relative_base")); - $typefamily{$e->{TYPE}}->{PULL_FN_BODY}->($self, $e, $ndr, $varname); - # restore the old relative_base_offset - $self->pidl("ndr_pull_restore_relative_base_offset($ndr, _save_relative_base_offset);") if defined(has_property($e, "relative_base")); -} - -sub ParseTypePullFunction($$) -{ - my ($self, $e, $varname) = @_; - my $ndr = "ndr"; - - my $args = $typefamily{$e->{TYPE}}->{DECL}->($e, "pull", $e->{NAME}, $varname); - - $self->fn_declare("pull", $e, "enum ndr_err_code ".TypeFunctionName("ndr_pull", $e)."(struct ndr_pull *$ndr, int ndr_flags, $args)") or return; - - $self->pidl("{"); - $self->indent; - $self->ParseTypePull($e, $ndr, $varname, 1, 1); - $self->pidl("return NDR_ERR_SUCCESS;"); - $self->deindent; - $self->pidl("}"); - $self->pidl(""); -} - -sub ParseTypePrint($$$$) -{ - my ($self, $e, $ndr, $varname) = @_; - - $typefamily{$e->{TYPE}}->{PRINT_FN_BODY}->($self, $e, $ndr, $e->{NAME}, $varname); -} - -sub ParseTypePrintFunction($$$) -{ - my ($self, $e, $varname) = @_; - my $ndr = "ndr"; - - my $args = $typefamily{$e->{TYPE}}->{DECL}->($e, "print", $e->{NAME}, $varname); - - $self->pidl_hdr("void ".TypeFunctionName("ndr_print", $e)."(struct ndr_print *ndr, const char *name, $args);"); - - return if (has_property($e, "noprint")); - - $self->pidl("_PUBLIC_ void ".TypeFunctionName("ndr_print", $e)."(struct ndr_print *$ndr, const char *name, $args)"); - $self->pidl("{"); - $self->indent; - $self->ParseTypePrint($e, $ndr, $varname); - $self->deindent; - $self->pidl("}"); - $self->pidl(""); -} - -sub ParseTypeNdrSize($$) -{ - my ($self,$t) = @_; - - my $varname = "r"; - my $tf = $typefamily{$t->{TYPE}}; - my $args = $tf->{SIZE_FN_ARGS}->($t, $t->{NAME}, $varname); - - $self->fn_declare("size", $t, "size_t ndr_size_$t->{NAME}($args)") or return; - - $self->pidl("{"); - $self->indent; - $typefamily{$t->{TYPE}}->{SIZE_FN_BODY}->($self,$t, $t->{NAME}, $varname); - $self->deindent; - $self->pidl("}"); - $self->pidl(""); -} - -##################################################################### -# parse the interface definitions -sub ParseInterface($$$) -{ - my($self,$interface,$needed) = @_; - - $self->pidl_hdr("#ifndef _HEADER_NDR_$interface->{NAME}"); - $self->pidl_hdr("#define _HEADER_NDR_$interface->{NAME}"); - - $self->pidl_hdr(""); - - $self->HeaderInterface($interface, $needed); - - # Typedefs - foreach my $d (@{$interface->{TYPES}}) { - next unless(typeHasBody($d)); - - ($needed->{TypeFunctionName("ndr_push", $d)}) && $self->ParseTypePushFunction($d, "r"); - ($needed->{TypeFunctionName("ndr_pull", $d)}) && $self->ParseTypePullFunction($d, "r"); - ($needed->{TypeFunctionName("ndr_print", $d)}) && $self->ParseTypePrintFunction($d, "r"); - - # Make sure we don't generate a function twice... - $needed->{TypeFunctionName("ndr_push", $d)} = - $needed->{TypeFunctionName("ndr_pull", $d)} = - $needed->{TypeFunctionName("ndr_print", $d)} = 0; - - ($needed->{"ndr_size_$d->{NAME}"}) && $self->ParseTypeNdrSize($d); - } - - # Functions - foreach my $d (@{$interface->{FUNCTIONS}}) { - ($needed->{"ndr_push_$d->{NAME}"}) && $self->ParseFunctionPush($d); - ($needed->{"ndr_pull_$d->{NAME}"}) && $self->ParseFunctionPull($d); - ($needed->{"ndr_print_$d->{NAME}"}) && $self->ParseFunctionPrint($d); - - # Make sure we don't generate a function twice... - $needed->{"ndr_push_$d->{NAME}"} = $needed->{"ndr_pull_$d->{NAME}"} = - $needed->{"ndr_print_$d->{NAME}"} = 0; - } - - $self->FunctionTable($interface); - - $self->pidl_hdr("#endif /* _HEADER_NDR_$interface->{NAME} */"); -} - -sub GenerateIncludes($) -{ - my ($self) = @_; - if (is_intree()) { - $self->pidl("#include \"includes.h\""); - } else { - $self->pidl("#define _GNU_SOURCE"); - $self->pidl("#include <stdint.h>"); - $self->pidl("#include <stdlib.h>"); - $self->pidl("#include <stdio.h>"); - $self->pidl("#include <stdbool.h>"); - $self->pidl("#include <stdarg.h>"); - $self->pidl("#include <string.h>"); - } -} - -##################################################################### -# parse a parsed IDL structure back into an IDL file -sub Parse($$$$) -{ - my($self, $ndr,$gen_header,$ndr_header) = @_; - - $self->pidl_hdr("/* header auto-generated by pidl */"); - $self->pidl_hdr(""); - $self->pidl_hdr(choose_header("librpc/ndr/libndr.h", "ndr.h")); - $self->pidl_hdr("#include \"$gen_header\"") if ($gen_header); - $self->pidl_hdr(""); - - $self->pidl("/* parser auto-generated by pidl */"); - $self->pidl(""); - $self->GenerateIncludes(); - $self->pidl("#include \"$ndr_header\"") if ($ndr_header); - $self->pidl(""); - - my %needed = (); - - foreach (@{$ndr}) { - ($_->{TYPE} eq "INTERFACE") && NeededInterface($_, \%needed); - } - - foreach (@{$ndr}) { - ($_->{TYPE} eq "INTERFACE") && $self->ParseInterface($_, \%needed); - ($_->{TYPE} eq "IMPORT") && $self->HeaderImport(@{$_->{PATHS}}); - ($_->{TYPE} eq "INCLUDE") && $self->HeaderInclude(@{$_->{PATHS}}); - } - - return ($self->{res_hdr}, $self->{res}); -} - -sub NeededElement($$$) -{ - my ($e, $dir, $needed) = @_; - - return if ($e->{TYPE} eq "EMPTY"); - - return if (ref($e->{TYPE}) eq "HASH" and - not defined($e->{TYPE}->{NAME})); - - my ($t, $rt); - if (ref($e->{TYPE}) eq "HASH") { - $t = $e->{TYPE}->{TYPE}."_".$e->{TYPE}->{NAME}; - } else { - $t = $e->{TYPE}; - } - - if (ref($e->{REPRESENTATION_TYPE}) eq "HASH") { - $rt = $e->{REPRESENTATION_TYPE}->{TYPE}."_".$e->{REPRESENTATION_TYPE}->{NAME}; - } else { - $rt = $e->{REPRESENTATION_TYPE}; - } - - die ("$e->{NAME} $t, $rt FOO") unless ($rt ne ""); - - my @fn = (); - if ($dir eq "print") { - push(@fn, TypeFunctionName("ndr_print", $e->{REPRESENTATION_TYPE})); - } elsif ($dir eq "pull") { - push (@fn, TypeFunctionName("ndr_pull", $e->{TYPE})); - push (@fn, "ndr_$t\_to_$rt") - if ($rt ne $t); - } elsif ($dir eq "push") { - push (@fn, TypeFunctionName("ndr_push", $e->{TYPE})); - push (@fn, "ndr_$rt\_to_$t") - if ($rt ne $t); - } else { - die("invalid direction `$dir'"); - } - - foreach (@fn) { - unless (defined($needed->{$_})) { - $needed->{$_} = 1; - } - } -} - -sub NeededFunction($$) -{ - my ($fn,$needed) = @_; - $needed->{"ndr_pull_$fn->{NAME}"} = 1; - $needed->{"ndr_push_$fn->{NAME}"} = 1; - $needed->{"ndr_print_$fn->{NAME}"} = 1; - foreach my $e (@{$fn->{ELEMENTS}}) { - $e->{PARENT} = $fn; - NeededElement($e, $_, $needed) foreach ("pull", "push", "print"); - } -} - -sub NeededType($$$) -{ - sub NeededType($$$); - my ($t,$needed,$req) = @_; - - NeededType($t->{DATA}, $needed, $req) if ($t->{TYPE} eq "TYPEDEF"); - - if ($t->{TYPE} eq "STRUCT" or $t->{TYPE} eq "UNION") { - return unless defined($t->{ELEMENTS}); - for my $e (@{$t->{ELEMENTS}}) { - $e->{PARENT} = $t; - if (has_property($e, "compression")) { - $needed->{"compression"} = 1; - } - NeededElement($e, $req, $needed); - NeededType($e->{TYPE}, $needed, $req) if (ref($e->{TYPE}) eq "HASH"); - } - } -} - -##################################################################### -# work out what parse functions are needed -sub NeededInterface($$) -{ - my ($interface,$needed) = @_; - NeededFunction($_, $needed) foreach (@{$interface->{FUNCTIONS}}); - foreach (reverse @{$interface->{TYPES}}) { - if (has_property($_, "public")) { - $needed->{TypeFunctionName("ndr_pull", $_)} = $needed->{TypeFunctionName("ndr_push", $_)} = - $needed->{TypeFunctionName("ndr_print", $_)} = 1; - } - - NeededType($_, $needed, "pull") if ($needed->{TypeFunctionName("ndr_pull", $_)}); - NeededType($_, $needed, "push") if ($needed->{TypeFunctionName("ndr_push", $_)}); - NeededType($_, $needed, "print") if ($needed->{TypeFunctionName("ndr_print", $_)}); - if (has_property($_, "gensize")) { - $needed->{"ndr_size_$_->{NAME}"} = 1; - } - } -} - -sub TypeFunctionName($$) -{ - my ($prefix, $t) = @_; - - return "$prefix\_$t->{NAME}" if (ref($t) eq "HASH" and - $t->{TYPE} eq "TYPEDEF"); - return "$prefix\_$t->{TYPE}_$t->{NAME}" if (ref($t) eq "HASH"); - return "$prefix\_$t"; -} - -1; diff --git a/source4/pidl/lib/Parse/Pidl/Samba4/NDR/Server.pm b/source4/pidl/lib/Parse/Pidl/Samba4/NDR/Server.pm deleted file mode 100644 index e30102b4e1..0000000000 --- a/source4/pidl/lib/Parse/Pidl/Samba4/NDR/Server.pm +++ /dev/null @@ -1,328 +0,0 @@ -################################################### -# server boilerplate generator -# Copyright tridge@samba.org 2003 -# Copyright metze@samba.org 2004 -# released under the GNU GPL - -package Parse::Pidl::Samba4::NDR::Server; - -use strict; -use Parse::Pidl::Util; - -use vars qw($VERSION); -$VERSION = '0.01'; - -my($res); - -sub pidl($) -{ - $res .= shift; -} - - -##################################################### -# generate the switch statement for function dispatch -sub gen_dispatch_switch($) -{ - my $interface = shift; - - foreach my $fn (@{$interface->{FUNCTIONS}}) { - next if not defined($fn->{OPNUM}); - - pidl "\tcase $fn->{OPNUM}: {\n"; - pidl "\t\tstruct $fn->{NAME} *r2 = (struct $fn->{NAME} *)r;\n"; - pidl "\t\tif (DEBUGLEVEL >= 10) {\n"; - pidl "\t\t\tNDR_PRINT_FUNCTION_DEBUG($fn->{NAME}, NDR_IN, r2);\n"; - pidl "\t\t}\n"; - if ($fn->{RETURN_TYPE} && $fn->{RETURN_TYPE} ne "void") { - pidl "\t\tr2->out.result = dcesrv_$fn->{NAME}(dce_call, mem_ctx, r2);\n"; - } else { - pidl "\t\tdcesrv_$fn->{NAME}(dce_call, mem_ctx, r2);\n"; - } - pidl "\t\tif (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {\n"; - pidl "\t\t\tDEBUG(5,(\"function $fn->{NAME} will reply async\\n\"));\n"; - pidl "\t\t}\n"; - pidl "\t\tbreak;\n\t}\n"; - } -} - -##################################################### -# generate the switch statement for function reply -sub gen_reply_switch($) -{ - my $interface = shift; - - foreach my $fn (@{$interface->{FUNCTIONS}}) { - next if not defined($fn->{OPNUM}); - - pidl "\tcase $fn->{OPNUM}: {\n"; - pidl "\t\tstruct $fn->{NAME} *r2 = (struct $fn->{NAME} *)r;\n"; - pidl "\t\tif (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {\n"; - pidl "\t\t\tDEBUG(5,(\"function $fn->{NAME} replied async\\n\"));\n"; - pidl "\t\t}\n"; - pidl "\t\tif (DEBUGLEVEL >= 10 && dce_call->fault_code == 0) {\n"; - pidl "\t\t\tNDR_PRINT_FUNCTION_DEBUG($fn->{NAME}, NDR_OUT | NDR_SET_VALUES, r2);\n"; - pidl "\t\t}\n"; - pidl "\t\tif (dce_call->fault_code != 0) {\n"; - pidl "\t\t\tDEBUG(2,(\"dcerpc_fault %s in $fn->{NAME}\\n\", dcerpc_errstr(mem_ctx, dce_call->fault_code)));\n"; - pidl "\t\t}\n"; - pidl "\t\tbreak;\n\t}\n"; - } -} - -##################################################################### -# produce boilerplate code for a interface -sub Boilerplate_Iface($) -{ - my($interface) = shift; - my $name = $interface->{NAME}; - my $uname = uc $name; - my $uuid = lc($interface->{PROPERTIES}->{uuid}); - my $if_version = $interface->{PROPERTIES}->{version}; - - 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_context *context, const struct dcesrv_interface *iface) -{ -#ifdef DCESRV_INTERFACE_$uname\_UNBIND - DCESRV_INTERFACE_$uname\_UNBIND(context, iface); -#else - return; -#endif -} - -static NTSTATUS $name\__op_ndr_pull(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct ndr_pull *pull, void **r) -{ - enum ndr_err_code ndr_err; - uint16_t opnum = dce_call->pkt.u.request.opnum; - - dce_call->fault_code = 0; - - if (opnum >= ndr_table_$name.num_calls) { - dce_call->fault_code = DCERPC_FAULT_OP_RNG_ERROR; - return NT_STATUS_NET_WRITE_FAULT; - } - - *r = talloc_named(mem_ctx, - ndr_table_$name.calls[opnum].struct_size, - \"struct %s\", - ndr_table_$name.calls[opnum].name); - NT_STATUS_HAVE_NO_MEMORY(*r); - - /* unravel the NDR for the packet */ - ndr_err = ndr_table_$name.calls[opnum].ndr_pull(pull, NDR_IN, *r); - if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { - dcerpc_log_packet(&ndr_table_$name, opnum, NDR_IN, - &dce_call->pkt.u.request.stub_and_verifier); - dce_call->fault_code = DCERPC_FAULT_NDR; - return NT_STATUS_NET_WRITE_FAULT; - } - - return NT_STATUS_OK; -} - -static NTSTATUS $name\__op_dispatch(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, void *r) -{ - uint16_t opnum = dce_call->pkt.u.request.opnum; - - switch (opnum) { -"; - gen_dispatch_switch($interface); - -pidl " - default: - dce_call->fault_code = DCERPC_FAULT_OP_RNG_ERROR; - break; - } - - if (dce_call->fault_code != 0) { - dcerpc_log_packet(&ndr_table_$name, opnum, NDR_IN, - &dce_call->pkt.u.request.stub_and_verifier); - return NT_STATUS_NET_WRITE_FAULT; - } - - return NT_STATUS_OK; -} - -static NTSTATUS $name\__op_reply(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, void *r) -{ - uint16_t opnum = dce_call->pkt.u.request.opnum; - - switch (opnum) { -"; - gen_reply_switch($interface); - -pidl " - default: - dce_call->fault_code = DCERPC_FAULT_OP_RNG_ERROR; - break; - } - - if (dce_call->fault_code != 0) { - dcerpc_log_packet(&ndr_table_$name, opnum, NDR_IN, - &dce_call->pkt.u.request.stub_and_verifier); - return NT_STATUS_NET_WRITE_FAULT; - } - - return NT_STATUS_OK; -} - -static NTSTATUS $name\__op_ndr_push(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct ndr_push *push, const void *r) -{ - enum ndr_err_code ndr_err; - uint16_t opnum = dce_call->pkt.u.request.opnum; - - ndr_err = ndr_table_$name.calls[opnum].ndr_push(push, NDR_OUT, r); - if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { - dce_call->fault_code = DCERPC_FAULT_NDR; - return NT_STATUS_NET_WRITE_FAULT; - } - - return NT_STATUS_OK; -} - -const struct dcesrv_interface dcesrv\_$name\_interface = { - .name = \"$name\", - .syntax_id = {".print_uuid($uuid).",$if_version}, - .bind = $name\__op_bind, - .unbind = $name\__op_unbind, - .ndr_pull = $name\__op_ndr_pull, - .dispatch = $name\__op_dispatch, - .reply = $name\__op_reply, - .ndr_push = $name\__op_ndr_push -}; - -"; -} - -##################################################################### -# produce boilerplate code for an endpoint server -sub Boilerplate_Ep_Server($) -{ - my($interface) = shift; - my $name = $interface->{NAME}; - my $uname = uc $name; - - 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<ndr_table_$name.endpoints->count;i++) { - NTSTATUS ret; - const char *name = ndr_table_$name.endpoints->names[i]; - - ret = dcesrv_interface_register(dce_ctx, name, &dcesrv_$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 struct GUID *uuid, uint32_t if_version) -{ - if (dcesrv_$name\_interface.syntax_id.if_version == if_version && - GUID_equal(\&dcesrv\_$name\_interface.syntax_id.uuid, uuid)) { - memcpy(iface,&dcesrv\_$name\_interface, sizeof(*iface)); - return true; - } - - return false; -} - -static bool $name\__op_interface_by_name(struct dcesrv_interface *iface, const char *name) -{ - if (strcmp(dcesrv_$name\_interface.name, name)==0) { - memcpy(iface, &dcesrv_$name\_interface, sizeof(*iface)); - return true; - } - - return false; -} - -NTSTATUS dcerpc_server_$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 = dcerpc_register_ep_server(&ep_server); - - if (!NT_STATUS_IS_OK(ret)) { - DEBUG(0,(\"Failed to register \'$name\' endpoint server!\\n\")); - return ret; - } - - return ret; -} - -"; -} - -##################################################################### -# dcerpc server boilerplate from a parsed IDL structure -sub ParseInterface($) -{ - my($interface) = shift; - my $count = 0; - - if (!defined $interface->{PROPERTIES}->{uuid}) { - return $res; - } - - if (!defined $interface->{PROPERTIES}->{version}) { - $interface->{PROPERTIES}->{version} = "0.0"; - } - - foreach my $fn (@{$interface->{FUNCTIONS}}) { - if (defined($fn->{OPNUM})) { $count++; } - } - - if ($count == 0) { - return $res; - } - - $res .= "/* $interface->{NAME} - dcerpc server boilerplate generated by pidl */\n\n"; - Boilerplate_Iface($interface); - Boilerplate_Ep_Server($interface); - - return $res; -} - -sub Parse($$) -{ - my($ndr,$header) = @_; - - $res = ""; - $res .= "/* server functions auto-generated by pidl */\n"; - $res .= "#include \"$header\"\n"; - $res .= "\n"; - - foreach my $x (@{$ndr}) { - ParseInterface($x) if ($x->{TYPE} eq "INTERFACE" and not defined($x->{PROPERTIES}{object})); - } - - return $res; -} - -1; |