r7160: Initial work on an esp function wrapper generator
[samba.git] / source / build / pidl / pidl.pl
1 #!/usr/bin/perl -w
2
3 ###################################################
4 # package to parse IDL files and generate code for
5 # rpc functions in Samba
6 # Copyright tridge@samba.org 2000-2003
7 # Copyright jelmer@samba.org 2005
8 # released under the GNU GPL
9
10 use strict;
11
12 use FindBin qw($RealBin);
13 use lib "$RealBin/..";
14 use Getopt::Long;
15 use File::Basename;
16 use pidl::idl;
17 use pidl::dump;
18 use pidl::ndr_client;
19 use pidl::ndr_header;
20 use pidl::ndr_parser;
21 use pidl::server;
22 use pidl::dcom_proxy;
23 use pidl::dcom_stub;
24 use pidl::com_header;
25 use pidl::odl;
26 use pidl::eth_parser;
27 use pidl::eth_header;
28 use pidl::validator;
29 use pidl::typelist;
30 use pidl::util;
31 use pidl::template;
32 use pidl::swig;
33 use pidl::compat;
34 use pidl::esp;
35
36 my($opt_help) = 0;
37 my($opt_parse) = 0;
38 my($opt_dump) = 0;
39 my($opt_diff) = 0;
40 my($opt_header);
41 my($opt_template) = 0;
42 my($opt_client) = 0;
43 my($opt_server) = 0;
44 my($opt_parser);
45 my($opt_eth_parser);
46 my($opt_eth_header);
47 my($opt_keep) = 0;
48 my($opt_swig) = 0;
49 my($opt_dcom_proxy) = 0;
50 my($opt_com_header) = 0;
51 my($opt_esp);
52 my($opt_odl) = 0;
53 my($opt_quiet) = 0;
54 my($opt_output);
55 my($opt_warn_compat) = 0;
56
57 my $idl_parser = new idl;
58
59 #########################################
60 # display help text
61 sub ShowHelp()
62 {
63 print "perl IDL parser and code generator
64 Copyright (C) tridge\@samba.org
65
66 Usage: pidl.pl [options] <idlfile>
67
68 Options:
69  --help                this help page
70  --output=OUTNAME      put output in OUTNAME.*
71  --parse               parse a idl file to a .pidl file
72  --dump                dump a pidl file back to idl
73  --header[=OUTFILE]    create a C NDR header file
74  --parser[=OUTFILE]    create a C NDR parser
75  --esp[=OUTFILE]       create esp wrapper file
76  --client              create a C NDR client
77  --server              create server boilerplate
78  --template            print a template for a pipe
79  --eth-parser          create an ethereal parser
80  --eth-header          create an ethereal header file
81  --swig                create swig wrapper file
82  --diff                run diff on the idl and dumped output
83  --keep                keep the .pidl file
84  --odl                 accept ODL input
85  --dcom-proxy          create DCOM proxy (implies --odl)
86  --com-header          create header for COM interfaces (implies --odl)
87  --warn-compat         warn about incompatibility with other compilers
88  --quiet               be quiet
89 \n";
90     exit(0);
91 }
92
93 # main program
94 GetOptions (
95             'help|h|?' => \$opt_help, 
96             'output=s' => \$opt_output,
97             'parse' => \$opt_parse,
98             'dump' => \$opt_dump,
99             'header:s' => \$opt_header,
100             'server' => \$opt_server,
101             'template' => \$opt_template,
102             'parser:s' => \$opt_parser,
103         'client' => \$opt_client,
104             'eth-parser:s' => \$opt_eth_parser,
105                 'eth-header:s' => \$opt_eth_header,
106                 'esp:s' => \$opt_esp,
107             'diff' => \$opt_diff,
108                 'odl' => \$opt_odl,
109             'keep' => \$opt_keep,
110             'swig' => \$opt_swig,
111                 'dcom-proxy' => \$opt_dcom_proxy,
112                 'com-header' => \$opt_com_header,
113                 'quiet' => \$opt_quiet,
114                 'warn-compat' => \$opt_warn_compat
115             );
116
117 if ($opt_help) {
118     ShowHelp();
119     exit(0);
120 }
121
122 sub process_file($)
123 {
124         my $idl_file = shift;
125         my $output;
126         my $pidl;
127         my $ndr;
128
129         my $basename = basename($idl_file, ".idl");
130
131         if (!defined($opt_output)) {
132                 $output = $idl_file;
133         } else {
134                 $output = $opt_output . $basename;
135         }
136
137         my($pidl_file) = util::ChangeExtension($output, ".pidl");
138
139         unless ($opt_quiet) { print "Compiling $idl_file\n"; }
140
141         if ($opt_parse) {
142                 $pidl = $idl_parser->parse_idl($idl_file);
143                 defined @$pidl || die "Failed to parse $idl_file";
144                 typelist::LoadIdl($pidl);
145                 IdlValidator::Validate($pidl);
146                 if ($opt_keep && !util::SaveStructure($pidl_file, $pidl)) {
147                             die "Failed to save $pidl_file\n";
148                 }
149         } else {
150                 $pidl = util::LoadStructure($pidl_file);
151                 defined $pidl || die "Failed to load $pidl_file - maybe you need --parse\n";
152         }
153
154         if ($opt_dump) {
155                 print IdlDump::Dump($pidl);
156         }
157
158         if ($opt_diff) {
159                 my($tempfile) = util::ChangeExtension($output, ".tmp");
160                 util::FileSave($tempfile, IdlDump::Dump($pidl));
161                 system("diff -wu $idl_file $tempfile");
162                 unlink($tempfile);
163         }
164
165         if ($opt_com_header) {
166                 my $res = COMHeader::Parse($pidl);
167                 if ($res) {
168                         my $comh_filename = dirname($output) . "/com_$basename.h";
169                         util::FileSave($comh_filename, 
170                         "#include \"librpc/gen_ndr/ndr_orpc.h\"\n" . 
171                         "#include \"librpc/gen_ndr/ndr_$basename.h\"\n" . 
172                         $res);
173                 }
174                 $opt_odl = 1;
175         }
176
177         if ($opt_dcom_proxy) {
178                 my $res = DCOMProxy::Parse($pidl);
179                 if ($res) {
180                         my ($client) = util::ChangeExtension($output, "_p.c");
181                         util::FileSave($client, 
182                         "#include \"includes.h\"\n" .
183                         "#include \"librpc/gen_ndr/com_$basename.h\"\n" . 
184                         "#include \"lib/com/dcom/dcom.h\"\n" .$res);
185                 }
186                 $opt_odl = 1;
187         }
188
189         if ($opt_warn_compat) {
190                 IDLCompat::Check($pidl);
191         }
192
193         if ($opt_odl) {
194                 $pidl = ODL::ODL2IDL($pidl);
195         }
196
197         if (defined($opt_header) or defined($opt_eth_parser) or defined($opt_eth_header) or $opt_client or $opt_server or defined($opt_parser) or defined($opt_esp)) {
198                 $ndr = Ndr::Parse($pidl);
199 #               print util::MyDumper($ndr);
200         }
201
202         if (defined($opt_header)) {
203                 my $header = $opt_header;
204                 if ($header eq "") {
205                         $header = util::ChangeExtension($output, ".h");
206                 }
207                 util::FileSave($header, NdrHeader::Parse($ndr));
208                 if ($opt_swig) {
209                   my($filename) = $output;
210                   $filename =~ s/\/ndr_/\//;
211                   $filename = util::ChangeExtension($filename, ".i");
212                   IdlSwig::RewriteHeader($pidl, $header, $filename);
213                 }
214         }
215
216
217         if (defined($opt_eth_header)) {
218           my($eparserhdr) = $opt_eth_header;
219           if ($eparserhdr eq "") {
220                   $eparserhdr = dirname($output) . "/packet-dcerpc-$basename.h";
221           }
222
223           util::FileSave($eparserhdr, EthHeader::Parse($ndr));
224         }
225
226         my $h_filename = util::ChangeExtension($output, ".h");
227         if ($opt_client) {
228                 my ($client) = util::ChangeExtension($output, "_c.c");
229
230                 util::FileSave($client, NdrClient::Parse($ndr,$h_filename));
231         }
232
233         if (defined($opt_esp)) {
234                 my $esp = $opt_esp;
235                 if ($esp eq "") { $esp = util::ChangeExtension($output, "_esp.c"); }
236                 util::FileSave($esp, EspClient::Parse($ndr, $h_filename));
237         }
238
239         if ($opt_server) {
240                 my $dcom = "";
241
242                 foreach my $x (@{$pidl}) {
243                         next if ($x->{TYPE} ne "INTERFACE");
244
245                         if (util::has_property($x, "object")) {
246                                 $dcom .= DCOMStub::ParseInterface($x);
247                         }
248                 }
249
250                 util::FileSave(util::ChangeExtension($output, "_s.c"), NdrServer::Parse($ndr,$h_filename));
251
252                 if ($dcom ne "") {
253                         $dcom = "
254 #include \"includes.h\"
255 #include \"$h_filename\"
256 #include \"rpc_server/dcerpc_server.h\"
257 #include \"rpc_server/common/common.h\"
258
259 $dcom
260 ";
261                         util::FileSave(util::ChangeExtension($output, "_d.c"), $dcom);
262                 }
263         }
264
265         if (defined($opt_parser)) {
266                 my $parser = $opt_parser;
267                 if ($parser eq "") {
268                         $parser = util::ChangeExtension($output, ".c");
269                 }
270                 
271                 util::FileSave($parser, NdrParser::Parse($ndr, $parser));
272         }
273
274         if (defined($opt_eth_parser)) {
275           my($eparser) = $opt_eth_parser;
276           if ($eparser eq "") {
277                   $eparser = dirname($output) . "/packet-dcerpc-$basename.c";
278           }
279           util::FileSave($eparser, EthParser::Parse($ndr, $basename, $eparser));
280         }
281
282
283         if ($opt_template) {
284                 print IdlTemplate::Parse($pidl);
285         }
286 }
287
288 foreach my $filename (@ARGV) {
289         process_file($filename);
290 }