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