From e81fd2e11918a775175a91744bced45689343914 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Thu, 4 May 2006 16:04:08 +0000 Subject: r15437: Add generator that creates Samba3 client code which uses Samba4's NDR routines. (This used to be commit 538be4a6319b6f8235ed450740784104671ab0b5) --- source4/pidl/lib/Parse/Pidl/Samba3/ClientNDR.pm | 136 ++++++++++++++++++++++++ source4/pidl/pidl | 29 ++++- 2 files changed, 162 insertions(+), 3 deletions(-) create mode 100644 source4/pidl/lib/Parse/Pidl/Samba3/ClientNDR.pm (limited to 'source4/pidl') diff --git a/source4/pidl/lib/Parse/Pidl/Samba3/ClientNDR.pm b/source4/pidl/lib/Parse/Pidl/Samba3/ClientNDR.pm new file mode 100644 index 0000000000..ec3287ffb0 --- /dev/null +++ b/source4/pidl/lib/Parse/Pidl/Samba3/ClientNDR.pm @@ -0,0 +1,136 @@ +################################################### +# Samba3 client generator for IDL structures +# on top of Samba4 style NDR functions +# Copyright jelmer@samba.org 2005-2006 +# released under the GNU GPL + +package Parse::Pidl::Samba3::ClientNDR; + +use strict; +use Parse::Pidl::Typelist qw(hasType getType mapType); +use Parse::Pidl::Util qw(has_property ParseExpr); +use Parse::Pidl::NDR qw(GetPrevLevel GetNextLevel ContainsDeferred); +use Parse::Pidl::Samba3::Types qw(DeclLong); + +use vars qw($VERSION); +$VERSION = '0.01'; + +my $res = ""; +my $tabs = ""; +sub indent() { $tabs.="\t"; } +sub deindent() { $tabs = substr($tabs, 1); } +sub pidl($) { $res .= $tabs.(shift)."\n"; } +sub fatal($$) { my ($e,$s) = @_; die("$e->{ORIGINAL}->{FILE}:$e->{ORIGINAL}->{LINE}: $s\n"); } +sub warning($$) { my ($e,$s) = @_; warn("$e->{ORIGINAL}->{FILE}:$e->{ORIGINAL}->{LINE}: $s\n"); } + +sub CopyLevel($$$$) +{ + sub CopyLevel($$$$); + my ($e,$l,$argument,$member) = @_; + + if ($l->{TYPE} eq "DATA") { + pidl "*$argument = *$member;"; + } elsif ($l->{TYPE} eq "POINTER") { + pidl "if (r.ptr$l->{POINTER_INDEX}_$e->{NAME}) {"; + indent; + pidl "*$argument = talloc_size(mem_ctx, sizeof(void *));"; + CopyLevel($e,GetNextLevel($e,$l),"*$argument", $member); + deindent; + pidl "}"; + } elsif ($l->{TYPE} eq "SWITCH") { + CopyLevel($e,GetNextLevel($e,$l),$argument,$member); + } elsif ($l->{TYPE} eq "ARRAY") { + pidl "*$argument = $member;"; + } +} + +sub ParseFunction($$) +{ + my ($if,$fn) = @_; + + my $inargs = ""; + my $defargs = ""; + my $uif = uc($if->{NAME}); + my $ufn = uc($fn->{NAME}); + + foreach (@{$fn->{ELEMENTS}}) { + $defargs .= ", " . DeclLong($_); + } + pidl "NTSTATUS rpccli_$fn->{NAME}(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx$defargs)"; + pidl "{"; + indent; + pidl "struct $fn->{NAME} r;"; + pidl "NTSTATUS status;"; + pidl ""; + pidl "/* In parameters */"; + + foreach (@{$fn->{ELEMENTS}}) { + if (grep(/in/, @{$_->{DIRECTION}})) { + pidl "r.in.$_->{NAME} = $_->{NAME};"; + } + } + + pidl "status = cli_do_rpc_ndr(cli, mem_ctx, PI_$uif, $ufn, &r, ndr_pull_$fn->{NAME}, ndr_push_$fn->{NAME});"; + pidl "if (NT_STATUS_IS_ERR(status)) {"; + pidl "\treturn status;"; + pidl "}"; + pidl ""; + pidl "/* Return variables */"; + foreach my $e (@{$fn->{ELEMENTS}}) { + next unless (grep(/out/, @{$e->{DIRECTION}})); + + if ($e->{LEVELS}[0]->{TYPE} ne "POINTER") { + warning($e, "First element not a pointer for [out] argument"); + next; + } + + CopyLevel($e, $e->{LEVELS}[1], $e->{NAME}, "r.out.$e->{NAME}"); + } + + pidl""; + pidl "/* Return result */"; + if (not $fn->{RETURN_TYPE}) { + pidl "return NT_STATUS_OK;"; + } elsif ($fn->{RETURN_TYPE} eq "NTSTATUS") { + pidl "return r.status;"; + } elsif ($fn->{RETURN_TYPE} eq "WERROR") { + pidl "return werror_to_ntstatus(r.status);"; + } else { + pidl "/* Sorry, don't know how to convert $fn->{RETURN_TYPE} to NTSTATUS */"; + pidl "return NT_STATUS_OK;"; + } + + deindent; + pidl "}"; + pidl ""; +} + +sub ParseInterface($) +{ + my $if = shift; + + ParseFunction($if, $_) foreach (@{$if->{FUNCTIONS}}); +} + +sub Parse($$) +{ + my($ndr,$filename) = @_; + + $res = ""; + + pidl "/*"; + pidl " * Unix SMB/CIFS implementation."; + pidl " * client auto-generated by pidl. DO NOT MODIFY!"; + pidl " */"; + pidl ""; + pidl "#include \"includes.h\""; + pidl ""; + + foreach (@$ndr) { + ParseInterface($_) if ($_->{TYPE} eq "INTERFACE"); + } + + return $res; +} + +1; diff --git a/source4/pidl/pidl b/source4/pidl/pidl index 314ab7c60b..5784822f26 100755 --- a/source4/pidl/pidl +++ b/source4/pidl/pidl @@ -17,7 +17,7 @@ pidl - An IDL compiler written in Perl pidl --help -pidl [--outputdir[=OUTNAME]] [--parse-idl-tree] [--dump-idl-tree] [--dump-ndr-tree] [--header[=OUTPUT]] [--ejs[=OUTPUT]] [--swig[=OUTPUT]] [--uint-enums] [--ndr-parser[=OUTPUT]] [--client] [--server] [--dcom-proxy] [--com-header] [--warn-compat] [--quiet] [--verbose] [--template] [--eth-parser[=OUTPUT]] [--diff] [--dump-idl] [--tdr-parser[=OUTPUT]] [--samba3-header[=OUTPUT]] [--samba3-parser=[OUTPUT]] [--samba3-server=[OUTPUT]] [--samba3-template[=OUTPUT]] [--samba3-client[=OUTPUT]] [.idl]... +pidl [--outputdir[=OUTNAME]] [--parse-idl-tree] [--dump-idl-tree] [--dump-ndr-tree] [--header[=OUTPUT]] [--ejs[=OUTPUT]] [--swig[=OUTPUT]] [--uint-enums] [--ndr-parser[=OUTPUT]] [--client] [--server] [--dcom-proxy] [--com-header] [--warn-compat] [--quiet] [--verbose] [--template] [--eth-parser[=OUTPUT]] [--diff] [--dump-idl] [--tdr-parser[=OUTPUT]] [--samba3-header[=OUTPUT]] [--samba3-parser=[OUTPUT]] [--samba3-server=[OUTPUT]] [--samba3-template[=OUTPUT]] [--samba3-client[=OUTPUT]] [--samba3-ndr-client[=OUTPUT]] [.idl]... =head1 DESCRIPTION @@ -144,6 +144,12 @@ rpc_server/. Filename defaults to srv_BASENAME_nt.c Generate client calls for Samba 3, to be placed in rpc_client/. Filename defaults to cli_BASENAME.c. +=item I<--samba3-ndr-client> + +Generate client calls for Samba3, to be placed in rpc_client/. Instead of +calling out to the code in Samba3's rpc_parse/, this will call out to +Samba4's NDR code instead. + =back =head1 IDL SYNTAX @@ -465,6 +471,7 @@ my($opt_samba3_parser); my($opt_samba3_server); my($opt_samba3_template); my($opt_samba3_client); +my($opt_samba3_ndr_client); my($opt_template) = 0; my($opt_client); my($opt_server); @@ -523,6 +530,8 @@ Samba 3 output: --samba3-template[=OUTF]create template implementation [srv_BASENAME_nt.c] --samba3-server[=OUTF] create server side wrappers for Samba3 [srv_BASENAME.c] --samba3-client[=OUTF] create client calls for Samba3 [cli_BASENAME.c] + --samba3-ndr-client[=OUTF] create client calls for Samba3 + using Samba4's NDR code [cli_BASENAME.c] Ethereal parsers: --eth-parser[=OUTFILE] create ethereal parser and header @@ -544,6 +553,7 @@ my $result = GetOptions ( 'samba3-server:s' => \$opt_samba3_server, 'samba3-template:s' => \$opt_samba3_template, 'samba3-client:s' => \$opt_samba3_client, + 'samba3-ndr-client:s' => \$opt_samba3_ndr_client, 'header:s' => \$opt_header, 'server:s' => \$opt_server, 'tdr-parser:s' => \$opt_tdr_parser, @@ -570,6 +580,11 @@ if ($opt_help) { exit(0); } +if ($opt_samba3_client and $opt_samba3_ndr_client) { + print "--samba3-client and --samba3-ndr-client can not be used together\n"; + exit(1); +} + sub process_file($) { my $idl_file = shift; @@ -645,7 +660,8 @@ sub process_file($) defined($opt_ndr_parser) or defined($opt_ejs) or defined($opt_dump_ndr_tree) or defined($opt_samba3_header) or defined($opt_samba3_parser) or defined($opt_samba3_server) or - defined($opt_samba3_template) or defined($opt_samba3_client)) { + defined($opt_samba3_template) or defined($opt_samba3_client) or + defined($opt_samba3_ndr_client)) { require Parse::Pidl::NDR; $ndr = Parse::Pidl::NDR::Parse($pidl); } @@ -756,7 +772,7 @@ $dcom if (defined($opt_samba3_header) or defined($opt_samba3_parser) or defined($opt_samba3_server) or defined($opt_samba3_client) or - defined($opt_samba3_template)) { + defined($opt_samba3_ndr_client) or defined($opt_samba3_template)) { require Parse::Pidl::Samba3::Types; Parse::Pidl::Samba3::Types::LoadTypes($ndr); } @@ -791,6 +807,13 @@ $dcom FileSave($header, Parse::Pidl::Samba3::Client::Parse($ndr, $basename)); } + if (defined($opt_samba3_ndr_client)) { + my $header = ($opt_samba3_ndr_client or "$outputdir/cli_$basename.c"); + require Parse::Pidl::Samba3::ClientNDR; + FileSave($header, Parse::Pidl::Samba3::ClientNDR::Parse($ndr, $basename)); + } + + } if (scalar(@ARGV) == 0) { -- cgit