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
15 use Parse::Pidl::Util;
17 #####################################################################
18 # save a data structure into a file
21 my($filename,$v) = @_;
22 Parse::Pidl::Util::FileSave($filename, Parse::Pidl::Util::MyDumper($v));
25 #####################################################################
26 # load a data structure from a file (as saved with SaveStructure)
30 my $contents = Parse::Pidl::Util::FileLoad($f);
31 defined $contents || return undef;
32 return eval "$contents";
38 my($opt_uint_enums) = 0;
41 my($opt_template) = 0;
56 my($opt_warn_compat) = 0;
58 #########################################
62 print "perl IDL parser and code generator
63 Copyright (C) tridge\@samba.org
65 Usage: pidl [options] <idlfile>
69 --output=OUTNAME put output in OUTNAME.*
70 --parse parse a idl file to a .pidl file
71 --dump dump a pidl file back to idl
72 --uint-enums don't use C enums, instead use uint* types
73 --header[=OUTFILE] create a C NDR header file
74 --parser[=OUTFILE] create a C NDR parser
75 --ejs[=OUTFILE] create ejs wrapper file
76 --client[=OUTFILE] create a C NDR client
77 --server[=OUTFILE] create server boilerplate
78 --template print a template for a pipe
79 --eth-parser[=OUTFILE]create an ethereal parser
80 --eth-header[=OUTFILE]create an ethereal header file
81 --swig[=OUTFILE] create swig wrapper file
82 --diff run diff on the idl and dumped output
83 --keep[=OUTFILE] keep the .pidl file
84 --odl accept ODL input
85 --dcom-proxy[=OUTFILE]create DCOM proxy (implies --odl)
86 --com-header[=OUTFILE]create header for COM interfaces (implies --odl)
87 --warn-compat warn about incompatibility with other compilers
96 'help|h|?' => \$opt_help,
97 'output=s' => \$opt_output,
98 'parse' => \$opt_parse,
100 'uint-enums' => \$opt_uint_enums,
101 'header:s' => \$opt_header,
102 'server:s' => \$opt_server,
103 'template' => \$opt_template,
104 'parser:s' => \$opt_parser,
105 'client:s' => \$opt_client,
106 'eth-parser:s' => \$opt_eth_parser,
107 'eth-header:s' => \$opt_eth_header,
109 'diff' => \$opt_diff,
111 'keep:s' => \$opt_keep,
112 'swig:s' => \$opt_swig,
113 'dcom-proxy:s' => \$opt_dcom_proxy,
114 'com-header:s' => \$opt_com_header,
115 'quiet' => \$opt_quiet,
116 'verbose' => \$opt_verbose,
117 'warn-compat' => \$opt_warn_compat
127 my $idl_file = shift;
132 my $basename = basename($idl_file, ".idl");
134 if (!defined($opt_output)) {
137 $output = $opt_output . $basename;
140 my($pidl_file) = ($opt_keep or Parse::Pidl::Util::ChangeExtension($output, ".pidl"));
142 unless ($opt_quiet) { print "Compiling $idl_file\n"; }
145 require Parse::Pidl::IDL;
146 my $idl_parser = new Parse::Pidl::IDL;
148 $pidl = $idl_parser->parse_idl($idl_file);
149 defined @$pidl || die "Failed to parse $idl_file";
150 require Parse::Pidl::Typelist;
151 Parse::Pidl::Typelist::LoadIdl($pidl);
152 require Parse::Pidl::Validator;
153 Parse::Pidl::Validator::Validate($pidl);
154 if (defined($opt_keep) && !SaveStructure($pidl_file, $pidl)) {
155 die "Failed to save $pidl_file\n";
158 $pidl = LoadStructure($pidl_file);
159 defined $pidl || die "Failed to load $pidl_file - maybe you need --parse\n";
162 if ($opt_uint_enums) {
163 Parse::Pidl::Util::setUseUintEnums(1);
167 require Parse::Pidl::Dump;
168 print Parse::Pidl::Dump($pidl);
172 my($tempfile) = Parse::Pidl::Util::ChangeExtension($output, ".tmp");
173 Parse::Pidl::Util::FileSave($tempfile, IdlDump::Dump($pidl));
174 system("diff -wu $idl_file $tempfile");
178 if (defined($opt_com_header)) {
179 require Parse::Pidl::Samba::COM::Header;
180 my $res = Parse::Pidl::Samba::COM::Header::Parse($pidl);
182 my $comh_filename = ($opt_com_header or (dirname($output) . "/com_$basename.h"));
183 Parse::Pidl::Util::FileSave($comh_filename,
184 "#include \"librpc/gen_ndr/ndr_orpc.h\"\n" .
185 "#include \"librpc/gen_ndr/ndr_$basename.h\"\n" .
191 if (defined($opt_dcom_proxy)) {
192 require Parse::Pidl::Samba::COM::Proxy;
193 my $res = Parse::Pidl::Samba::COM::Proxy::Parse($pidl);
195 my ($client) = ($opt_dcom_proxy or Parse::Pidl::Util::ChangeExtension($output, "_p.c"));
196 Parse::Pidl::Util::FileSave($client,
197 "#include \"includes.h\"\n" .
198 "#include \"librpc/gen_ndr/com_$basename.h\"\n" .
199 "#include \"lib/com/dcom/dcom.h\"\n" .$res);
204 if ($opt_warn_compat) {
205 require Parse::Pidl::Compat;
206 Parse::Pidl::Compat::Check($pidl);
210 require Parse::Pidl::ODL;
211 $pidl = Parse::Pidl::ODL::ODL2IDL($pidl);
214 if (defined($opt_header) or defined($opt_eth_parser) or
215 defined($opt_eth_header) or defined($opt_client) or
216 defined($opt_server) or defined($opt_parser) or
218 require Parse::Pidl::NDR;
219 $ndr = Parse::Pidl::NDR::Parse($pidl);
222 if (defined($opt_header)) {
223 my $header = $opt_header;
225 $header = Parse::Pidl::Util::ChangeExtension($output, ".h");
227 require Parse::Pidl::Samba::NDR::Header;
228 Parse::Pidl::Util::FileSave($header, Parse::Pidl::Samba::NDR::Header::Parse($ndr));
229 if (defined($opt_swig)) {
230 require Parse::Pidl::Samba::SWIG;
231 my($filename) = $output;
232 $filename =~ s/\/ndr_/\//;
233 $filename = ($opt_swig or Parse::Pidl::Util::ChangeExtension($filename, ".i"));
234 Parse::Pidl::Samba::SWIG::RewriteHeader($pidl, $header, $filename);
238 if (defined($opt_eth_header)) {
239 require Parse::Pidl::Ethereal::NDR::Header;
240 my($eparserhdr) = ($opt_eth_header or (dirname($output) . "/packet-dcerpc-$basename.h"));
242 Parse::Pidl::Util::FileSave($eparserhdr, Parse::Pidl::Ethereal::NDR::Header::Parse($ndr));
245 my $h_filename = Parse::Pidl::Util::ChangeExtension($output, ".h");
246 if (defined($opt_client)) {
247 require Parse::Pidl::Samba::NDR::Client;
248 my ($client) = ($opt_client or Parse::Pidl::Util::ChangeExtension($output, "_c.c"));
250 Parse::Pidl::Util::FileSave($client, Parse::Pidl::Samba::NDR::Client::Parse($ndr,$h_filename));
253 if (defined($opt_ejs)) {
254 require Parse::Pidl::Samba::EJS;
255 require Parse::Pidl::Samba::EJSHeader;
256 my $ejs = Parse::Pidl::Util::ChangeExtension($output, "_ejs.c");
257 Parse::Pidl::Util::FileSave($ejs, Parse::Pidl::Samba::EJS::Parse($ndr, $h_filename));
259 $ejs = Parse::Pidl::Util::ChangeExtension($output, "_ejs.h");
260 Parse::Pidl::Util::FileSave($ejs, Parse::Pidl::Samba::EJSHeader::Parse($ndr));
263 if (defined($opt_server)) {
264 require Parse::Pidl::Samba::NDR::Server;
267 foreach my $x (@{$pidl}) {
268 next if ($x->{TYPE} ne "INTERFACE");
270 if (Parse::Pidl::Util::has_property($x, "object")) {
271 require Parse::Pidl::Samba::COM::Stub;
272 $dcom .= Parse::Pidl::Samba::COM::Stub::ParseInterface($x);
276 Parse::Pidl::Util::FileSave(($opt_server or Parse::Pidl::Util::ChangeExtension($output, "_s.c")), Parse::Pidl::Samba::NDR::Server::Parse($ndr,$h_filename));
280 #include \"includes.h\"
281 #include \"$h_filename\"
282 #include \"rpc_server/dcerpc_server.h\"
283 #include \"rpc_server/common/common.h\"
287 Parse::Pidl::Util::FileSave(Parse::Pidl::Util::ChangeExtension($output, "_d.c"), $dcom);
291 if (defined($opt_parser)) {
292 my $parser = ($opt_parser or Parse::Pidl::Util::ChangeExtension($output, ".c"));
293 require Parse::Pidl::Samba::NDR::Parser;
294 Parse::Pidl::Util::FileSave($parser, Parse::Pidl::Samba::NDR::Parser::Parse($ndr, $parser));
297 if (defined($opt_eth_parser)) {
298 require Parse::Pidl::Ethereal::NDR::Parser;
299 my($eparser) = ($opt_eth_parser or dirname($output) . "/packet-dcerpc-$basename.c");
300 Parse::Pidl::Util::FileSave($eparser, Parse::Pidl::Ethereal::NDR::Parser::Parse($ndr, $basename, $eparser));
304 require Parse::Pidl::Samba::Template;
305 print Parse::Pidl::Samba::Template::Parse($pidl);
309 foreach my $filename (@ARGV) {
310 process_file($filename);