r5852: Rename ndr.pm to ndr_parser.pm
[samba.git] / source4 / 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_parser;
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                 typelist::LoadIdl($pidl);
141                 IdlValidator::Validate($pidl);
142                 if ($opt_keep && !util::SaveStructure($pidl_file, $pidl)) {
143                             die "Failed to save $pidl_file\n";
144                 }
145         } else {
146                 $pidl = util::LoadStructure($pidl_file);
147                 defined $pidl || die "Failed to load $pidl_file - maybe you need --parse\n";
148         }
149
150         if ($opt_dump) {
151                 print IdlDump::Dump($pidl);
152         }
153
154         if ($opt_diff) {
155                 my($tempfile) = util::ChangeExtension($output, ".tmp");
156                 util::FileSave($tempfile, IdlDump::Dump($pidl));
157                 system("diff -wu $idl_file $tempfile");
158                 unlink($tempfile);
159         }
160
161         if ($opt_com_header) {
162                 my $res = COMHeader::Parse($pidl);
163                 if ($res) {
164                         my $h_filename = dirname($output) . "/com_$basename.h";
165                         util::FileSave($h_filename, 
166                         "#include \"librpc/gen_ndr/ndr_orpc.h\"\n" . 
167                         "#include \"librpc/gen_ndr/ndr_$basename.h\"\n" . 
168                         $res);
169                 }
170                 $opt_odl = 1;
171         }
172
173         if ($opt_dcom_proxy) {
174                 my $res = DCOMProxy::Parse($pidl);
175                 if ($res) {
176                         my ($client) = util::ChangeExtension($output, "_p.c");
177                         util::FileSave($client, 
178                         "#include \"includes.h\"\n" .
179                         "#include \"librpc/gen_ndr/com_$basename.h\"\n" . 
180                         "#include \"lib/com/dcom/dcom.h\"\n" .$res);
181                 }
182                 $opt_odl = 1;
183         }
184
185         if ($opt_odl) {
186                 $pidl = ODL::ODL2IDL($pidl);
187         }
188
189         if ($opt_header) {
190                 my($header) = util::ChangeExtension($output, ".h");
191                 util::FileSave($header, NdrHeader::Parse($pidl));
192                 if ($opt_eparser) {
193                   my($eparserhdr) = dirname($output) . "/packet-dcerpc-$basename.h";
194                   IdlEParser::RewriteHeader($pidl, $header, $eparserhdr);
195                 }
196                 if ($opt_swig) {
197                   my($filename) = $output;
198                   $filename =~ s/\/ndr_/\//;
199                   $filename = util::ChangeExtension($filename, ".i");
200                   IdlSwig::RewriteHeader($pidl, $header, $filename);
201                 }
202         }
203
204         if ($opt_client) {
205                 my ($client) = util::ChangeExtension($output, "_c.c");
206                 my $res = "";
207                 my $h_filename = util::ChangeExtension($output, ".h");
208
209                 $res .= "#include \"includes.h\"\n";
210                 $res .= "#include \"$h_filename\"\n\n";
211
212                 foreach my $x (@{$pidl}) {
213                         $res .= NdrClient::ParseInterface($x);
214                 }
215
216                 util::FileSave($client, $res);
217         }
218
219         if ($opt_server) {
220                 my $h_filename = util::ChangeExtension($output, ".h");
221                 my $plain = "";
222                 my $dcom = "";
223
224                 foreach my $x (@{$pidl}) {
225                         next if ($x->{TYPE} ne "INTERFACE");
226
227                         if (util::has_property($x, "object")) {
228                                 $dcom .= DCOMStub::ParseInterface($x);
229                         } else {
230                                 $plain .= IdlServer::ParseInterface($x);
231                         }
232                 }
233
234                 if ($plain ne "") {
235                         util::FileSave(util::ChangeExtension($output, "_s.c"), $plain);
236                 }
237
238                 if ($dcom ne "") {
239                         $dcom = "
240 #include \"includes.h\"
241 #include \"$h_filename\"
242 #include \"rpc_server/dcerpc_server.h\"
243 #include \"rpc_server/common/common.h\"
244
245 $dcom
246 ";
247                         util::FileSave(util::ChangeExtension($output, "_d.c"), $dcom);
248                 }
249         }
250
251         if ($opt_parser) {
252                 my($parser) = util::ChangeExtension($output, ".c");
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
266 foreach my $filename (@ARGV) {
267         process_file($filename);
268 }