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
12 use FindBin qw($RealBin);
14 use lib "$RealBin/lib";
41 my($opt_template) = 0;
49 my($opt_dcom_proxy) = 0;
50 my($opt_com_header) = 0;
54 my($opt_warn_compat) = 0;
56 my $idl_parser = new idl;
58 #########################################
63 perl IDL parser and code generator
64 Copyright (C) tridge\@samba.org
66 Usage: pidl.pl [options] <idlfile>
70 --output=OUTNAME put output in OUTNAME.*
71 --parse parse a idl file to a .pidl file
72 --dump dump a pidl file back to idl
73 --header[=OUTFILE] create a C NDR header file
74 --parser[=OUTFILE] create a C NDR parser
75 --client create a C NDR client
76 --server create server boilerplate
77 --template print a template for a pipe
78 --eth-parser create an ethereal parser
79 --eth-header create an ethereal header file
80 --swig create swig wrapper file
81 --diff run diff on the idl and dumped output
82 --keep keep the .pidl file
83 --odl accept ODL input
84 --dcom-proxy create DCOM proxy (implies --odl)
85 --com-header create header for COM interfaces (implies --odl)
86 --warn-compat warn about incompatibility with other compilers
94 'help|h|?' => \$opt_help,
95 'output=s' => \$opt_output,
96 'parse' => \$opt_parse,
98 'header:s' => \$opt_header,
99 'server' => \$opt_server,
100 'template' => \$opt_template,
101 'parser:s' => \$opt_parser,
102 'client' => \$opt_client,
103 'eth-parser:s' => \$opt_eth_parser,
104 'eth-header:s' => \$opt_eth_header,
105 'diff' => \$opt_diff,
107 'keep' => \$opt_keep,
108 'swig' => \$opt_swig,
109 'dcom-proxy' => \$opt_dcom_proxy,
110 'com-header' => \$opt_com_header,
111 'quiet' => \$opt_quiet,
112 'warn-compat' => \$opt_warn_compat
122 my $idl_file = shift;
127 my $basename = basename($idl_file, ".idl");
129 if (!defined($opt_output)) {
132 $output = $opt_output . $basename;
135 my($pidl_file) = util::ChangeExtension($output, ".pidl");
137 unless ($opt_quiet) { print "Compiling $idl_file\n"; }
140 $pidl = $idl_parser->parse_idl($idl_file);
141 defined @$pidl || die "Failed to parse $idl_file";
142 typelist::LoadIdl($pidl);
143 IdlValidator::Validate($pidl);
144 if ($opt_keep && !util::SaveStructure($pidl_file, $pidl)) {
145 die "Failed to save $pidl_file\n";
148 $pidl = util::LoadStructure($pidl_file);
149 defined $pidl || die "Failed to load $pidl_file - maybe you need --parse\n";
153 print IdlDump::Dump($pidl);
157 my($tempfile) = util::ChangeExtension($output, ".tmp");
158 util::FileSave($tempfile, IdlDump::Dump($pidl));
159 system("diff -wu $idl_file $tempfile");
163 if ($opt_com_header) {
164 my $res = COMHeader::Parse($pidl);
166 my $h_filename = dirname($output) . "/com_$basename.h";
167 util::FileSave($h_filename,
168 "#include \"librpc/gen_ndr/ndr_orpc.h\"\n" .
169 "#include \"librpc/gen_ndr/ndr_$basename.h\"\n" .
175 if ($opt_dcom_proxy) {
176 my $res = DCOMProxy::Parse($pidl);
178 my ($client) = util::ChangeExtension($output, "_p.c");
179 util::FileSave($client,
180 "#include \"includes.h\"\n" .
181 "#include \"librpc/gen_ndr/com_$basename.h\"\n" .
182 "#include \"lib/com/dcom/dcom.h\"\n" .$res);
187 if ($opt_warn_compat) {
188 IDLCompat::Check($pidl);
192 $pidl = ODL::ODL2IDL($pidl);
195 if (defined($opt_header) or defined($opt_eth_parser) or defined($opt_eth_header) or $opt_client or $opt_server or defined($opt_parser)) {
196 $ndr = Ndr::Parse($pidl);
197 # print util::MyDumper($ndr);
200 if (defined($opt_header)) {
201 my $header = $opt_header;
203 $header = util::ChangeExtension($output, ".h");
205 util::FileSave($header, NdrHeader::Parse($ndr));
207 my($filename) = $output;
208 $filename =~ s/\/ndr_/\//;
209 $filename = util::ChangeExtension($filename, ".i");
210 IdlSwig::RewriteHeader($pidl, $header, $filename);
214 if (defined($opt_eth_header)) {
215 my($eparserhdr) = $opt_eth_header;
216 if ($eparserhdr eq "") {
217 $eparserhdr = dirname($output) . "/packet-dcerpc-$basename.h";
220 util::FileSave($eparserhdr, EthHeader::Parse($ndr));
224 my ($client) = util::ChangeExtension($output, "_c.c");
226 my $h_filename = util::ChangeExtension($output, ".h");
228 $res .= "#include \"includes.h\"\n";
229 $res .= "#include \"$h_filename\"\n\n";
231 foreach my $x (@{$pidl}) {
232 $res .= NdrClient::ParseInterface($x);
235 util::FileSave($client, $res);
239 my $h_filename = util::ChangeExtension($output, ".h");
243 foreach my $x (@{$pidl}) {
244 next if ($x->{TYPE} ne "INTERFACE");
246 if (util::has_property($x, "object")) {
247 $dcom .= DCOMStub::ParseInterface($x);
249 $plain .= IdlServer::ParseInterface($x);
254 util::FileSave(util::ChangeExtension($output, "_s.c"), $plain);
259 #include \"includes.h\"
260 #include \"$h_filename\"
261 #include \"rpc_server/dcerpc_server.h\"
262 #include \"rpc_server/common/common.h\"
266 util::FileSave(util::ChangeExtension($output, "_d.c"), $dcom);
270 if (defined($opt_parser)) {
271 my $parser = $opt_parser;
273 $parser = util::ChangeExtension($output, ".c");
276 util::FileSave($parser, NdrParser::Parse($ndr, $parser));
279 if (defined($opt_eth_parser)) {
280 my($eparser) = $opt_eth_parser;
281 if ($eparser eq "") {
282 $eparser = dirname($output) . "/packet-dcerpc-$basename.c";
284 util::FileSave($eparser, EthParser::Parse($ndr, $basename, $eparser));
289 print IdlTemplate::Parse($pidl);
293 foreach my $filename (@ARGV) {
294 process_file($filename);