r15437: Add generator that creates Samba3 client code which uses Samba4's NDR
authorJelmer Vernooij <jelmer@samba.org>
Thu, 4 May 2006 16:04:08 +0000 (16:04 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 19:05:37 +0000 (14:05 -0500)
routines.
(This used to be commit 538be4a6319b6f8235ed450740784104671ab0b5)

source4/pidl/lib/Parse/Pidl/Samba3/ClientNDR.pm [new file with mode: 0644]
source4/pidl/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 (file)
index 0000000..ec3287f
--- /dev/null
@@ -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;
index 314ab7c60b190f92cddc5aa38af82240d642abd9..5784822f2690cf40a22c822e5720ed7147d00cfa 100755 (executable)
@@ -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]] [<idlfile>.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]] [<idlfile>.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) {