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
16 use Parse::Pidl::Util;
18 #####################################################################
19 # save a data structure into a file
22 my($filename,$v) = @_;
23 FileSave($filename, Parse::Pidl::Util::MyDumper($v));
26 #####################################################################
27 # load a data structure from a file (as saved with SaveStructure)
31 my $contents = FileLoad($f);
32 defined $contents || return undef;
33 return eval "$contents";
36 #####################################################################
37 # read a file into a string
40 my($filename) = shift;
42 open(INPUTFILE, $filename) || return undef;
43 my($saved_delim) = $/;
45 my($data) = <INPUTFILE>;
51 #####################################################################
52 # write a string into a file
55 my($filename) = shift;
58 open(FILE, ">$filename") || die "can't open $filename";
66 my($opt_uint_enums) = 0;
70 my($opt_template) = 0;
84 my($opt_outputdir) = '.';
86 my($opt_warn_compat) = 0;
88 #########################################
92 print "perl IDL parser and code generator
93 Copyright (C) tridge\@samba.org
95 Usage: pidl [options] [--] <idlfile> [<idlfile>...]
99 --outputdir=OUTDIR put output in OUTDIR/ [.]
100 --parse parse a idl file to a .pidl file
101 --dump dump a pidl file back to idl
102 --diff run diff on the idl and dumped output
103 --keep[=OUTFILE] keep the .pidl file
104 --odl accept ODL input
105 --warn-compat warn about incompatibility with other compilers
110 --header[=OUTFILE] create generic header file
111 --uint-enums don't use C enums, instead use uint* types
112 --ndr-header[=OUTFILE] create a C NDR-specific header file
113 --ndr-parser[=OUTFILE] create a C NDR parser
114 --client[=OUTFILE] create a C NDR client
115 --tdr-header[=OUTFILE] create a C TDR header file
116 --tdr-parser[=OUTFILE] create a C TDR parser
117 --ejs[=OUTFILE] create ejs wrapper file
118 --swig[=OUTFILE] create swig wrapper file
119 --server[=OUTFILE] create server boilerplate
120 --template print a template for a pipe
121 --dcom-proxy[=OUTFILE] create DCOM proxy (implies --odl)
122 --com-header[=OUTFILE] create header for COM interfaces (implies --odl)
125 --eth-parser[=OUTFILE] create ethereal parser and header
132 'help|h|?' => \$opt_help,
133 'outputdir=s' => \$opt_outputdir,
134 'parse' => \$opt_parse,
135 'dump' => \$opt_dump,
136 'uint-enums' => \$opt_uint_enums,
137 'ndr-header:s' => \$opt_ndr_header,
138 'header:s' => \$opt_header,
139 'server:s' => \$opt_server,
140 'tdr-header:s' => \$opt_tdr_header,
141 'tdr-parser:s' => \$opt_tdr_parser,
142 'template' => \$opt_template,
143 'ndr-parser:s' => \$opt_ndr_parser,
144 'client:s' => \$opt_client,
145 'eth-parser:s' => \$opt_eth_parser,
147 'diff' => \$opt_diff,
149 'keep:s' => \$opt_keep,
150 'swig:s' => \$opt_swig,
151 'dcom-proxy:s' => \$opt_dcom_proxy,
152 'com-header:s' => \$opt_com_header,
153 'quiet' => \$opt_quiet,
154 'verbose' => \$opt_verbose,
155 'warn-compat' => \$opt_warn_compat
165 my $idl_file = shift;
166 my $outputdir = $opt_outputdir;
170 my $basename = basename($idl_file, ".idl");
172 my($pidl_file) = ($opt_keep or "$outputdir/$basename.pidl");
174 unless ($opt_quiet) { print "Compiling $idl_file\n"; }
177 require Parse::Pidl::IDL;
178 my $idl_parser = new Parse::Pidl::IDL;
180 $pidl = $idl_parser->parse_idl($idl_file);
181 defined @$pidl || die "Failed to parse $idl_file";
182 require Parse::Pidl::Typelist;
183 Parse::Pidl::Typelist::LoadIdl($pidl);
184 if (defined($opt_keep) && !SaveStructure($pidl_file, $pidl)) {
185 die "Failed to save $pidl_file\n";
188 $pidl = LoadStructure($pidl_file);
189 defined $pidl || die "Failed to load $pidl_file - maybe you need --parse\n";
192 if ($opt_uint_enums) {
193 Parse::Pidl::Util::setUseUintEnums(1);
197 require Parse::Pidl::Dump;
198 print Parse::Pidl::Dump($pidl);
202 my($tempfile) = "$outputdir/$basename.tmp";
203 FileSave($tempfile, IdlDump::Dump($pidl));
204 system("diff -wu $idl_file $tempfile");
208 if (defined($opt_com_header)) {
209 require Parse::Pidl::Samba::COM::Header;
210 my $res = Parse::Pidl::Samba::COM::Header::Parse($pidl);
212 my $comh_filename = ($opt_com_header or "$outputdir/com_$basename.h");
213 FileSave($comh_filename,
214 "#include \"librpc/gen_ndr/ndr_orpc.h\"\n" .
215 "#include \"$outputdir/ndr_$basename.h\"\n" .
221 if (defined($opt_dcom_proxy)) {
222 require Parse::Pidl::Samba::COM::Proxy;
223 my $res = Parse::Pidl::Samba::COM::Proxy::Parse($pidl);
225 my ($client) = ($opt_dcom_proxy or "$outputdir/$basename\_p.c");
227 "#include \"includes.h\"\n" .
228 "#include \"$outputdir/com_$basename.h\"\n" .
229 "#include \"lib/com/dcom/dcom.h\"\n" .$res);
234 if ($opt_warn_compat) {
235 require Parse::Pidl::Compat;
236 Parse::Pidl::Compat::Check($pidl);
240 require Parse::Pidl::ODL;
241 $pidl = Parse::Pidl::ODL::ODL2IDL($pidl);
244 if (defined($opt_ndr_header) or defined($opt_eth_parser) or
245 defined($opt_client) or defined($opt_server) or
246 defined($opt_ndr_parser) or defined($opt_ejs)) {
247 require Parse::Pidl::NDR;
248 Parse::Pidl::NDR::Validate($pidl);
249 $ndr = Parse::Pidl::NDR::Parse($pidl);
252 if (defined($opt_header)) {
253 my $header = ($opt_header or "$outputdir/$basename.h");
254 require Parse::Pidl::Samba::Header;
255 FileSave($header, Parse::Pidl::Samba::Header::Parse($pidl));
258 if (defined($opt_ndr_header)) {
259 my $header = ($opt_ndr_header or "$outputdir/ndr_$basename.h");
260 require Parse::Pidl::Samba::NDR::Header;
261 FileSave($header, Parse::Pidl::Samba::NDR::Header::Parse($pidl, $basename));
262 if (defined($opt_swig)) {
263 require Parse::Pidl::Samba::SWIG;
264 my($filename) = ($opt_swig or "$outputdir/$basename.i");
265 Parse::Pidl::Samba::SWIG::RewriteHeader($pidl, $header, $filename);
269 my $h_filename = "$outputdir/ndr_$basename.h";
270 if (defined($opt_client)) {
271 require Parse::Pidl::Samba::NDR::Client;
272 my ($client) = ($opt_client or "$outputdir/ndr_$basename\_c.c");
274 FileSave($client, Parse::Pidl::Samba::NDR::Client::Parse($ndr,$h_filename));
277 if (defined($opt_ejs)) {
278 require Parse::Pidl::Samba::EJS;
279 require Parse::Pidl::Samba::EJSHeader;
280 FileSave("$outputdir/ndr_$basename\_ejs.c", Parse::Pidl::Samba::EJS::Parse($ndr, $h_filename));
282 FileSave("$outputdir/ndr_$basename\_ejs.h", Parse::Pidl::Samba::EJSHeader::Parse($ndr));
285 if (defined($opt_server)) {
286 require Parse::Pidl::Samba::NDR::Server;
289 foreach my $x (@{$pidl}) {
290 next if ($x->{TYPE} ne "INTERFACE");
292 if (Parse::Pidl::Util::has_property($x, "object")) {
293 require Parse::Pidl::Samba::COM::Stub;
294 $dcom .= Parse::Pidl::Samba::COM::Stub::ParseInterface($x);
298 FileSave(($opt_server or "$outputdir/ndr_$basename\_s.c"), Parse::Pidl::Samba::NDR::Server::Parse($ndr,$h_filename));
302 #include \"includes.h\"
303 #include \"$h_filename\"
304 #include \"rpc_server/dcerpc_server.h\"
305 #include \"rpc_server/common/common.h\"
309 FileSave("$outputdir/$basename\_d.c", $dcom);
313 if (defined($opt_ndr_parser)) {
314 my $parser = ($opt_ndr_parser or "$outputdir/ndr_$basename.c");
315 require Parse::Pidl::Samba::NDR::Parser;
316 FileSave($parser, Parse::Pidl::Samba::NDR::Parser::Parse($ndr, $parser));
319 if (defined($opt_eth_parser)) {
320 require Parse::Pidl::Ethereal::NDR;
321 my($eparser) = ($opt_eth_parser or "$outputdir/packet-dcerpc-$basename.c");
322 my $eheader = $eparser;
323 $eheader =~ s/\.c$/\.h/;
324 my $cnffile = $idl_file;
325 $cnffile =~ s/\.idl$/\.cnf/;
327 my ($dp, $dh) = Parse::Pidl::Ethereal::NDR::Parse($ndr, $eheader, $cnffile);
328 FileSave($eparser, $dp);
329 FileSave($eheader, $dh);
332 my $tdr_parser = ($opt_tdr_parser or "$outputdir/tdr_$basename.c");
333 my $tdr_header = ($opt_tdr_header or "$outputdir/tdr_$basename.h");
334 if (defined($opt_tdr_parser)) {
335 require Parse::Pidl::Samba::TDR;
336 FileSave($tdr_parser, Parse::Pidl::Samba::TDR::Parser($pidl, $tdr_header));
339 if (defined($opt_tdr_header)) {
340 require Parse::Pidl::Samba::TDR;
341 FileSave($tdr_header, Parse::Pidl::Samba::TDR::Header($pidl, $outputdir));
345 require Parse::Pidl::Samba::Template;
346 print Parse::Pidl::Samba::Template::Parse($pidl);
350 if (scalar(@ARGV) == 0) {
351 print "pidl: no input files\n";
355 process_file($_) foreach (@ARGV);