#!/usr/bin/perl -w ################################################### # package to parse IDL files and generate code for # rpc functions in Samba # Copyright tridge@samba.org 2000-2003 # Copyright jelmer@samba.org 2005 # released under the GNU GPL use strict; use FindBin qw($RealBin); use lib "$RealBin/.."; use Getopt::Long; use File::Basename; use pidl::idl; use pidl::dump; use pidl::ndr_client; use pidl::ndr_header; use pidl::ndr_parser; use pidl::server; use pidl::dcom_proxy; use pidl::dcom_stub; use pidl::com_header; use pidl::odl; use pidl::eth_parser; use pidl::eth_header; use pidl::validator; use pidl::typelist; use pidl::util; use pidl::template; use pidl::swig; use pidl::compat; use pidl::ejs; use pidl::ejs_header; my($opt_help) = 0; my($opt_parse) = 0; my($opt_dump) = 0; my($opt_uint_enums) = 0; my($opt_diff) = 0; my($opt_header); my($opt_template) = 0; my($opt_client); my($opt_server); my($opt_parser); my($opt_eth_parser); my($opt_eth_header); my($opt_keep); my($opt_swig); my($opt_dcom_proxy); my($opt_com_header); my($opt_ejs); my($opt_odl) = 0; my($opt_quiet) = 0; my($opt_output); my($opt_verbose) = 0; my($opt_warn_compat) = 0; my $idl_parser = new idl; ######################################### # display help text sub ShowHelp() { print "perl IDL parser and code generator Copyright (C) tridge\@samba.org Usage: pidl.pl [options] Options: --help this help page --output=OUTNAME put output in OUTNAME.* --parse parse a idl file to a .pidl file --dump dump a pidl file back to idl --uint-enums don't use C enums, instead use uint* types --header[=OUTFILE] create a C NDR header file --parser[=OUTFILE] create a C NDR parser --ejs[=OUTFILE] create ejs wrapper file --client[=OUTFILE] create a C NDR client --server[=OUTFILE] create server boilerplate --template print a template for a pipe --eth-parser[=OUTFILE]create an ethereal parser --eth-header[=OUTFILE]create an ethereal header file --swig[=OUTFILE] create swig wrapper file --diff run diff on the idl and dumped output --keep[=OUTFILE] keep the .pidl file --odl accept ODL input --dcom-proxy[=OUTFILE]create DCOM proxy (implies --odl) --com-header[=OUTFILE]create header for COM interfaces (implies --odl) --warn-compat warn about incompatibility with other compilers --quiet be quiet --verbose be verbose \n"; exit(0); } # main program GetOptions ( 'help|h|?' => \$opt_help, 'output=s' => \$opt_output, 'parse' => \$opt_parse, 'dump' => \$opt_dump, 'uint-enums' => \$opt_uint_enums, 'header:s' => \$opt_header, 'server:s' => \$opt_server, 'template' => \$opt_template, 'parser:s' => \$opt_parser, 'client:s' => \$opt_client, 'eth-parser:s' => \$opt_eth_parser, 'eth-header:s' => \$opt_eth_header, 'ejs:s' => \$opt_ejs, 'diff' => \$opt_diff, 'odl' => \$opt_odl, 'keep:s' => \$opt_keep, 'swig:s' => \$opt_swig, 'dcom-proxy:s' => \$opt_dcom_proxy, 'com-header:s' => \$opt_com_header, 'quiet' => \$opt_quiet, 'verbose' => \$opt_verbose, 'warn-compat' => \$opt_warn_compat ); if ($opt_help) { ShowHelp(); exit(0); } sub process_file($) { my $idl_file = shift; my $output; my $pidl; my $ndr; my $basename = basename($idl_file, ".idl"); if (!defined($opt_output)) { $output = $idl_file; } else { $output = $opt_output . $basename; } my($pidl_file) = ($opt_keep or util::ChangeExtension($output, ".pidl")); unless ($opt_quiet) { print "Compiling $idl_file\n"; } if ($opt_parse) { $pidl = $idl_parser->parse_idl($idl_file); defined @$pidl || die "Failed to parse $idl_file"; typelist::LoadIdl($pidl); IdlValidator::Validate($pidl); if (defined($opt_keep) && !util::SaveStructure($pidl_file, $pidl)) { die "Failed to save $pidl_file\n"; } } else { $pidl = util::LoadStructure($pidl_file); defined $pidl || die "Failed to load $pidl_file - maybe you need --parse\n"; } if ($opt_uint_enums) { util::setUseUintEnums(1); } if ($opt_dump) { print IdlDump::Dump($pidl); } if ($opt_diff) { my($tempfile) = util::ChangeExtension($output, ".tmp"); util::FileSave($tempfile, IdlDump::Dump($pidl)); system("diff -wu $idl_file $tempfile"); unlink($tempfile); } if (defined($opt_com_header)) { my $res = COMHeader::Parse($pidl); if ($res) { my $comh_filename = ($opt_com_header or (dirname($output) . "/com_$basename.h")); util::FileSave($comh_filename, "#include \"librpc/gen_ndr/ndr_orpc.h\"\n" . "#include \"librpc/gen_ndr/ndr_$basename.h\"\n" . $res); } $opt_odl = 1; } if (defined($opt_dcom_proxy)) { my $res = DCOMProxy::Parse($pidl); if ($res) { my ($client) = ($opt_dcom_proxy or util::ChangeExtension($output, "_p.c")); util::FileSave($client, "#include \"includes.h\"\n" . "#include \"librpc/gen_ndr/com_$basename.h\"\n" . "#include \"lib/com/dcom/dcom.h\"\n" .$res); } $opt_odl = 1; } if ($opt_warn_compat) { IDLCompat::Check($pidl); } if ($opt_odl) { $pidl = ODL::ODL2IDL($pidl); } if (defined($opt_header) or defined($opt_eth_parser) or defined($opt_eth_header) or defined($opt_client) or defined($opt_server) or defined($opt_parser) or defined($opt_ejs)) { $ndr = Ndr::Parse($pidl); } if (defined($opt_header)) { my $header = $opt_header; if ($header eq "") { $header = util::ChangeExtension($output, ".h"); } util::FileSave($header, NdrHeader::Parse($ndr)); if (defined($opt_swig)) { my($filename) = $output; $filename =~ s/\/ndr_/\//; $filename = ($opt_swig or util::ChangeExtension($filename, ".i")); IdlSwig::RewriteHeader($pidl, $header, $filename); } } if (defined($opt_eth_header)) { my($eparserhdr) = ($opt_eth_header or (dirname($output) . "/packet-dcerpc-$basename.h")); util::FileSave($eparserhdr, EthHeader::Parse($ndr)); } my $h_filename = util::ChangeExtension($output, ".h"); if (defined($opt_client)) { my ($client) = ($opt_client or util::ChangeExtension($output, "_c.c")); util::FileSave($client, NdrClient::Parse($ndr,$h_filename)); } if (defined($opt_ejs)) { my $ejs = ($opt_ejs or util::ChangeExtension($output, "_ejs.c")); util::FileSave($ejs, EjsClient::Parse($ndr, $h_filename)); $ejs = ($opt_ejs or util::ChangeExtension($output, "_ejs.h")); util::FileSave($ejs, EjsHeader::Parse($ndr)); } if (defined($opt_server)) { my $dcom = ""; foreach my $x (@{$pidl}) { next if ($x->{TYPE} ne "INTERFACE"); if (util::has_property($x, "object")) { $dcom .= DCOMStub::ParseInterface($x); } } util::FileSave(($opt_server or util::ChangeExtension($output, "_s.c")), NdrServer::Parse($ndr,$h_filename)); if ($dcom ne "") { $dcom = " #include \"includes.h\" #include \"$h_filename\" #include \"rpc_server/dcerpc_server.h\" #include \"rpc_server/common/common.h\" $dcom "; util::FileSave(util::ChangeExtension($output, "_d.c"), $dcom); } } if (defined($opt_parser)) { my $parser = ($opt_parser or util::ChangeExtension($output, ".c")); util::FileSave($parser, NdrParser::Parse($ndr, $parser)); } if (defined($opt_eth_parser)) { my($eparser) = ($opt_eth_parser or dirname($output) . "/packet-dcerpc-$basename.c"); util::FileSave($eparser, EthParser::Parse($ndr, $basename, $eparser)); } if ($opt_template) { print IdlTemplate::Parse($pidl); } } foreach my $filename (@ARGV) { process_file($filename); }