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