1#!/usr/bin/perl -w
2
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
9
10=pod
11
12=head1 NAME
13
14pidl - An IDL compiler written in Perl
15
16=head1 SYNOPSIS
17
18pidl --help
19
20pidl [--outputdir[=OUTNAME]] [--includedir DIR...] [--parse-idl-tree] [--dump-idl-tree] [--dump-ndr-tree] [--header[=OUTPUT]] [--ejs[=OUTPUT]] [--swig[=OUTPUT]] [--uint-enums] [--ndr-parser[=OUTPUT]] [--client] [--server] [--dcom-proxy] [--com-header] [--warn-compat] [--quiet] [--verbose] [--template] [--ws-parser[=OUTPUT]] [--diff] [--dump-idl] [--tdr-parser[=OUTPUT]] [--samba3-ndr-client[=OUTPUT]] [--samba3-ndr-server[=OUTPUT]] [<idlfile>.idl]...
21
22=head1 DESCRIPTION
23
24pidl is an IDL compiler written in Perl that aims to be somewhat
25compatible with the midl compiler. IDL is short for
26"Interface Definition Language".
27
28pidl can generate stubs for DCE/RPC server code, DCE/RPC
29client code and Wireshark dissectors for DCE/RPC traffic.
30
31IDL compilers like pidl take a description
32of an interface as their input and use it to generate C
33(though support for other languages may be added later) code that
34can use these interfaces, pretty print data sent
35using these interfaces, or even generate Wireshark
36dissectors that can parse data sent over the
37wire by these interfaces.
38
39pidl takes IDL files in the same format as is used by midl,
40converts it to a .pidl file (which contains pidl's internal representation of the interface) and can then generate whatever output you need.
41.pidl files should be used for debugging purposes only. Write your
42interface definitions in .idl format.
43
44The goal of pidl is to implement a IDL compiler that can be used
45while developing the RPC subsystem in Samba (for
46both marshalling/unmarshalling and debugging purposes).
47
48=head1 OPTIONS
49
50=over 4
51
52=item I<--help>
53
54Show list of available options.
55
56=item I<--outputdir OUTNAME>
57
58Write output files to the specified directory.  Defaults to the current
59directory.
60
61=item I<--includedir DIR>
62
63Add DIR to the search path used by the preprocessor. This option can be
64specified multiple times.
65
66=item I<--parse-idl-tree>
67
68Read internal tree structure from input files rather
69than assuming they contain IDL.
70
71=item I<--dump-idl>
72
73Generate a new IDL file. File will be named OUTNAME.idl.
74
75=item I<--header>
76
77Generate a C header file for the specified interface. Filename defaults to OUTNAME.h.
78
79=item I<--ndr-parser>
80
81Generate a C file and C header containing NDR parsers. The filename for
82the parser defaults to ndr_OUTNAME.c. The header filename will be the
83parser filename with the extension changed from .c to .h.
84
85=item I<--tdr-parser>
86
87Generate a C file and C header containing TDR parsers. The filename for
88the parser defaults to tdr_OUTNAME.c. The header filename will be the
89parser filename with the extension changed from .c to .h.
90
91=item I<--server>
92
93Generate boilerplate for the RPC server that implements
94the interface. Filename defaults to ndr_OUTNAME_s.c.
95
96=item I<--template>
97
98Generate stubs for a RPC server that implements the interface. Output will
99be written to stdout.
100
101=item I<--ws-parser>
102
103Generate an Wireshark dissector (in C) and header file. The dissector filename
104defaults to packet-dcerpc-OUTNAME.c while the header filename defaults to
105packet-dcerpc-OUTNAME.h.
106
107Pidl will read additional data from an Wireshark conformance file if present.
108Such a file should have the same location as the IDL file but with the
109extension I<cnf> rather than I<idl>. See L<Parse::Pidl::Wireshark::Conformance>
110for details on the format of this file.
111
112=item I<--diff>
113
114Parse an IDL file,  generate a new IDL file based on the internal data
115structures and see if there are any differences with the original IDL file.
116Useful for debugging pidl.
117
118=item I<--dump-idl-tree>
119
120Tell pidl to dump the internal tree representation of an IDL
121file the to disk. Useful for debugging pidl.
122
123=item I<--dump-ndr-tree>
124
125Tell pidl to dump the internal NDR information tree it generated
126from the IDL file to disk.  Useful for debugging pidl.
127
128=item I<--samba3-ndr-client>
129
130Generate client calls for Samba3, to be placed in rpc_client/. Instead of
131calling out to the code in Samba3's rpc_parse/, this will call out to
132Samba4's NDR code instead.
133
134=item I<--samba3-ndr-server>
135
136Generate server calls for Samba3, to be placed in rpc_server/. Instead of
137calling out to the code in Samba3's rpc_parse/, this will call out to
138Samba4's NDR code instead.
139
140=back
141
142=head1 IDL SYNTAX
143
144IDL files are always preprocessed using the C preprocessor.
145
146Pretty much everything in an interface (the interface itself, functions,
147parameters) can have attributes (or properties whatever name you give them).
148Attributes always prepend the element they apply to and are surrounded
149by square brackets ([]). Multiple attributes are separated by comma's;
150arguments to attributes are specified between parentheses.
151
152See the section COMPATIBILITY for the list of attributes that
153pidl supports.
154
155C-style comments can be used.
156
157=head2 CONFORMANT ARRAYS
158
159A conformant array is one with that ends in [*] or []. The strange
160things about conformant arrays are that they can only appear as the last
161element of a structure (unless there is a pointer to the conformant array,
162of course) and the array size appears before the structure itself on the wire.
163
164So, in this example:
165
166	typedef struct {
167		long abc;
168		long count;
169		long foo;
170		[size_is(count)] long s[*];
171	} Struct1;
172
173it appears like this:
174
175	[size_is] [abc] [count] [foo] [s...]
176
177the first [size_is] field is the allocation size of the array, and
178occurs before the array elements and even before the structure
179alignment.
180
181Note that size_is() can refer to a constant, but that doesn't change
182the wire representation. It does not make the array a fixed array.
183
184midl.exe would write the above array as the following C header:
185
186   typedef struct {
187		long abc;
188		long count;
189		long foo;
190		long s[1];
191	} Struct1;
192
193pidl takes a different approach, and writes it like this:
194
195    typedef struct {
196		long abc;
197		long count;
198		long foo;
199		long *s;
200	} Struct1;
201
202=head2 VARYING ARRAYS
203
204A varying array looks like this:
205
206	typedef struct {
207		long abc;
208		long count;
209		long foo;
210		[size_is(count)] long *s;
211	} Struct1;
212
213This will look like this on the wire:
214
215	[abc] [count] [foo] [PTR_s]    [count] [s...]
216
217=head2 FIXED ARRAYS
218
219A fixed array looks like this:
220
221    typedef struct {
222	    long s[10];
223    } Struct1;
224
225The NDR representation looks just like 10 separate long
226declarations. The array size is not encoded on the wire.
227
228pidl also supports "inline" arrays, which are not part of the IDL/NDR
229standard. These are declared like this:
230
231    typedef struct {
232	    uint32 foo;
233	    uint32 count;
234	    uint32 bar;
235	    long s[count];
236    } Struct1;
237
238This appears like this:
239
240	[foo] [count] [bar] [s...]
241
242Fixed arrays are an extension added to support some of the strange
243embedded structures in security descriptors and spoolss.
244
245This section is by no means complete. See the OpenGroup and MSDN
246	documentation for additional information.
247
248=head1 COMPATIBILITY WITH MIDL
249
250=head2 Missing features in pidl
251
252The following MIDL features are not (yet) implemented in pidl
253or are implemented with an incompatible interface:
254
255=over
256
257=item *
258
259Asynchronous communication
260
261=item *
262
263Typelibs (.tlb files)
264
265=item *
266
267Datagram support (ncadg_*)
268
269=back
270
271=head2 Supported attributes and statements
272
273in, out, ref, length_is, switch_is, size_is, uuid, case, default, string,
274unique, ptr, pointer_default, v1_enum, object, helpstring, range, local,
275call_as, endpoint, switch_type, progid, coclass, iid_is, represent_as,
276transmit_as, import, include.
277
278=head2 PIDL Specific properties
279
280=over 4
281
282=item public
283
284The [public] property on a structure or union is a pidl extension that
285forces the generated pull/push functions to be non-static. This allows
286you to declare types that can be used between modules. If you don't
287specify [public] then pull/push functions for other than top-level
288functions are declared static.
289
290=item noprint
291
292The [noprint] property is a pidl extension that allows you to specify
293that pidl should not generate a ndr_print_*() function for that
294structure or union. This is used when you wish to define your own
295print function that prints a structure in a nicer manner. A good
296example is the use of [noprint] on dom_sid, which allows the
297pretty-printing of SIDs.
298
299=item value
300
301The [value(expression)] property is a pidl extension that allows you
302to specify the value of a field when it is put on the wire. This
303allows fields that always have a well-known value to be automatically
304filled in, thus making the API more programmer friendly. The
305expression can be any C expression.
306
307=item relative
308
309The [relative] property can be supplied on a pointer. When it is used
310it declares the pointer as a spoolss style "relative" pointer, which
311means it appears on the wire as an offset within the current
312encapsulating structure. This is not part of normal IDL/NDR, but it is
313a very useful extension as it avoids the manual encoding of many
314complex structures.
315
316=item subcontext(length)
317
318Specifies that a size of I<length>
319bytes should be read, followed by a blob of that size,
320which will be parsed as NDR.
321
322=item flag
323
324Specify boolean options, mostly used for
325low-level NDR options. Several options
326can be specified using the | character.
327Note that flags are inherited by substructures!
328
329=item nodiscriminant
330
331The [nodiscriminant] property on a union means that the usual uint16
332discriminent field at the start of the union on the wire is
333omitted. This is not normally allowed in IDL/NDR, but is used for some
334spoolss structures.
335
336=item charset(name)
337
338Specify that the array or string uses the specified
339charset. If this attribute is specified, pidl will
340take care of converting the character data from this format
341to the host format. Commonly used values are UCS2, DOS and UTF8.
342
343=back
344
345=head2 Unsupported MIDL properties or statements
346
347aggregatable, appobject, async_uuid, bindable, control, cpp_quote,
348defaultbind, defaultcollelem, defaultvalue, defaultvtable, dispinterface,
349displaybind, dual, entry, first_is, helpcontext, helpfile, helpstringcontext,
350helpstringdll, hidden, idl_module, idl_quote, id, immediatebind, importlib,
351includelib, last_is, lcid, licensed, max_is, module,
352ms_union, no_injected_text, nonbrowsable, noncreatable, nonextensible, odl,
353oleautomation, optional, pragma, propget, propputref, propput, readonly,
354requestedit, restricted, retval, source, uidefault,
355usesgetlasterror, vararg, vi_progid, wire_marshal.
356
357=head1 EXAMPLES
358
359	# Generating an Wireshark parser
360	$ ./pidl --ws-parser -- atsvc.idl
361
362	# Generating a TDR parser and header
363	$ ./pidl --tdr-parser --header -- regf.idl
364
365	# Generating a Samba3 client and server
366	$ ./pidl --samba3-ndr-client --samba3-ndr-server -- dfs.idl
367
368	# Generating a Samba4 NDR parser, client and server
369	$ ./pidl --ndr-parser --ndr-client --ndr-server -- samr.idl
370
371=head1 SEE ALSO
372
373L<http://msdn.microsoft.com/library/en-us/rpc/rpc/field_attributes.asp>,
374L<http://wiki.wireshark.org/DCE/RPC>,
375L<http://www.samba.org/>,
376L<yapp(1)>
377
378=head1 LICENSE
379
380pidl is licensed under the GNU General Public License L<http://www.gnu.org/licenses/gpl.html>.
381
382=head1 AUTHOR
383
384pidl was written by Andrew Tridgell, Stefan Metzmacher, Tim Potter and Jelmer
385Vernooij. The current maintainer is Jelmer Vernooij.
386
387This manpage was written by Jelmer Vernooij, partially based on the original
388pidl README by Andrew Tridgell.
389
390=cut
391
392
393use strict;
394use FindBin qw($RealBin);
395use lib "$RealBin";
396use lib "$RealBin/lib";
397use Getopt::Long;
398use File::Basename;
399use Parse::Pidl;
400use Parse::Pidl::Util;
401use Parse::Pidl::ODL;
402
403#####################################################################
404# save a data structure into a file
405sub SaveStructure($$)
406{
407	my($filename,$v) = @_;
408	FileSave($filename, Parse::Pidl::Util::MyDumper($v));
409}
410
411#####################################################################
412# load a data structure from a file (as saved with SaveStructure)
413sub LoadStructure($)
414{
415	my $f = shift;
416	my $contents = FileLoad($f);
417	defined $contents || return undef;
418	return eval "$contents";
419}
420
421#####################################################################
422# read a file into a string
423sub FileLoad($)
424{
425    my($filename) = shift;
426    local(*INPUTFILE);
427    open(INPUTFILE, $filename) || return undef;
428    my($saved_delim) = $/;
429    undef $/;
430    my($data) = <INPUTFILE>;
431    close(INPUTFILE);
432    $/ = $saved_delim;
433    return $data;
434}
435
436#####################################################################
437# write a string into a file
438sub FileSave($$)
439{
440    my($filename) = shift;
441    my($v) = shift;
442    local(*FILE);
443    open(FILE, ">$filename") || die "can't open $filename";
444    print FILE $v;
445    close(FILE);
446}
447
448my(@opt_incdirs) = ();
449my($opt_help) = 0;
450my($opt_parse_idl_tree) = 0;
451my($opt_dump_idl_tree);
452my($opt_dump_ndr_tree);
453my($opt_dump_idl) = 0;
454my($opt_uint_enums) = 0;
455my($opt_diff) = 0;
456my($opt_header);
457my($opt_samba3_header);
458my($opt_samba3_parser);
459my($opt_samba3_server);
460my($opt_samba3_ndr_client);
461my($opt_samba3_ndr_server);
462my($opt_template) = 0;
463my($opt_client);
464my($opt_server);
465my($opt_ndr_parser);
466my($opt_tdr_parser);
467my($opt_ws_parser);
468my($opt_swig);
469my($opt_dcom_proxy);
470my($opt_com_header);
471my($opt_ejs);
472my($opt_quiet) = 0;
473my($opt_outputdir) = '.';
474my($opt_verbose) = 0;
475my($opt_warn_compat) = 0;
476
477#########################################
478# display help text
479sub ShowHelp()
480{
481print "perl IDL parser and code generator
482Copyright (C) Andrew Tridgell <tridge\@samba.org>
483Copyright (C) Jelmer Vernooij <jelmer\@samba.org>
484
485Usage: pidl [options] [--] <idlfile> [<idlfile>...]
486
487Generic Options:
488 --help                  this help page
489 --outputdir=OUTDIR      put output in OUTDIR/ [.]
490 --warn-compat           warn about incompatibility with other compilers
491 --quiet                 be quiet
492 --verbose               be verbose
493 --includedir DIR        search DIR for included files
494
495Debugging:
496 --dump-idl-tree[=FILE]  dump internal representation to file [BASENAME.pidl]
497 --parse-idl-tree        read internal representation instead of IDL
498 --dump-ndr-tree[=FILE]  dump internal NDR data tree to file [BASENAME.ndr]
499 --dump-idl              regenerate IDL file
500 --diff                  run diff on original IDL and dumped output
501
502Samba 4 output:
503 --header[=OUTFILE]      create generic header file [BASENAME.h]
504 --uint-enums            don't use C enums, instead use uint* types
505 --ndr-parser[=OUTFILE]  create a C NDR parser [ndr_BASENAME.c]
506 --client[=OUTFILE]      create a C NDR client [ndr_BASENAME_c.c]
507 --tdr-parser[=OUTFILE]  create a C TDR parser [tdr_BASENAME.c]
508 --ejs[=OUTFILE]         create ejs wrapper file [BASENAME_ejs.c]
509 --swig[=OUTFILE]        create swig wrapper file [BASENAME.i]
510 --server[=OUTFILE]      create server boilerplate [ndr_BASENAME_s.c]
511 --template              print a template for a pipe
512 --dcom-proxy[=OUTFILE]  create DCOM proxy [ndr_BASENAME_p.c]
513 --com-header[=OUTFILE]  create header for COM [com_BASENAME.h]
514
515Samba 3 output:
516 --samba3-ndr-client[=OUTF] create client calls for Samba3
517                            using Samba4's NDR code [cli_BASENAME.c]
518 --samba3-ndr-server[=OUTF] create server call wrapper for Samba3
519                            using Samba4's NDR code [srv_BASENAME.c]
520
521Wireshark parsers:
522 --ws-parser[=OUTFILE]  create Wireshark parser and header
523\n";
524    exit(0);
525}
526
527# main program
528my $result = GetOptions (
529	    'help|h|?' => \$opt_help,
530	    'outputdir=s' => \$opt_outputdir,
531	    'dump-idl' => \$opt_dump_idl,
532		'dump-idl-tree:s' => \$opt_dump_idl_tree,
533		'parse-idl-tree' => \$opt_parse_idl_tree,
534		'dump-ndr-tree:s' => \$opt_dump_ndr_tree,
535	    'uint-enums' => \$opt_uint_enums,
536		'samba3-ndr-client:s' => \$opt_samba3_ndr_client,
537		'samba3-ndr-server:s' => \$opt_samba3_ndr_server,
538		'header:s' => \$opt_header,
539	    'server:s' => \$opt_server,
540	    'tdr-parser:s' => \$opt_tdr_parser,
541	    'template' => \$opt_template,
542	    'ndr-parser:s' => \$opt_ndr_parser,
543	    'client:s' => \$opt_client,
544	    'ws-parser:s' => \$opt_ws_parser,
545	    'ejs' => \$opt_ejs,
546	    'diff' => \$opt_diff,
547	    'swig:s' => \$opt_swig,
548	    'dcom-proxy:s' => \$opt_dcom_proxy,
549	    'com-header:s' => \$opt_com_header,
550	    'quiet' => \$opt_quiet,
551		'verbose' => \$opt_verbose,
552	    'warn-compat' => \$opt_warn_compat,
553		'includedir=s@' => \@opt_incdirs
554	    );
555
556if (not $result) {
557	exit(1);
558}
559
560if ($opt_help) {
561    ShowHelp();
562    exit(0);
563}
564
565sub process_file($)
566{
567	my $idl_file = shift;
568	my $outputdir = $opt_outputdir;
569	my $pidl;
570	my $ndr;
571
572	my $basename = basename($idl_file, ".idl");
573
574	unless ($opt_quiet) { print "Compiling $idl_file\n"; }
575
576	if ($opt_parse_idl_tree) {
577		$pidl = LoadStructure($idl_file);
578		defined $pidl || die "Failed to load $idl_file";
579	} else {
580		require Parse::Pidl::IDL;
581
582		$pidl = Parse::Pidl::IDL::parse_file($idl_file, \@opt_incdirs);
583		@$pidl || die "Failed to parse $idl_file";
584		require Parse::Pidl::Typelist;
585		Parse::Pidl::Typelist::LoadIdl($pidl);
586	}
587
588	if (defined($opt_dump_idl_tree)) {
589		my($pidl_file) = ($opt_dump_idl_tree or "$outputdir/$basename.pidl");
590		SaveStructure($pidl_file, $pidl) or die "Failed to save $pidl_file\n";
591	}
592
593	if ($opt_uint_enums) {
594		Parse::Pidl::Util::setUseUintEnums(1);
595	}
596
597	if ($opt_dump_idl) {
598		require Parse::Pidl::Dump;
599		print Parse::Pidl::Dump($pidl);
600	}
601
602	if ($opt_diff) {
603		my($tempfile) = "$outputdir/$basename.tmp";
604		FileSave($tempfile, IdlDump::Dump($pidl));
605		system("diff -wu $idl_file $tempfile");
606		unlink($tempfile);
607	}
608
609
610	my $comh_filename = ($opt_com_header or "$outputdir/com_$basename.h");
611	if (defined($opt_com_header)) {
612		require Parse::Pidl::Samba4::COM::Header;
613		my $res = Parse::Pidl::Samba4::COM::Header::Parse($pidl,"$outputdir/ndr_$basename.h");
614		if ($res) {
615			FileSave($comh_filename, $res);
616		}
617	}
618
619	if (defined($opt_dcom_proxy)) {
620		require Parse::Pidl::Samba4::COM::Proxy;
621		my $res = Parse::Pidl::Samba4::COM::Proxy::Parse($pidl,$comh_filename);
622		if ($res) {
623			my ($client) = ($opt_dcom_proxy or "$outputdir/$basename\_p.c");
624			FileSave($client, $res);
625		}
626	}
627
628	if ($opt_warn_compat) {
629		require Parse::Pidl::Compat;
630		Parse::Pidl::Compat::Check($pidl);
631	}
632
633	$pidl = Parse::Pidl::ODL::ODL2IDL($pidl);
634
635	if (defined($opt_ws_parser) or
636	    defined($opt_client) or defined($opt_server) or
637	    defined($opt_ndr_parser) or defined($opt_ejs) or
638		defined($opt_dump_ndr_tree) or defined($opt_samba3_header) or
639	    defined($opt_samba3_parser) or defined($opt_samba3_server) or
640		defined($opt_swig) or defined($opt_samba3_ndr_client) or
641		defined($opt_samba3_ndr_server)) {
642		require Parse::Pidl::NDR;
643		$ndr = Parse::Pidl::NDR::Parse($pidl);
644	}
645
646	if (defined($opt_dump_ndr_tree)) {
647		my($ndr_file) = ($opt_dump_ndr_tree or "$outputdir/$basename.ndr");
648		SaveStructure($ndr_file, $ndr) or die "Failed to save $ndr_file\n";
649	}
650
651	my $gen_header = ($opt_header or "$outputdir/$basename.h");
652	if (defined($opt_header)) {
653		require Parse::Pidl::Samba4::Header;
654		FileSave($gen_header, Parse::Pidl::Samba4::Header::Parse($pidl));
655	}
656
657	my $h_filename = "$outputdir/ndr_$basename.h";
658	if (defined($opt_client)) {
659		require Parse::Pidl::Samba4::NDR::Client;
660		my ($c_client) = ($opt_client or "$outputdir/ndr_$basename\_c.c");
661		my ($c_header) = $c_client;
662		$c_header =~ s/\.c$/.h/;
663
664		my ($srcd,$hdrd) = Parse::Pidl::Samba4::NDR::Client::Parse(
665			$ndr,$gen_header,$h_filename,$c_header);
666
667		FileSave($c_client, $srcd);
668		FileSave($c_header, $hdrd);
669	}
670
671	if (defined($opt_swig)) {
672		  require Parse::Pidl::Samba4::SWIG;
673		  my($filename) = ($opt_swig or "$outputdir/$basename.i");
674		  my $code = Parse::Pidl::Samba4::SWIG::Parse($ndr, $basename, "$outputdir/ndr_$basename\_c.h", $gen_header);
675		  FileSave($filename, $code);
676	}
677
678	if (defined($opt_ejs)) {
679		require Parse::Pidl::Samba4::EJS;
680		my ($hdr,$prsr) = Parse::Pidl::Samba4::EJS::Parse($ndr, $h_filename);
681		FileSave("$outputdir/ndr_$basename\_ejs.c", $prsr);
682		FileSave("$outputdir/ndr_$basename\_ejs.h", $hdr);
683	}
684
685	if (defined($opt_server)) {
686		require Parse::Pidl::Samba4::NDR::Server;
687		my $dcom = "";
688
689		foreach (@{$pidl}) {
690			next if ($_->{TYPE} ne "INTERFACE");
691
692			if (Parse::Pidl::Util::has_property($_, "object")) {
693				require Parse::Pidl::Samba4::COM::Stub;
694				$dcom .= Parse::Pidl::Samba4::COM::Stub::ParseInterface($_);
695			}
696		}
697
698		FileSave(($opt_server or "$outputdir/ndr_$basename\_s.c"), Parse::Pidl::Samba4::NDR::Server::Parse($ndr,$h_filename));
699
700		if ($dcom ne "") {
701			$dcom = "
702#include \"includes.h\"
703#include \"$h_filename\"
704#include \"rpc_server/dcerpc_server.h\"
705#include \"rpc_server/common/common.h\"
706
707$dcom
708";
709	FileSave("$outputdir/$basename\_d.c", $dcom);
710		}
711	}
712
713	if (defined($opt_ndr_parser)) {
714		my $parser_fname = ($opt_ndr_parser or "$outputdir/ndr_$basename.c");
715		require Parse::Pidl::Samba4::NDR::Parser;
716		my ($header,$parser) = Parse::Pidl::Samba4::NDR::Parser::Parse($ndr, $gen_header, $h_filename);
717
718
719		FileSave($parser_fname, $parser);
720		FileSave($h_filename, $header);
721
722	}
723
724	if (defined($opt_ws_parser)) {
725	  require Parse::Pidl::Wireshark::NDR;
726	  my($eparser) = ($opt_ws_parser or "$outputdir/packet-dcerpc-$basename.c");
727	  my $eheader = $eparser;
728	  $eheader =~ s/\.c$/\.h/;
729	  my $cnffile = $idl_file;
730	  $cnffile =~ s/\.idl$/\.cnf/;
731
732	  my ($dp, $dh) = Parse::Pidl::Wireshark::NDR::Parse($ndr, $idl_file, $eheader, $cnffile);
733	  FileSave($eparser, $dp) if defined($dp);
734	  FileSave($eheader, $dh) if defined($dh);
735	}
736
737	if (defined($opt_tdr_parser)) {
738		my $tdr_parser = ($opt_tdr_parser or "$outputdir/tdr_$basename.c");
739		my $tdr_header = $tdr_parser;
740		$tdr_header =~ s/\.c$/\.h/;
741		require Parse::Pidl::Samba4::TDR;
742		my ($hdr,$prsr) = Parse::Pidl::Samba4::TDR::Parser($pidl, $tdr_header, $gen_header);
743		FileSave($tdr_parser, $prsr);
744		FileSave($tdr_header, $hdr);
745	}
746
747	if ($opt_template) {
748		require Parse::Pidl::Samba4::Template;
749		print Parse::Pidl::Samba4::Template::Parse($pidl);
750	}
751
752	if (defined($opt_samba3_ndr_client)) {
753		my $client = ($opt_samba3_ndr_client or "$outputdir/cli_$basename.c");
754		my $header = $client; $header =~ s/\.c$/\.h/;
755		require Parse::Pidl::Samba3::ClientNDR;
756		my ($c_code,$h_code) = Parse::Pidl::Samba3::ClientNDR::Parse($ndr, $header, $h_filename);
757		FileSave($client, $c_code);
758		FileSave($header, $h_code);
759	}
760
761	if (defined($opt_samba3_ndr_server)) {
762		my $server = ($opt_samba3_ndr_server or "$outputdir/srv_$basename.c");
763		my $header = $server; $header =~ s/\.c$/\.h/;
764		require Parse::Pidl::Samba3::ServerNDR;
765		my ($c_code,$h_code) = Parse::Pidl::Samba3::ServerNDR::Parse($ndr, $header, $h_filename);
766		FileSave($server, $c_code);
767		FileSave($header, $h_code);
768	}
769
770}
771
772if (scalar(@ARGV) == 0) {
773	print "pidl: no input files\n";
774	exit(1);
775}
776
777process_file($_) foreach (@ARGV);
778