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;
42 my($opt_template) = 0;
55 my($opt_outputdir) = '.';
57 my($opt_warn_compat) = 0;
59 #########################################
63 print "perl IDL parser and code generator
64 Copyright (C) tridge\@samba.org
66 Usage: pidl [options] <idlfile>
70 --outputdir=OUTDIR put output in OUTDIR/ [.]
71 --parse parse a idl file to a .pidl file
72 --dump dump a pidl file back to idl
73 --uint-enums don't use C enums, instead use uint* types
74 --header[=OUTFILE] create generic header file
75 --ndr-header[=OUTFILE]create a C NDR-specific header file
76 --ndr-parser[=OUTFILE]create a C NDR parser
77 --ejs[=OUTFILE] create ejs wrapper file
78 --client[=OUTFILE] create a C NDR client
79 --server[=OUTFILE] create server boilerplate
80 --template print a template for a pipe
81 --eth-parser[=OUTFILE]create an ethereal parser
82 --eth-header[=OUTFILE]create an ethereal header file
83 --swig[=OUTFILE] create swig wrapper file
84 --diff run diff on the idl and dumped output
85 --keep[=OUTFILE] keep the .pidl file
86 --odl accept ODL input
87 --dcom-proxy[=OUTFILE]create DCOM proxy (implies --odl)
88 --com-header[=OUTFILE]create header for COM interfaces (implies --odl)
89 --warn-compat warn about incompatibility with other compilers
98 'help|h|?' => \$opt_help,
99 'outputdir=s' => \$opt_outputdir,
100 'parse' => \$opt_parse,
101 'dump' => \$opt_dump,
102 'uint-enums' => \$opt_uint_enums,
103 'ndr-header:s' => \$opt_ndr_header,
104 'header:s' => \$opt_header,
105 'server:s' => \$opt_server,
106 'template' => \$opt_template,
107 'ndr-parser:s' => \$opt_ndr_parser,
108 'client:s' => \$opt_client,
109 'eth-parser:s' => \$opt_eth_parser,
110 'eth-header:s' => \$opt_eth_header,
112 'diff' => \$opt_diff,
114 'keep:s' => \$opt_keep,
115 'swig:s' => \$opt_swig,
116 'dcom-proxy:s' => \$opt_dcom_proxy,
117 'com-header:s' => \$opt_com_header,
118 'quiet' => \$opt_quiet,
119 'verbose' => \$opt_verbose,
120 'warn-compat' => \$opt_warn_compat
130 my $idl_file = shift;
131 my $outputdir = $opt_outputdir;
135 my $basename = basename($idl_file, ".idl");
137 my($pidl_file) = ($opt_keep or "$outputdir/$basename.pidl");
139 unless ($opt_quiet) { print "Compiling $idl_file\n"; }
142 require Parse::Pidl::IDL;
143 my $idl_parser = new Parse::Pidl::IDL;
145 $pidl = $idl_parser->parse_idl($idl_file);
146 defined @$pidl || die "Failed to parse $idl_file";
147 require Parse::Pidl::Typelist;
148 Parse::Pidl::Typelist::LoadIdl($pidl);
149 require Parse::Pidl::Validator;
150 Parse::Pidl::Validator::Validate($pidl);
151 if (defined($opt_keep) && !SaveStructure($pidl_file, $pidl)) {
152 die "Failed to save $pidl_file\n";
155 $pidl = LoadStructure($pidl_file);
156 defined $pidl || die "Failed to load $pidl_file - maybe you need --parse\n";
159 if ($opt_uint_enums) {
160 Parse::Pidl::Util::setUseUintEnums(1);
164 require Parse::Pidl::Dump;
165 print Parse::Pidl::Dump($pidl);
169 my($tempfile) = "$outputdir/$basename.tmp";
170 Parse::Pidl::Util::FileSave($tempfile, IdlDump::Dump($pidl));
171 system("diff -wu $idl_file $tempfile");
175 if (defined($opt_com_header)) {
176 require Parse::Pidl::Samba::COM::Header;
177 my $res = Parse::Pidl::Samba::COM::Header::Parse($pidl);
179 my $comh_filename = ($opt_com_header or "$outputdir/com_$basename.h");
180 Parse::Pidl::Util::FileSave($comh_filename,
181 "#include \"librpc/gen_ndr/ndr_orpc.h\"\n" .
182 "#include \"$outputdir/ndr_$basename.h\"\n" .
188 if (defined($opt_dcom_proxy)) {
189 require Parse::Pidl::Samba::COM::Proxy;
190 my $res = Parse::Pidl::Samba::COM::Proxy::Parse($pidl);
192 my ($client) = ($opt_dcom_proxy or "$outputdir/$basename\_p.c");
193 Parse::Pidl::Util::FileSave($client,
194 "#include \"includes.h\"\n" .
195 "#include \"$outputdir/com_$basename.h\"\n" .
196 "#include \"lib/com/dcom/dcom.h\"\n" .$res);
201 if ($opt_warn_compat) {
202 require Parse::Pidl::Compat;
203 Parse::Pidl::Compat::Check($pidl);
207 require Parse::Pidl::ODL;
208 $pidl = Parse::Pidl::ODL::ODL2IDL($pidl);
211 if (defined($opt_ndr_header) or defined($opt_eth_parser) or
212 defined($opt_eth_header) or defined($opt_client) or
213 defined($opt_server) or defined($opt_ndr_parser) or
215 require Parse::Pidl::NDR;
216 $ndr = Parse::Pidl::NDR::Parse($pidl);
219 if (defined($opt_header)) {
220 my $header = ($opt_header or "$outputdir/$basename.h");
221 require Parse::Pidl::Samba::Header;
222 Parse::Pidl::Util::FileSave($header, Parse::Pidl::Samba::Header::Parse($pidl));
225 if (defined($opt_ndr_header)) {
226 my $header = ($opt_ndr_header or "$outputdir/ndr_$basename.h");
227 require Parse::Pidl::Samba::NDR::Header;
228 Parse::Pidl::Util::FileSave($header, Parse::Pidl::Samba::NDR::Header::Parse($pidl, $basename));
229 if (defined($opt_swig)) {
230 require Parse::Pidl::Samba::SWIG;
231 my($filename) = ($opt_swig or "$outputdir/$basename.i");
232 Parse::Pidl::Samba::SWIG::RewriteHeader($pidl, $header, $filename);
236 if (defined($opt_eth_header)) {
237 require Parse::Pidl::Ethereal::NDR::Header;
238 my($eparserhdr) = ($opt_eth_header or "$outputdir/packet-dcerpc-$basename.h");
240 Parse::Pidl::Util::FileSave($eparserhdr, Parse::Pidl::Ethereal::NDR::Header::Parse($ndr));
243 my $h_filename = "$outputdir/ndr_$basename.h";
244 if (defined($opt_client)) {
245 require Parse::Pidl::Samba::NDR::Client;
246 my ($client) = ($opt_client or "$outputdir/ndr_$basename\_c.c");
248 Parse::Pidl::Util::FileSave($client, Parse::Pidl::Samba::NDR::Client::Parse($ndr,$h_filename));
251 if (defined($opt_ejs)) {
252 require Parse::Pidl::Samba::EJS;
253 require Parse::Pidl::Samba::EJSHeader;
254 Parse::Pidl::Util::FileSave("$outputdir/ndr_$basename\_ejs.c", Parse::Pidl::Samba::EJS::Parse($ndr, $h_filename));
256 Parse::Pidl::Util::FileSave("$outputdir/ndr_$basename\_ejs.h", Parse::Pidl::Samba::EJSHeader::Parse($ndr));
259 if (defined($opt_server)) {
260 require Parse::Pidl::Samba::NDR::Server;
263 foreach my $x (@{$pidl}) {
264 next if ($x->{TYPE} ne "INTERFACE");
266 if (Parse::Pidl::Util::has_property($x, "object")) {
267 require Parse::Pidl::Samba::COM::Stub;
268 $dcom .= Parse::Pidl::Samba::COM::Stub::ParseInterface($x);
272 Parse::Pidl::Util::FileSave(($opt_server or "$outputdir/ndr_$basename\_s.c"), Parse::Pidl::Samba::NDR::Server::Parse($ndr,$h_filename));
276 #include \"includes.h\"
277 #include \"$h_filename\"
278 #include \"rpc_server/dcerpc_server.h\"
279 #include \"rpc_server/common/common.h\"
283 Parse::Pidl::Util::FileSave("$outputdir/$basename\_d.c", $dcom);
287 if (defined($opt_ndr_parser)) {
288 my $parser = ($opt_ndr_parser or "$outputdir/ndr_$basename.c");
289 require Parse::Pidl::Samba::NDR::Parser;
290 Parse::Pidl::Util::FileSave($parser, Parse::Pidl::Samba::NDR::Parser::Parse($ndr, $parser));
293 if (defined($opt_eth_parser)) {
294 require Parse::Pidl::Ethereal::NDR::Parser;
295 my($eparser) = ($opt_eth_parser or "$outputdir/packet-dcerpc-$basename.c");
296 Parse::Pidl::Util::FileSave($eparser, Parse::Pidl::Ethereal::NDR::Parser::Parse($ndr, $basename, $eparser));
300 require Parse::Pidl::Samba::Template;
301 print Parse::Pidl::Samba::Template::Parse($pidl);
305 foreach my $filename (@ARGV) {
306 process_file($filename);