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
13 pidl - IDL Compiler written in Perl
18 pidl [--outputdir[=OUTNAME]] [--parse-idl-tree] [--dump-idl-tree] [--dump-ndr-tree] [--ndr-header[=OUTPUT]] [--header[=OUTPUT]] [--ejs[=OUTPUT]] [--swig[=OUTPUT]] [--uint-enums] [--ndr-parser[=OUTPUT]] [--client] [--server] [--dcom-proxy] [--com-header] [--warn-compat] [--quiet] [--verbose] [--template] [--eth-parser[=OUTPUT]] [--diff] [--dump-idl] [--tdr-header=[OUTPUT]] [--tdr-parser[=OUTPUT]] [--samba3-header[=OUTPUT]] [--samba3-parser=[OUTPUT]] [--samba3-server=[OUTPUT]] [--samba3-template[=OUTPUT]] [--samba3-client[=OUTPUT]] [<idlfile>.idl]...
22 pidl is an IDL compiler written in Perl that aims to be somewhat
23 compatible with the midl compiler. IDL is short for
24 "Interface Definition Language".
26 pidl can generate stubs for DCE/RPC server code, DCE/RPC
27 client code and ethereal dissectors for DCE/RPC traffic.
29 IDL compilers like pidl take a description
30 of an interface as their input and use it to generate C
31 (though support for other languages may be added later) code that
32 can use these interfaces, pretty print data sent
33 using these interfaces, or even generate ethereal
34 dissectors that can parse data sent over the
35 wire by these interfaces.
37 pidl takes IDL files in the same format as is used by midl,
38 converts it to a .pidl file (which contains pidl's internal representation of the interface) and can then generate whatever output you need.
39 .pidl files should be used for debugging purposes only. Write your
40 interface definitions in .idl format.
42 The goal of pidl is to implement a IDL compiler that can be used
43 while developing the RPC subsystem in Samba (for
44 both marshalling/unmarshalling and debugging purposes).
52 Show list of available options.
54 =item I<--outputdir OUTNAME>
56 Write output files to the specified directory. Defaults to the current
59 =item I<--parse-idl-tree>
61 Read internal tree structure from input files rather
62 then assuming they contain IDL.
66 Generate a new IDL file. File will be named OUTNAME.idl.
70 Generate a C header file for the specified interface. Filename defaults to OUTNAME.h.
74 Generate a C header file with the prototypes for the NDR parsers. Filename defaults to ndr_OUTNAME.h.
78 Generate a C file containing NDR parsers. Filename defaults to ndr_OUTNAME.c.
82 Generate boilerplate for the RPC server that implements
83 the interface. Filename defaults to ndr_OUTNAME_s.c.
87 Generate stubs for a RPC server that implements the interface. Output will
92 Generate an Ethereal dissector (in C) and header file. The dissector filename
93 defaults to packet-dcerpc-OUTNAME.c while the header filename defaults to
94 packet-dcerpc-OUTNAME.h.
96 Pidl will read additional data from an ethereal conformance file if present.
97 Such a file should have the same location as the IDL file but with the
98 extension I<cnf> rather then I<idl>. See below for details on the format of
103 Parse an IDL file, generate a new IDL file based on the internal data
104 structures and see if there are any differences with the original IDL file.
105 Useful for debugging pidl.
107 =item I<--dump-idl-tree>
109 Tell pidl to dump the internal tree representation of an IDL
110 file the to disk. Useful for debugging pidl.
112 =item I<--dump-ndr-tree>
114 Tell pidl to dump the internal NDR information tree it generated
115 from the IDL file to disk. Useful for debugging pidl.
117 =item I<--samba3-header>
119 Generate Samba3-style RPC header file. Filename defaults to rpc_BASENAME.h.
121 =item I<--samba3-parser>
123 Generate parser file for Samba3, to be placed in rpc_parse/. Filename defaults
126 =item I<--samba3-server>
128 Generate server file for Samba3, to be placed in rpc_server/. Filename defaults
131 =item I<--samba3-template>
133 Generate template for server-side implementation in Samba3, to be placed in
134 rpc_server/. Filename defaults to srv_BASENAME_nt.c
136 =item I<--samba3-client>
138 Generate client calls for Samba 3, to be placed in rpc_client/. Filename
139 defaults to cli_BASENAME.c.
145 IDL files are always preprocessed using the C preprocessor.
147 Pretty much everything in an interface (the interface itself, functions,
148 parameters) can have attributes (or properties whatever name you give them).
149 Attributes always prepend the element they apply to and are surrounded
150 by square brackets ([]). Multiple attributes are separated by comma's;
151 arguments to attributes are specified between parentheses.
153 See the section COMPATIBILITY for the list of attributes that
156 C-style comments can be used.
158 =head2 CONFORMANT ARRAYS
160 A conformant array is one with that ends in [*] or []. The strange
161 things about conformant arrays are that they can only appear as the last
162 element of a structure (unless there is a pointer to the conformant array,
163 of course) and the array size appears before the structure itself on the wire.
171 [size_is(count)] long s[*];
174 it appears like this:
176 [size_is] [abc] [count] [foo] [s...]
178 the first [size_is] field is the allocation size of the array, and
179 occurs before the array elements and even before the structure
182 Note that size_is() can refer to a constant, but that doesn't change
183 the wire representation. It does not make the array a fixed array.
185 midl.exe would write the above array as the following C header:
194 pidl takes a different approach, and writes it like this:
203 =head2 VARYING ARRAYS
205 A varying array looks like this:
211 [size_is(count)] long *s;
214 This will look like this on the wire:
216 [abc] [count] [foo] [PTR_s] [count] [s...]
220 A fixed array looks like this:
226 The NDR representation looks just like 10 separate long
227 declarations. The array size is not encoded on the wire.
229 pidl also supports "inline" arrays, which are not part of the IDL/NDR
230 standard. These are declared like this:
239 This appears like this:
241 [foo] [count] [bar] [s...]
243 Fixed arrays are an extension added to support some of the strange
244 embedded structures in security descriptors and spoolss.
246 This section is by no means complete. See the OpenGroup and MSDN
247 documentation for additional information.
249 =head1 COMPATIBILITY WITH MIDL
251 =head2 Missing features in pidl
253 The following MIDL features are not (yet) implemented in pidl
254 or are implemented with an incompatible interface:
260 Asynchronous communication
264 Typelibs (.tlb files)
268 Datagram support (ncadg_*)
272 =head2 Supported attributes
274 in, out, ref, length_is, switch_is, size_is, uuid, case, default, string,
275 unique, ptr, pointer_default, v1_enum, object, helpstring, range, local,
276 call_as, endpoint, switch_type, progid, coclass, iid_is.
278 =head2 PIDL Specific properties
284 The [public] property on a structure or union is a pidl extension that
285 forces the generated pull/push functions to be non-static. This allows
286 you to declare types that can be used between modules. If you don't
287 specify [public] then pull/push functions for other than top-level
288 functions are declared static.
292 The [noprint] property is a pidl extension that allows you to specify
293 that pidl should not generate a ndr_print_*() function for that
294 structure or union. This is used when you wish to define your own
295 print function that prints a structure in a nicer manner. A good
296 example is the use of [noprint] on dom_sid, which allows the
297 pretty-printing of SIDs.
301 The [value(expression)] property is a pidl extension that allows you
302 to specify the value of a field when it is put on the wire. This
303 allows fields that always have a well-known value to be automatically
304 filled in, thus making the API more programmer friendly. The
305 expression can be any C expression.
309 The [relative] property can be supplied on a pointer. When it is used
310 it declares the pointer as a spoolss style "relative" pointer, which
311 means it appears on the wire as an offset within the current
312 encapsulating structure. This is not part of normal IDL/NDR, but it is
313 a very useful extension as it avoids the manual encoding of many
316 =item subcontext(length)
318 Specifies that a size of I<length>
319 bytes should be read, followed by a blob of that size,
320 which will be parsed as NDR.
324 Specify boolean options, mostly used for
325 low-level NDR options. Several options
326 can be specified using the | character.
327 Note that flags are inherited by substructures!
331 The [nodiscriminant] property on a union means that the usual uint16
332 discriminent field at the start of the union on the wire is
333 omitted. This is not normally allowed in IDL/NDR, but is used for some
338 Specify that the array or string uses the specified
339 charset. If this attribute is specified, pidl will
340 take care of converting the character data from this format
341 to the host format. Commonly used values are UCS2, DOS and UTF8.
345 =head2 Unsupported MIDL properties
347 aggregatable, appobject, async_uuid, bindable, control, cpp_quote,
348 defaultbind, defaultcollelem, defaultvalue, defaultvtable, dispinterface,
349 displaybind, dual, entry, first_is, helpcontext, helpfile, helpstringcontext,
350 helpstringdll, hidden, idl_module, idl_quote, id, immediatebind, importlib,
351 import, include, includelib, last_is, lcid, licensed, max_is, module,
352 ms_union, no_injected_text, nonbrowsable, noncreatable, nonextensible, odl,
353 oleautomation, optional, pragma, propget, propputref, propput, readonly,
354 requestedit, restricted, retval, source, transmit_as, uidefault,
355 usesgetlasterror, vararg, vi_progid, wire_marshal.
357 =head1 ETHEREAL CONFORMANCE FILES
359 Pidl needs additional data for ethereal output. This data is read from
360 so-called conformance files. This section describes the format of these
363 Conformance files are simple text files with a single command on each line.
364 Empty lines and lines starting with a '#' character are ignored.
365 Arguments to commands are seperated by spaces.
367 The following commands are currently supported:
371 =item I<TYPE> name dissector ft_type base_type mask valsstring alignment
373 Register new data type with specified name, what dissector function to call
374 and what properties to give header fields for elements of this type.
378 Suppress emitting a dissect_type function for the specified type
380 =item I<PARAM_VALUE> type param
382 Set parameter to specify to dissector function for given type.
384 =item I<HF_FIELD> hf title filter ft_type base_type valsstring mask description
386 Generate a custom header field with specified properties.
388 =item I<HF_RENAME> old_hf_name new_hf_name
390 Force the use of new_hf_name when the parser generator was going to
393 This can be used in conjunction with HF_FIELD in order to make more then
394 one element use the same filter name.
396 =item I<STRIP_PREFIX> prefix
398 Remove the specified prefix from all function names (if present).
400 =item I<PROTOCOL> longname shortname filtername
402 Change the short-, long- and filter-name for the current interface in
405 =item I<FIELD_DESCRIPTION> field desc
407 Change description for the specified header field. `field' is the hf name of the field.
409 =item I<IMPORT> dissector code...
411 Code to insert when generating the specified dissector. @HF@ and
412 @PARAM@ will be substituted.
418 # Generating an ethereal parser
419 $ ./pidl --eth-parser -- atsvc.idl
421 # Generating a TDR parser
422 $ ./pidl --tdr-parser --tdr-header --header -- regf.idl
426 This man page is correct for version 4.0 of the Samba suite. L<http://www.samba.org/>.
430 L<http://msdn.microsoft.com/library/en-us/rpc/rpc/field_attributes.asp>,
431 L<http://wiki.ethereal.com/DCE/RPC>,
436 pidl is licensed under the GNU General Public License L<http://www.gnu.org/licenses/gpl.html>.
440 pidl was written by Andrew Tridgell, Stefan Metzmacher, Tim Potter and Jelmer
443 This manpage was written by Jelmer Vernooij, partially based on the original
444 pidl README by Andrew Tridgell.
450 use FindBin qw($RealBin);
452 use lib "$RealBin/lib";
456 use Parse::Pidl::Util;
457 use Parse::Pidl::ODL;
459 #####################################################################
460 # save a data structure into a file
461 sub SaveStructure($$)
463 my($filename,$v) = @_;
464 FileSave($filename, Parse::Pidl::Util::MyDumper($v));
467 #####################################################################
468 # load a data structure from a file (as saved with SaveStructure)
472 my $contents = FileLoad($f);
473 defined $contents || return undef;
474 return eval "$contents";
477 #####################################################################
478 # read a file into a string
481 my($filename) = shift;
483 open(INPUTFILE, $filename) || return undef;
484 my($saved_delim) = $/;
486 my($data) = <INPUTFILE>;
492 #####################################################################
493 # write a string into a file
496 my($filename) = shift;
499 open(FILE, ">$filename") || die "can't open $filename";
505 my($opt_parse_idl_tree) = 0;
506 my($opt_dump_idl_tree);
507 my($opt_dump_ndr_tree);
508 my($opt_dump_idl) = 0;
509 my($opt_uint_enums) = 0;
513 my($opt_samba3_header);
514 my($opt_samba3_parser);
515 my($opt_samba3_server);
516 my($opt_samba3_template);
517 my($opt_samba3_client);
518 my($opt_template) = 0;
530 my($opt_outputdir) = '.';
531 my($opt_verbose) = 0;
532 my($opt_warn_compat) = 0;
534 #########################################
538 print "perl IDL parser and code generator
539 Copyright (C) tridge\@samba.org
541 Usage: pidl [options] [--] <idlfile> [<idlfile>...]
544 --help this help page
545 --outputdir=OUTDIR put output in OUTDIR/ [.]
546 --warn-compat warn about incompatibility with other compilers
551 --dump-idl-tree[=FILE] dump internal representation to file [BASENAME.pidl]
552 --parse-idl-tree read internal representation instead of IDL
553 --dump-ndr-tree[=FILE] dump internal NDR data tree to file [BASENAME.ndr]
554 --dump-idl regenerate IDL file
555 --diff run diff on original IDL and dumped output
558 --header[=OUTFILE] create generic header file [BASENAME.h]
559 --uint-enums don't use C enums, instead use uint* types
560 --ndr-header[=OUTFILE] create a C NDR-specific header file [ndr_BASENAME.h]
561 --ndr-parser[=OUTFILE] create a C NDR parser [ndr_BASENAME.c]
562 --client[=OUTFILE] create a C NDR client [ndr_BASENAME_c.c]
563 --tdr-header[=OUTFILE] create a C TDR header file [tdr_BASENAME.h]
564 --tdr-parser[=OUTFILE] create a C TDR parser [tdr_BASENAME.c]
565 --ejs[=OUTFILE] create ejs wrapper file [BASENAME_ejs.c]
566 --swig[=OUTFILE] create swig wrapper file [BASENAME.i]
567 --server[=OUTFILE] create server boilerplate [ndr_BASENAME_s.c]
568 --template print a template for a pipe
569 --dcom-proxy[=OUTFILE] create DCOM proxy [ndr_BASENAME_p.c]
570 --com-header[=OUTFILE] create header for COM [com_BASENAME.h]
573 --samba3-header[=OUTF] create Samba3-style header [rpc_BASENAME.h]
574 --samba3-parser[=OUTF] create parser for Samba3 [parse_BASENAME.c]
575 --samba3-template[=OUTF]create template implementation [srv_BASENAME_nt.c]
576 --samba3-server[=OUTF] create server side wrappers for Samba3 [srv_BASENAME.c]
577 --samba3-client[=OUTF] create client calls for Samba3 [cli_BASENAME.c]
580 --eth-parser[=OUTFILE] create ethereal parser and header
586 my $result = GetOptions (
587 'help|h|?' => \$opt_help,
588 'outputdir=s' => \$opt_outputdir,
589 'dump-idl' => \$opt_dump_idl,
590 'dump-idl-tree:s' => \$opt_dump_idl_tree,
591 'parse-idl-tree' => \$opt_parse_idl_tree,
592 'dump-ndr-tree:s' => \$opt_dump_ndr_tree,
593 'uint-enums' => \$opt_uint_enums,
594 'ndr-header:s' => \$opt_ndr_header,
595 'samba3-header:s' => \$opt_samba3_header,
596 'samba3-parser:s' => \$opt_samba3_parser,
597 'samba3-server:s' => \$opt_samba3_server,
598 'samba3-template:s' => \$opt_samba3_template,
599 'samba3-client:s' => \$opt_samba3_client,
600 'header:s' => \$opt_header,
601 'server:s' => \$opt_server,
602 'tdr-header:s' => \$opt_tdr_header,
603 'tdr-parser:s' => \$opt_tdr_parser,
604 'template' => \$opt_template,
605 'ndr-parser:s' => \$opt_ndr_parser,
606 'client:s' => \$opt_client,
607 'eth-parser:s' => \$opt_eth_parser,
609 'diff' => \$opt_diff,
610 'swig:s' => \$opt_swig,
611 'dcom-proxy:s' => \$opt_dcom_proxy,
612 'com-header:s' => \$opt_com_header,
613 'quiet' => \$opt_quiet,
614 'verbose' => \$opt_verbose,
615 'warn-compat' => \$opt_warn_compat
629 my $idl_file = shift;
630 my $outputdir = $opt_outputdir;
634 my $basename = basename($idl_file, ".idl");
636 unless ($opt_quiet) { print "Compiling $idl_file\n"; }
638 if ($opt_parse_idl_tree) {
639 $pidl = LoadStructure($idl_file);
640 defined $pidl || die "Failed to load $idl_file";
642 require Parse::Pidl::IDL;
643 my $idl_parser = new Parse::Pidl::IDL;
645 $pidl = $idl_parser->parse_idl($idl_file);
646 defined @$pidl || die "Failed to parse $idl_file";
647 require Parse::Pidl::Typelist;
648 Parse::Pidl::Typelist::LoadIdl($pidl);
651 if (defined($opt_dump_idl_tree)) {
652 my($pidl_file) = ($opt_dump_idl_tree or "$outputdir/$basename.pidl");
653 SaveStructure($pidl_file, $pidl) or die "Failed to save $pidl_file\n";
656 if ($opt_uint_enums) {
657 Parse::Pidl::Util::setUseUintEnums(1);
661 require Parse::Pidl::Dump;
662 print Parse::Pidl::Dump($pidl);
666 my($tempfile) = "$outputdir/$basename.tmp";
667 FileSave($tempfile, IdlDump::Dump($pidl));
668 system("diff -wu $idl_file $tempfile");
672 if (defined($opt_com_header)) {
673 require Parse::Pidl::Samba::COM::Header;
674 my $res = Parse::Pidl::Samba::COM::Header::Parse($pidl);
676 my $comh_filename = ($opt_com_header or "$outputdir/com_$basename.h");
677 FileSave($comh_filename,
678 "#include \"librpc/gen_ndr/ndr_orpc.h\"\n" .
679 "#include \"$outputdir/ndr_$basename.h\"\n" .
684 if (defined($opt_dcom_proxy)) {
685 require Parse::Pidl::Samba::COM::Proxy;
686 my $res = Parse::Pidl::Samba::COM::Proxy::Parse($pidl);
688 my ($client) = ($opt_dcom_proxy or "$outputdir/$basename\_p.c");
690 "#include \"includes.h\"\n" .
691 "#include \"$outputdir/com_$basename.h\"\n" .
692 "#include \"lib/com/dcom/dcom.h\"\n" .$res);
696 if ($opt_warn_compat) {
697 require Parse::Pidl::Compat;
698 Parse::Pidl::Compat::Check($pidl);
701 $pidl = Parse::Pidl::ODL::ODL2IDL($pidl);
703 if (defined($opt_ndr_header) or defined($opt_eth_parser) or
704 defined($opt_client) or defined($opt_server) or
705 defined($opt_ndr_parser) or defined($opt_ejs) or
706 defined($opt_dump_ndr_tree) or defined($opt_samba3_header) or
707 defined($opt_samba3_header) or defined($opt_samba3_server) or
708 defined($opt_samba3_template) or defined($opt_samba3_client)) {
709 require Parse::Pidl::NDR;
710 Parse::Pidl::NDR::Validate($pidl);
711 $ndr = Parse::Pidl::NDR::Parse($pidl);
714 if (defined($opt_dump_ndr_tree)) {
715 my($ndr_file) = ($opt_dump_ndr_tree or "$outputdir/$basename.ndr");
716 SaveStructure($ndr_file, $ndr) or die "Failed to save $ndr_file\n";
719 if (defined($opt_header)) {
720 my $header = ($opt_header or "$outputdir/$basename.h");
721 require Parse::Pidl::Samba::Header;
722 FileSave($header, Parse::Pidl::Samba::Header::Parse($pidl));
725 if (defined($opt_ndr_header)) {
726 my $header = ($opt_ndr_header or "$outputdir/ndr_$basename.h");
727 require Parse::Pidl::Samba::NDR::Header;
728 FileSave($header, Parse::Pidl::Samba::NDR::Header::Parse($pidl, $basename));
729 if (defined($opt_swig)) {
730 require Parse::Pidl::Samba::SWIG;
731 my($filename) = ($opt_swig or "$outputdir/$basename.i");
732 Parse::Pidl::Samba::SWIG::RewriteHeader($pidl, $header, $filename);
736 my $h_filename = "$outputdir/ndr_$basename.h";
737 if (defined($opt_client)) {
738 require Parse::Pidl::Samba::NDR::Client;
739 my ($client) = ($opt_client or "$outputdir/ndr_$basename\_c.c");
741 FileSave($client, Parse::Pidl::Samba::NDR::Client::Parse($ndr,$h_filename));
744 if (defined($opt_ejs)) {
745 require Parse::Pidl::Samba::EJS;
746 require Parse::Pidl::Samba::EJSHeader;
747 FileSave("$outputdir/ndr_$basename\_ejs.c", Parse::Pidl::Samba::EJS::Parse($ndr, $h_filename));
749 FileSave("$outputdir/ndr_$basename\_ejs.h", Parse::Pidl::Samba::EJSHeader::Parse($ndr));
752 if (defined($opt_server)) {
753 require Parse::Pidl::Samba::NDR::Server;
756 foreach my $x (@{$pidl}) {
757 next if ($x->{TYPE} ne "INTERFACE");
759 if (Parse::Pidl::Util::has_property($x, "object")) {
760 require Parse::Pidl::Samba::COM::Stub;
761 $dcom .= Parse::Pidl::Samba::COM::Stub::ParseInterface($x);
765 FileSave(($opt_server or "$outputdir/ndr_$basename\_s.c"), Parse::Pidl::Samba::NDR::Server::Parse($ndr,$h_filename));
769 #include \"includes.h\"
770 #include \"$h_filename\"
771 #include \"rpc_server/dcerpc_server.h\"
772 #include \"rpc_server/common/common.h\"
776 FileSave("$outputdir/$basename\_d.c", $dcom);
780 if (defined($opt_ndr_parser)) {
781 my $parser = ($opt_ndr_parser or "$outputdir/ndr_$basename.c");
782 require Parse::Pidl::Samba::NDR::Parser;
783 FileSave($parser, Parse::Pidl::Samba::NDR::Parser::Parse($ndr, $parser));
786 if (defined($opt_eth_parser)) {
787 require Parse::Pidl::Ethereal::NDR;
788 my($eparser) = ($opt_eth_parser or "$outputdir/packet-dcerpc-$basename.c");
789 my $eheader = $eparser;
790 $eheader =~ s/\.c$/\.h/;
791 my $cnffile = $idl_file;
792 $cnffile =~ s/\.idl$/\.cnf/;
794 my ($dp, $dh) = Parse::Pidl::Ethereal::NDR::Parse($ndr, $idl_file, $eheader, $cnffile);
795 FileSave($eparser, $dp) if defined($dp);
796 FileSave($eheader, $dh) if defined($dh);
799 my $tdr_parser = ($opt_tdr_parser or "$outputdir/tdr_$basename.c");
800 my $tdr_header = ($opt_tdr_header or "$outputdir/tdr_$basename.h");
801 if (defined($opt_tdr_parser)) {
802 require Parse::Pidl::Samba::TDR;
803 FileSave($tdr_parser, Parse::Pidl::Samba::TDR::Parser($pidl, $tdr_header));
806 if (defined($opt_tdr_header)) {
807 require Parse::Pidl::Samba::TDR;
808 FileSave($tdr_header, Parse::Pidl::Samba::TDR::Header($pidl, $outputdir,$basename));
812 require Parse::Pidl::Samba::Template;
813 print Parse::Pidl::Samba::Template::Parse($pidl);
816 if (defined($opt_samba3_header)) {
817 my $header = ($opt_samba3_header or "$outputdir/rpc_$basename.h");
818 require Parse::Pidl::Samba3::Header;
819 FileSave($header, Parse::Pidl::Samba3::Header::Parse($ndr, $basename));
822 if (defined($opt_samba3_parser)) {
823 my $header = ($opt_samba3_parser or "$outputdir/parse_$basename.c");
824 require Parse::Pidl::Samba3::Parser;
825 FileSave($header, Parse::Pidl::Samba3::Parser::Parse($ndr, $basename));
828 if (defined($opt_samba3_server)) {
829 my $header = ($opt_samba3_server or "$outputdir/srv_$basename.c");
830 require Parse::Pidl::Samba3::Server;
831 FileSave($header, Parse::Pidl::Samba3::Server::Parse($ndr, $basename));
834 if (defined($opt_samba3_template)) {
835 my $header = ($opt_samba3_template or "$outputdir/srv_$basename\_nt.c");
836 require Parse::Pidl::Samba3::Template;
837 FileSave($header, Parse::Pidl::Samba3::Template::Parse($ndr, $basename));
840 if (defined($opt_samba3_client)) {
841 my $header = ($opt_samba3_client or "$outputdir/cli_$basename.c");
842 require Parse::Pidl::Samba3::Client;
843 FileSave($header, Parse::Pidl::Samba3::Client::Parse($ndr, $basename));
848 if (scalar(@ARGV) == 0) {
849 print "pidl: no input files\n";
853 process_file($_) foreach (@ARGV);