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