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
11 use FindBin qw($RealBin);
13 use lib "$RealBin/lib";
17 use Parse::Pidl::Util;
19 #####################################################################
20 # save a data structure into a file
23 my($filename,$v) = @_;
24 FileSave($filename, Parse::Pidl::Util::MyDumper($v));
27 #####################################################################
28 # load a data structure from a file (as saved with SaveStructure)
32 my $contents = FileLoad($f);
33 defined $contents || return undef;
34 return eval "$contents";
37 #####################################################################
38 # read a file into a string
41 my($filename) = shift;
43 open(INPUTFILE, $filename) || return undef;
44 my($saved_delim) = $/;
46 my($data) = <INPUTFILE>;
52 #####################################################################
53 # write a string into a file
56 my($filename) = shift;
59 open(FILE, ">$filename") || die "can't open $filename";
65 my($opt_parse_tree) = 0;
67 my($opt_dump_idl) = 0;
68 my($opt_uint_enums) = 0;
72 my($opt_template) = 0;
85 my($opt_outputdir) = '.';
87 my($opt_warn_compat) = 0;
89 #########################################
93 print "perl IDL parser and code generator
94 Copyright (C) tridge\@samba.org
96 Usage: pidl [options] [--] <idlfile> [<idlfile>...]
100 --outputdir=OUTDIR put output in OUTDIR/ [.]
101 --odl accept ODL input
102 --warn-compat warn about incompatibility with other compilers
107 --dump-tree[=OUTFILE] dump internal representation to file [BASENAME.pidl]
108 --parse-tree read internal representation instead of IDL
109 --dump-idl regenerate IDL file
110 --diff run diff on original IDL and dumped output
113 --header[=OUTFILE] create generic header file [BASENAME.h]
114 --uint-enums don't use C enums, instead use uint* types
115 --ndr-header[=OUTFILE] create a C NDR-specific header file [ndr_BASENAME.h]
116 --ndr-parser[=OUTFILE] create a C NDR parser [ndr_BASENAME.c]
117 --client[=OUTFILE] create a C NDR client [ndr_BASENAME_c.c]
118 --tdr-header[=OUTFILE] create a C TDR header file [tdr_BASENAME.h]
119 --tdr-parser[=OUTFILE] create a C TDR parser [tdr_BASENAME.c]
120 --ejs[=OUTFILE] create ejs wrapper file [BASENAME_ejs.c]
121 --swig[=OUTFILE] create swig wrapper file [BASENAME.i]
122 --server[=OUTFILE] create server boilerplate [ndr_BASENAME_s.c]
123 --template print a template for a pipe
124 --dcom-proxy[=OUTFILE] create DCOM proxy (implies --odl) [ndr_BASENAME_p.c]
125 --com-header[=OUTFILE] create header for COM (implies --odl) [com_BASENAME.h]
128 --eth-parser[=OUTFILE] create ethereal parser and header
135 'help|h|?' => \$opt_help,
136 'outputdir=s' => \$opt_outputdir,
137 'dump-idl' => \$opt_dump_idl,
138 'dump-tree:s' => \$opt_dump_tree,
139 'parse-tree' => \$opt_parse_tree,
140 'uint-enums' => \$opt_uint_enums,
141 'ndr-header:s' => \$opt_ndr_header,
142 'header:s' => \$opt_header,
143 'server:s' => \$opt_server,
144 'tdr-header:s' => \$opt_tdr_header,
145 'tdr-parser:s' => \$opt_tdr_parser,
146 'template' => \$opt_template,
147 'ndr-parser:s' => \$opt_ndr_parser,
148 'client:s' => \$opt_client,
149 'eth-parser:s' => \$opt_eth_parser,
151 'diff' => \$opt_diff,
153 'swig:s' => \$opt_swig,
154 'dcom-proxy:s' => \$opt_dcom_proxy,
155 'com-header:s' => \$opt_com_header,
156 'quiet' => \$opt_quiet,
157 'verbose' => \$opt_verbose,
158 'warn-compat' => \$opt_warn_compat
168 my $idl_file = shift;
169 my $outputdir = $opt_outputdir;
173 my $basename = basename($idl_file, ".idl");
175 my($pidl_file) = ($opt_dump_tree or "$outputdir/$basename.pidl");
177 unless ($opt_quiet) { print "Compiling $idl_file\n"; }
179 if ($opt_parse_tree) {
180 $pidl = LoadStructure($pidl_file);
181 defined $pidl || die "Failed to load $pidl_file";
183 require Parse::Pidl::IDL;
184 my $idl_parser = new Parse::Pidl::IDL;
186 $pidl = $idl_parser->parse_idl($idl_file);
187 defined @$pidl || die "Failed to parse $idl_file";
188 require Parse::Pidl::Typelist;
189 Parse::Pidl::Typelist::LoadIdl($pidl);
192 if (defined($opt_dump_tree) && !SaveStructure($pidl_file, $pidl)) {
193 die "Failed to save $pidl_file\n";
196 if ($opt_uint_enums) {
197 Parse::Pidl::Util::setUseUintEnums(1);
201 require Parse::Pidl::Dump;
202 print Parse::Pidl::Dump($pidl);
206 my($tempfile) = "$outputdir/$basename.tmp";
207 FileSave($tempfile, IdlDump::Dump($pidl));
208 system("diff -wu $idl_file $tempfile");
212 if (defined($opt_com_header)) {
213 require Parse::Pidl::Samba::COM::Header;
214 my $res = Parse::Pidl::Samba::COM::Header::Parse($pidl);
216 my $comh_filename = ($opt_com_header or "$outputdir/com_$basename.h");
217 FileSave($comh_filename,
218 "#include \"librpc/gen_ndr/ndr_orpc.h\"\n" .
219 "#include \"$outputdir/ndr_$basename.h\"\n" .
225 if (defined($opt_dcom_proxy)) {
226 require Parse::Pidl::Samba::COM::Proxy;
227 my $res = Parse::Pidl::Samba::COM::Proxy::Parse($pidl);
229 my ($client) = ($opt_dcom_proxy or "$outputdir/$basename\_p.c");
231 "#include \"includes.h\"\n" .
232 "#include \"$outputdir/com_$basename.h\"\n" .
233 "#include \"lib/com/dcom/dcom.h\"\n" .$res);
238 if ($opt_warn_compat) {
239 require Parse::Pidl::Compat;
240 Parse::Pidl::Compat::Check($pidl);
244 require Parse::Pidl::ODL;
245 $pidl = Parse::Pidl::ODL::ODL2IDL($pidl);
248 if (defined($opt_ndr_header) or defined($opt_eth_parser) or
249 defined($opt_client) or defined($opt_server) or
250 defined($opt_ndr_parser) or defined($opt_ejs)) {
251 require Parse::Pidl::NDR;
252 Parse::Pidl::NDR::Validate($pidl);
253 $ndr = Parse::Pidl::NDR::Parse($pidl);
256 if (defined($opt_header)) {
257 my $header = ($opt_header or "$outputdir/$basename.h");
258 require Parse::Pidl::Samba::Header;
259 FileSave($header, Parse::Pidl::Samba::Header::Parse($pidl));
262 if (defined($opt_ndr_header)) {
263 my $header = ($opt_ndr_header or "$outputdir/ndr_$basename.h");
264 require Parse::Pidl::Samba::NDR::Header;
265 FileSave($header, Parse::Pidl::Samba::NDR::Header::Parse($pidl, $basename));
266 if (defined($opt_swig)) {
267 require Parse::Pidl::Samba::SWIG;
268 my($filename) = ($opt_swig or "$outputdir/$basename.i");
269 Parse::Pidl::Samba::SWIG::RewriteHeader($pidl, $header, $filename);
273 my $h_filename = "$outputdir/ndr_$basename.h";
274 if (defined($opt_client)) {
275 require Parse::Pidl::Samba::NDR::Client;
276 my ($client) = ($opt_client or "$outputdir/ndr_$basename\_c.c");
278 FileSave($client, Parse::Pidl::Samba::NDR::Client::Parse($ndr,$h_filename));
281 if (defined($opt_ejs)) {
282 require Parse::Pidl::Samba::EJS;
283 require Parse::Pidl::Samba::EJSHeader;
284 FileSave("$outputdir/ndr_$basename\_ejs.c", Parse::Pidl::Samba::EJS::Parse($ndr, $h_filename));
286 FileSave("$outputdir/ndr_$basename\_ejs.h", Parse::Pidl::Samba::EJSHeader::Parse($ndr));
289 if (defined($opt_server)) {
290 require Parse::Pidl::Samba::NDR::Server;
293 foreach my $x (@{$pidl}) {
294 next if ($x->{TYPE} ne "INTERFACE");
296 if (Parse::Pidl::Util::has_property($x, "object")) {
297 require Parse::Pidl::Samba::COM::Stub;
298 $dcom .= Parse::Pidl::Samba::COM::Stub::ParseInterface($x);
302 FileSave(($opt_server or "$outputdir/ndr_$basename\_s.c"), Parse::Pidl::Samba::NDR::Server::Parse($ndr,$h_filename));
306 #include \"includes.h\"
307 #include \"$h_filename\"
308 #include \"rpc_server/dcerpc_server.h\"
309 #include \"rpc_server/common/common.h\"
313 FileSave("$outputdir/$basename\_d.c", $dcom);
317 if (defined($opt_ndr_parser)) {
318 my $parser = ($opt_ndr_parser or "$outputdir/ndr_$basename.c");
319 require Parse::Pidl::Samba::NDR::Parser;
320 FileSave($parser, Parse::Pidl::Samba::NDR::Parser::Parse($ndr, $parser));
323 if (defined($opt_eth_parser)) {
324 require Parse::Pidl::Ethereal::NDR;
325 my($eparser) = ($opt_eth_parser or "$outputdir/packet-dcerpc-$basename.c");
326 my $eheader = $eparser;
327 $eheader =~ s/\.c$/\.h/;
328 my $cnffile = $idl_file;
329 $cnffile =~ s/\.idl$/\.cnf/;
331 my ($dp, $dh) = Parse::Pidl::Ethereal::NDR::Parse($ndr, $idl_file, $eheader, $cnffile);
332 FileSave($eparser, $dp) if defined($dp);
333 FileSave($eheader, $dh) if defined($dh);
336 my $tdr_parser = ($opt_tdr_parser or "$outputdir/tdr_$basename.c");
337 my $tdr_header = ($opt_tdr_header or "$outputdir/tdr_$basename.h");
338 if (defined($opt_tdr_parser)) {
339 require Parse::Pidl::Samba::TDR;
340 FileSave($tdr_parser, Parse::Pidl::Samba::TDR::Parser($pidl, $tdr_header));
343 if (defined($opt_tdr_header)) {
344 require Parse::Pidl::Samba::TDR;
345 FileSave($tdr_header, Parse::Pidl::Samba::TDR::Header($pidl, $outputdir,$basename));
349 require Parse::Pidl::Samba::Template;
350 print Parse::Pidl::Samba::Template::Parse($pidl);
354 if (scalar(@ARGV) == 0) {
355 print "pidl: no input files\n";
359 process_file($_) foreach (@ARGV);