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
14 pidl - An IDL compiler written in Perl
20 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]...
24 pidl is an IDL compiler written in Perl that aims to be somewhat
25 compatible with the midl compiler. IDL is short for
26 "Interface Definition Language".
28 pidl can generate stubs for DCE/RPC server code, DCE/RPC
29 client code and ethereal dissectors for DCE/RPC traffic.
31 IDL compilers like pidl take a description
32 of an interface as their input and use it to generate C
33 (though support for other languages may be added later) code that
34 can use these interfaces, pretty print data sent
35 using these interfaces, or even generate ethereal
36 dissectors that can parse data sent over the
37 wire by these interfaces.
39 pidl takes IDL files in the same format as is used by midl,
40 converts 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
42 interface definitions in .idl format.
44 The goal of pidl is to implement a IDL compiler that can be used
45 while developing the RPC subsystem in Samba (for
46 both marshalling/unmarshalling and debugging purposes).
54 Show list of available options.
56 =item I<--outputdir OUTNAME>
58 Write output files to the specified directory. Defaults to the current
61 =item I<--parse-idl-tree>
63 Read internal tree structure from input files rather
64 then assuming they contain IDL.
68 Generate a new IDL file. File will be named OUTNAME.idl.
72 Generate a C header file for the specified interface. Filename defaults to OUTNAME.h.
76 Generate a C header file with the prototypes for the NDR parsers. Filename defaults to ndr_OUTNAME.h.
80 Generate a C file containing NDR parsers. Filename defaults to ndr_OUTNAME.c.
84 Generate boilerplate for the RPC server that implements
85 the interface. Filename defaults to ndr_OUTNAME_s.c.
89 Generate stubs for a RPC server that implements the interface. Output will
94 Generate an Ethereal dissector (in C) and header file. The dissector filename
95 defaults to packet-dcerpc-OUTNAME.c while the header filename defaults to
96 packet-dcerpc-OUTNAME.h.
98 Pidl will read additional data from an ethereal conformance file if present.
99 Such a file should have the same location as the IDL file but with the
100 extension I<cnf> rather then I<idl>. See L<Parse::Pidl::Ethereal::Conformance>
101 for details on the format of this file.
105 Parse an IDL file, generate a new IDL file based on the internal data
106 structures and see if there are any differences with the original IDL file.
107 Useful for debugging pidl.
109 =item I<--dump-idl-tree>
111 Tell pidl to dump the internal tree representation of an IDL
112 file the to disk. Useful for debugging pidl.
114 =item I<--dump-ndr-tree>
116 Tell pidl to dump the internal NDR information tree it generated
117 from the IDL file to disk. Useful for debugging pidl.
119 =item I<--samba3-header>
121 Generate Samba3-style RPC header file. Filename defaults to rpc_BASENAME.h.
123 =item I<--samba3-parser>
125 Generate parser file for Samba3, to be placed in rpc_parse/. Filename defaults
128 =item I<--samba3-server>
130 Generate server file for Samba3, to be placed in rpc_server/. Filename defaults
133 =item I<--samba3-template>
135 Generate template for server-side implementation in Samba3, to be placed in
136 rpc_server/. Filename defaults to srv_BASENAME_nt.c
138 =item I<--samba3-client>
140 Generate client calls for Samba 3, to be placed in rpc_client/. Filename
141 defaults to cli_BASENAME.c.
147 IDL files are always preprocessed using the C preprocessor.
149 Pretty much everything in an interface (the interface itself, functions,
150 parameters) can have attributes (or properties whatever name you give them).
151 Attributes always prepend the element they apply to and are surrounded
152 by square brackets ([]). Multiple attributes are separated by comma's;
153 arguments to attributes are specified between parentheses.
155 See the section COMPATIBILITY for the list of attributes that
158 C-style comments can be used.
160 =head2 CONFORMANT ARRAYS
162 A conformant array is one with that ends in [*] or []. The strange
163 things about conformant arrays are that they can only appear as the last
164 element of a structure (unless there is a pointer to the conformant array,
165 of course) and the array size appears before the structure itself on the wire.
173 [size_is(count)] long s[*];
176 it appears like this:
178 [size_is] [abc] [count] [foo] [s...]
180 the first [size_is] field is the allocation size of the array, and
181 occurs before the array elements and even before the structure
184 Note that size_is() can refer to a constant, but that doesn't change
185 the wire representation. It does not make the array a fixed array.
187 midl.exe would write the above array as the following C header:
196 pidl takes a different approach, and writes it like this:
205 =head2 VARYING ARRAYS
207 A varying array looks like this:
213 [size_is(count)] long *s;
216 This will look like this on the wire:
218 [abc] [count] [foo] [PTR_s] [count] [s...]
222 A fixed array looks like this:
228 The NDR representation looks just like 10 separate long
229 declarations. The array size is not encoded on the wire.
231 pidl also supports "inline" arrays, which are not part of the IDL/NDR
232 standard. These are declared like this:
241 This appears like this:
243 [foo] [count] [bar] [s...]
245 Fixed arrays are an extension added to support some of the strange
246 embedded structures in security descriptors and spoolss.
248 This section is by no means complete. See the OpenGroup and MSDN
249 documentation for additional information.
251 =head1 COMPATIBILITY WITH MIDL
253 =head2 Missing features in pidl
255 The following MIDL features are not (yet) implemented in pidl
256 or are implemented with an incompatible interface:
262 Asynchronous communication
266 Typelibs (.tlb files)
270 Datagram support (ncadg_*)
274 =head2 Supported attributes
276 in, out, ref, length_is, switch_is, size_is, uuid, case, default, string,
277 unique, ptr, pointer_default, v1_enum, object, helpstring, range, local,
278 call_as, endpoint, switch_type, progid, coclass, iid_is, represent_as.
280 =head2 PIDL Specific properties
286 The [public] property on a structure or union is a pidl extension that
287 forces the generated pull/push functions to be non-static. This allows
288 you to declare types that can be used between modules. If you don't
289 specify [public] then pull/push functions for other than top-level
290 functions are declared static.
294 The [noprint] property is a pidl extension that allows you to specify
295 that pidl should not generate a ndr_print_*() function for that
296 structure or union. This is used when you wish to define your own
297 print function that prints a structure in a nicer manner. A good
298 example is the use of [noprint] on dom_sid, which allows the
299 pretty-printing of SIDs.
303 The [value(expression)] property is a pidl extension that allows you
304 to specify the value of a field when it is put on the wire. This
305 allows fields that always have a well-known value to be automatically
306 filled in, thus making the API more programmer friendly. The
307 expression can be any C expression.
311 The [relative] property can be supplied on a pointer. When it is used
312 it declares the pointer as a spoolss style "relative" pointer, which
313 means it appears on the wire as an offset within the current
314 encapsulating structure. This is not part of normal IDL/NDR, but it is
315 a very useful extension as it avoids the manual encoding of many
318 =item subcontext(length)
320 Specifies that a size of I<length>
321 bytes should be read, followed by a blob of that size,
322 which will be parsed as NDR.
326 Specify boolean options, mostly used for
327 low-level NDR options. Several options
328 can be specified using the | character.
329 Note that flags are inherited by substructures!
333 The [nodiscriminant] property on a union means that the usual uint16
334 discriminent field at the start of the union on the wire is
335 omitted. This is not normally allowed in IDL/NDR, but is used for some
340 Specify that the array or string uses the specified
341 charset. If this attribute is specified, pidl will
342 take care of converting the character data from this format
343 to the host format. Commonly used values are UCS2, DOS and UTF8.
347 =head2 Unsupported MIDL properties
349 aggregatable, appobject, async_uuid, bindable, control, cpp_quote,
350 defaultbind, defaultcollelem, defaultvalue, defaultvtable, dispinterface,
351 displaybind, dual, entry, first_is, helpcontext, helpfile, helpstringcontext,
352 helpstringdll, hidden, idl_module, idl_quote, id, immediatebind, importlib,
353 import, include, includelib, last_is, lcid, licensed, max_is, module,
354 ms_union, no_injected_text, nonbrowsable, noncreatable, nonextensible, odl,
355 oleautomation, optional, pragma, propget, propputref, propput, readonly,
356 requestedit, restricted, retval, source, transmit_as, uidefault,
357 usesgetlasterror, vararg, vi_progid, wire_marshal.
361 # Generating an ethereal parser
362 $ ./pidl --eth-parser -- atsvc.idl
364 # Generating a TDR parser and header
365 $ ./pidl --tdr-parser --tdr-header --header -- regf.idl
367 # Generating a Samba3 parser, client and server
368 $ ./pidl --samba3-parser --samba3-server --samba3-client -- dfs.idl
370 # Generating a Samba4 NDR parser, client and server
371 $ ./pidl --ndr-parser --ndr-client --ndr-server -- samr.idl
375 L<http://msdn.microsoft.com/library/en-us/rpc/rpc/field_attributes.asp>,
376 L<http://wiki.ethereal.com/DCE/RPC>,
377 L<http://www.samba.org/>,
382 pidl is licensed under the GNU General Public License L<http://www.gnu.org/licenses/gpl.html>.
386 pidl was written by Andrew Tridgell, Stefan Metzmacher, Tim Potter and Jelmer
387 Vernooij. The current maintainer is Jelmer Vernooij.
389 This manpage was written by Jelmer Vernooij, partially based on the original
390 pidl README by Andrew Tridgell.
396 use FindBin qw($RealBin);
398 use lib "$RealBin/lib";
402 use Parse::Pidl::Util;
403 use Parse::Pidl::ODL;
405 #####################################################################
406 # save a data structure into a file
407 sub SaveStructure($$)
409 my($filename,$v) = @_;
410 FileSave($filename, Parse::Pidl::Util::MyDumper($v));
413 #####################################################################
414 # load a data structure from a file (as saved with SaveStructure)
418 my $contents = FileLoad($f);
419 defined $contents || return undef;
420 return eval "$contents";
423 #####################################################################
424 # read a file into a string
427 my($filename) = shift;
429 open(INPUTFILE, $filename) || return undef;
430 my($saved_delim) = $/;
432 my($data) = <INPUTFILE>;
438 #####################################################################
439 # write a string into a file
442 my($filename) = shift;
445 open(FILE, ">$filename") || die "can't open $filename";
451 my($opt_parse_idl_tree) = 0;
452 my($opt_dump_idl_tree);
453 my($opt_dump_ndr_tree);
454 my($opt_dump_idl) = 0;
455 my($opt_uint_enums) = 0;
459 my($opt_samba3_header);
460 my($opt_samba3_parser);
461 my($opt_samba3_server);
462 my($opt_samba3_template);
463 my($opt_samba3_client);
464 my($opt_template) = 0;
476 my($opt_outputdir) = '.';
477 my($opt_verbose) = 0;
478 my($opt_warn_compat) = 0;
480 #########################################
484 print "perl IDL parser and code generator
485 Copyright (C) Andrew Tridgell <tridge\@samba.org>
486 Copyright (C) Jelmer Vernooij <jelmer\@samba.org>
488 Usage: pidl [options] [--] <idlfile> [<idlfile>...]
491 --help this help page
492 --outputdir=OUTDIR put output in OUTDIR/ [.]
493 --warn-compat warn about incompatibility with other compilers
498 --dump-idl-tree[=FILE] dump internal representation to file [BASENAME.pidl]
499 --parse-idl-tree read internal representation instead of IDL
500 --dump-ndr-tree[=FILE] dump internal NDR data tree to file [BASENAME.ndr]
501 --dump-idl regenerate IDL file
502 --diff run diff on original IDL and dumped output
505 --header[=OUTFILE] create generic header file [BASENAME.h]
506 --uint-enums don't use C enums, instead use uint* types
507 --ndr-header[=OUTFILE] create a C NDR-specific header file [ndr_BASENAME.h]
508 --ndr-parser[=OUTFILE] create a C NDR parser [ndr_BASENAME.c]
509 --client[=OUTFILE] create a C NDR client [ndr_BASENAME_c.c]
510 --tdr-header[=OUTFILE] create a C TDR header file [tdr_BASENAME.h]
511 --tdr-parser[=OUTFILE] create a C TDR parser [tdr_BASENAME.c]
512 --ejs[=OUTFILE] create ejs wrapper file [BASENAME_ejs.c]
513 --swig[=OUTFILE] create swig wrapper file [BASENAME.i]
514 --server[=OUTFILE] create server boilerplate [ndr_BASENAME_s.c]
515 --template print a template for a pipe
516 --dcom-proxy[=OUTFILE] create DCOM proxy [ndr_BASENAME_p.c]
517 --com-header[=OUTFILE] create header for COM [com_BASENAME.h]
520 --samba3-header[=OUTF] create Samba3-style header [rpc_BASENAME.h]
521 --samba3-parser[=OUTF] create parser for Samba3 [parse_BASENAME.c]
522 --samba3-template[=OUTF]create template implementation [srv_BASENAME_nt.c]
523 --samba3-server[=OUTF] create server side wrappers for Samba3 [srv_BASENAME.c]
524 --samba3-client[=OUTF] create client calls for Samba3 [cli_BASENAME.c]
527 --eth-parser[=OUTFILE] create ethereal parser and header
533 my $result = GetOptions (
534 'help|h|?' => \$opt_help,
535 'outputdir=s' => \$opt_outputdir,
536 'dump-idl' => \$opt_dump_idl,
537 'dump-idl-tree:s' => \$opt_dump_idl_tree,
538 'parse-idl-tree' => \$opt_parse_idl_tree,
539 'dump-ndr-tree:s' => \$opt_dump_ndr_tree,
540 'uint-enums' => \$opt_uint_enums,
541 'ndr-header:s' => \$opt_ndr_header,
542 'samba3-header:s' => \$opt_samba3_header,
543 'samba3-parser:s' => \$opt_samba3_parser,
544 'samba3-server:s' => \$opt_samba3_server,
545 'samba3-template:s' => \$opt_samba3_template,
546 'samba3-client:s' => \$opt_samba3_client,
547 'header:s' => \$opt_header,
548 'server:s' => \$opt_server,
549 'tdr-header:s' => \$opt_tdr_header,
550 'tdr-parser:s' => \$opt_tdr_parser,
551 'template' => \$opt_template,
552 'ndr-parser:s' => \$opt_ndr_parser,
553 'client:s' => \$opt_client,
554 'eth-parser:s' => \$opt_eth_parser,
556 'diff' => \$opt_diff,
557 'swig:s' => \$opt_swig,
558 'dcom-proxy:s' => \$opt_dcom_proxy,
559 'com-header:s' => \$opt_com_header,
560 'quiet' => \$opt_quiet,
561 'verbose' => \$opt_verbose,
562 'warn-compat' => \$opt_warn_compat
576 my $idl_file = shift;
577 my $outputdir = $opt_outputdir;
581 my $basename = basename($idl_file, ".idl");
583 unless ($opt_quiet) { print "Compiling $idl_file\n"; }
585 if ($opt_parse_idl_tree) {
586 $pidl = LoadStructure($idl_file);
587 defined $pidl || die "Failed to load $idl_file";
589 require Parse::Pidl::IDL;
591 $pidl = Parse::Pidl::IDL::parse_file($idl_file);
592 defined @$pidl || die "Failed to parse $idl_file";
593 require Parse::Pidl::Typelist;
594 Parse::Pidl::Typelist::LoadIdl($pidl);
597 if (defined($opt_dump_idl_tree)) {
598 my($pidl_file) = ($opt_dump_idl_tree or "$outputdir/$basename.pidl");
599 SaveStructure($pidl_file, $pidl) or die "Failed to save $pidl_file\n";
602 if ($opt_uint_enums) {
603 Parse::Pidl::Util::setUseUintEnums(1);
607 require Parse::Pidl::Dump;
608 print Parse::Pidl::Dump($pidl);
612 my($tempfile) = "$outputdir/$basename.tmp";
613 FileSave($tempfile, IdlDump::Dump($pidl));
614 system("diff -wu $idl_file $tempfile");
618 if (defined($opt_com_header)) {
619 require Parse::Pidl::Samba::COM::Header;
620 my $res = Parse::Pidl::Samba::COM::Header::Parse($pidl);
622 my $comh_filename = ($opt_com_header or "$outputdir/com_$basename.h");
623 FileSave($comh_filename,
624 "#include \"librpc/gen_ndr/ndr_orpc.h\"\n" .
625 "#include \"$outputdir/ndr_$basename.h\"\n" .
630 if (defined($opt_dcom_proxy)) {
631 require Parse::Pidl::Samba::COM::Proxy;
632 my $res = Parse::Pidl::Samba::COM::Proxy::Parse($pidl);
634 my ($client) = ($opt_dcom_proxy or "$outputdir/$basename\_p.c");
636 "#include \"includes.h\"\n" .
637 "#include \"$outputdir/com_$basename.h\"\n" .
638 "#include \"lib/com/dcom/dcom.h\"\n" .$res);
642 if ($opt_warn_compat) {
643 require Parse::Pidl::Compat;
644 Parse::Pidl::Compat::Check($pidl);
647 $pidl = Parse::Pidl::ODL::ODL2IDL($pidl);
649 if (defined($opt_ndr_header) or defined($opt_eth_parser) or
650 defined($opt_client) or defined($opt_server) or
651 defined($opt_ndr_parser) or defined($opt_ejs) or
652 defined($opt_dump_ndr_tree) or defined($opt_samba3_header) or
653 defined($opt_samba3_header) or defined($opt_samba3_server) or
654 defined($opt_samba3_template) or defined($opt_samba3_client)) {
655 require Parse::Pidl::NDR;
656 Parse::Pidl::NDR::Validate($pidl);
657 $ndr = Parse::Pidl::NDR::Parse($pidl);
660 if (defined($opt_dump_ndr_tree)) {
661 my($ndr_file) = ($opt_dump_ndr_tree or "$outputdir/$basename.ndr");
662 SaveStructure($ndr_file, $ndr) or die "Failed to save $ndr_file\n";
665 if (defined($opt_header)) {
666 my $header = ($opt_header or "$outputdir/$basename.h");
667 require Parse::Pidl::Samba::Header;
668 FileSave($header, Parse::Pidl::Samba::Header::Parse($pidl));
671 if (defined($opt_ndr_header)) {
672 my $header = ($opt_ndr_header or "$outputdir/ndr_$basename.h");
673 require Parse::Pidl::Samba::NDR::Header;
674 FileSave($header, Parse::Pidl::Samba::NDR::Header::Parse($pidl, $basename));
675 if (defined($opt_swig)) {
676 require Parse::Pidl::Samba::SWIG;
677 my($filename) = ($opt_swig or "$outputdir/$basename.i");
678 Parse::Pidl::Samba::SWIG::RewriteHeader($pidl, $header, $filename);
682 my $h_filename = "$outputdir/ndr_$basename.h";
683 if (defined($opt_client)) {
684 require Parse::Pidl::Samba::NDR::Client;
685 my ($client) = ($opt_client or "$outputdir/ndr_$basename\_c.c");
687 FileSave($client, Parse::Pidl::Samba::NDR::Client::Parse($ndr,$h_filename));
690 if (defined($opt_ejs)) {
691 require Parse::Pidl::Samba::EJS;
692 require Parse::Pidl::Samba::EJSHeader;
693 FileSave("$outputdir/ndr_$basename\_ejs.c", Parse::Pidl::Samba::EJS::Parse($ndr, $h_filename));
695 FileSave("$outputdir/ndr_$basename\_ejs.h", Parse::Pidl::Samba::EJSHeader::Parse($ndr));
698 if (defined($opt_server)) {
699 require Parse::Pidl::Samba::NDR::Server;
702 foreach my $x (@{$pidl}) {
703 next if ($x->{TYPE} ne "INTERFACE");
705 if (Parse::Pidl::Util::has_property($x, "object")) {
706 require Parse::Pidl::Samba::COM::Stub;
707 $dcom .= Parse::Pidl::Samba::COM::Stub::ParseInterface($x);
711 FileSave(($opt_server or "$outputdir/ndr_$basename\_s.c"), Parse::Pidl::Samba::NDR::Server::Parse($ndr,$h_filename));
715 #include \"includes.h\"
716 #include \"$h_filename\"
717 #include \"rpc_server/dcerpc_server.h\"
718 #include \"rpc_server/common/common.h\"
722 FileSave("$outputdir/$basename\_d.c", $dcom);
726 if (defined($opt_ndr_parser)) {
727 my $parser = ($opt_ndr_parser or "$outputdir/ndr_$basename.c");
728 require Parse::Pidl::Samba::NDR::Parser;
729 FileSave($parser, Parse::Pidl::Samba::NDR::Parser::Parse($ndr, $parser));
732 if (defined($opt_eth_parser)) {
733 require Parse::Pidl::Ethereal::NDR;
734 my($eparser) = ($opt_eth_parser or "$outputdir/packet-dcerpc-$basename.c");
735 my $eheader = $eparser;
736 $eheader =~ s/\.c$/\.h/;
737 my $cnffile = $idl_file;
738 $cnffile =~ s/\.idl$/\.cnf/;
740 my ($dp, $dh) = Parse::Pidl::Ethereal::NDR::Parse($ndr, $idl_file, $eheader, $cnffile);
741 FileSave($eparser, $dp) if defined($dp);
742 FileSave($eheader, $dh) if defined($dh);
745 my $tdr_parser = ($opt_tdr_parser or "$outputdir/tdr_$basename.c");
746 my $tdr_header = ($opt_tdr_header or "$outputdir/tdr_$basename.h");
747 if (defined($opt_tdr_parser)) {
748 require Parse::Pidl::Samba::TDR;
749 FileSave($tdr_parser, Parse::Pidl::Samba::TDR::Parser($pidl, $tdr_header));
752 if (defined($opt_tdr_header)) {
753 require Parse::Pidl::Samba::TDR;
754 FileSave($tdr_header, Parse::Pidl::Samba::TDR::Header($pidl, $outputdir,$basename));
758 require Parse::Pidl::Samba::Template;
759 print Parse::Pidl::Samba::Template::Parse($pidl);
762 if (defined($opt_samba3_header) or defined($opt_samba3_parser) or
763 defined($opt_samba3_server) or defined($opt_samba3_client) or
764 defined($opt_samba3_template)) {
765 require Parse::Pidl::Samba3::Types;
766 Parse::Pidl::Samba3::Types::LoadTypes($ndr);
769 if (defined($opt_samba3_header)) {
770 my $header = ($opt_samba3_header or "$outputdir/rpc_$basename.h");
771 require Parse::Pidl::Samba3::Header;
772 FileSave($header, Parse::Pidl::Samba3::Header::Parse($ndr, $basename));
775 if (defined($opt_samba3_parser)) {
776 my $header = ($opt_samba3_parser or "$outputdir/parse_$basename.c");
777 require Parse::Pidl::Samba3::Parser;
778 FileSave($header, Parse::Pidl::Samba3::Parser::Parse($ndr, $basename));
781 if (defined($opt_samba3_server)) {
782 my $header = ($opt_samba3_server or "$outputdir/srv_$basename.c");
783 require Parse::Pidl::Samba3::Server;
784 FileSave($header, Parse::Pidl::Samba3::Server::Parse($ndr, $basename));
787 if (defined($opt_samba3_template)) {
788 my $header = ($opt_samba3_template or "$outputdir/srv_$basename\_nt.c");
789 require Parse::Pidl::Samba3::Template;
790 FileSave($header, Parse::Pidl::Samba3::Template::Parse($ndr, $basename));
793 if (defined($opt_samba3_client)) {
794 my $header = ($opt_samba3_client or "$outputdir/cli_$basename.c");
795 require Parse::Pidl::Samba3::Client;
796 FileSave($header, Parse::Pidl::Samba3::Client::Parse($ndr, $basename));
801 if (scalar(@ARGV) == 0) {
802 print "pidl: no input files\n";
806 process_file($_) foreach (@ARGV);