r20688: Use argv[0] equivalent of perl.
[samba.git] / source4 / 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
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]] [--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
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<--server>
92
93 Generate boilerplate for the RPC server that implements 
94 the interface. Filename defaults to ndr_OUTNAME_s.c.
95
96 =item I<--template>
97
98 Generate stubs for a RPC server that implements the interface. Output will 
99 be written to stdout.
100
101 =item I<--ws-parser>
102
103 Generate an Wireshark dissector (in C) and header file. The dissector filename
104 defaults to packet-dcerpc-OUTNAME.c while the header filename defaults to 
105 packet-dcerpc-OUTNAME.h.
106         
107 Pidl will read additional data from an Wireshark conformance file if present. 
108 Such a file should have the same location as the IDL file but with the 
109 extension I<cnf> rather than I<idl>. See L<Parse::Pidl::Wireshark::Conformance>
110 for details on the format of this file.
111
112 =item I<--diff>
113
114 Parse an IDL file,  generate a new IDL file based on the internal data 
115 structures and see if there are any differences with the original IDL file. 
116 Useful for debugging pidl.
117
118 =item I<--dump-idl-tree>
119
120 Tell pidl to dump the internal tree representation of an IDL 
121 file the to disk. Useful for debugging pidl.
122
123 =item I<--dump-ndr-tree>
124
125 Tell pidl to dump the internal NDR information tree it generated 
126 from the IDL file to disk.  Useful for debugging pidl.
127
128 =item I<--samba3-ndr-client>
129
130 Generate client calls for Samba3, to be placed in rpc_client/. Instead of 
131 calling out to the code in Samba3's rpc_parse/, this will call out to 
132 Samba4's NDR code instead.
133
134 =item I<--samba3-ndr-server>
135
136 Generate server calls for Samba3, to be placed in rpc_server/. Instead of 
137 calling out to the code in Samba3's rpc_parse/, this will call out to 
138 Samba4's NDR code instead.
139
140 =back
141
142 =head1 IDL SYNTAX
143
144 IDL files are always preprocessed using the C preprocessor.
145
146 Pretty much everything in an interface (the interface itself, functions, 
147 parameters) can have attributes (or properties whatever name you give them). 
148 Attributes always prepend the element they apply to and are surrounded 
149 by square brackets ([]). Multiple attributes are separated by comma's; 
150 arguments to attributes are specified between parentheses. 
151
152 See the section COMPATIBILITY for the list of attributes that 
153 pidl supports.
154
155 C-style comments can be used.
156         
157 =head2 CONFORMANT ARRAYS
158
159 A conformant array is one with that ends in [*] or []. The strange
160 things about conformant arrays are that they can only appear as the last 
161 element of a structure (unless there is a pointer to the conformant array, 
162 of course) and the array size appears before the structure itself on the wire. 
163
164 So, 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
173 it appears like this:
174
175         [size_is] [abc] [count] [foo] [s...]
176
177 the first [size_is] field is the allocation size of the array, and
178 occurs before the array elements and even before the structure
179 alignment.
180
181 Note that size_is() can refer to a constant, but that doesn't change
182 the wire representation. It does not make the array a fixed array.
183
184 midl.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
193 pidl 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
204 A 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
213 This will look like this on the wire:
214
215         [abc] [count] [foo] [PTR_s]    [count] [s...]
216
217 =head2 FIXED ARRAYS
218
219 A fixed array looks like this:
220
221     typedef struct {
222             long s[10];
223     } Struct1;
224
225 The NDR representation looks just like 10 separate long
226 declarations. The array size is not encoded on the wire.
227
228 pidl also supports "inline" arrays, which are not part of the IDL/NDR
229 standard. 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
238 This appears like this:
239
240         [foo] [count] [bar] [s...]
241
242 Fixed arrays are an extension added to support some of the strange
243 embedded structures in security descriptors and spoolss. 
244
245 This 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
252 The following MIDL features are not (yet) implemented in pidl 
253 or are implemented with an incompatible interface:
254
255 =over
256
257 =item *
258
259 Asynchronous communication
260
261 =item * 
262
263 Typelibs (.tlb files)
264
265 =item *
266
267 Datagram support (ncadg_*)
268
269 =back
270
271 =head2 Supported attributes and statements
272
273 in, out, ref, length_is, switch_is, size_is, uuid, case, default, string, 
274 unique, ptr, pointer_default, v1_enum, object, helpstring, range, local, 
275 call_as, endpoint, switch_type, progid, coclass, iid_is, represent_as, 
276 transmit_as, import, include.
277
278 =head2 PIDL Specific properties
279
280 =over 4
281
282 =item public
283
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.
289                                 
290 =item noprint
291
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.
298
299 =item value
300
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.
306
307 =item relative
308
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
314 complex structures.
315
316 =item subcontext(length)
317
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.
321
322 =item flag
323
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!
328
329 =item nodiscriminant
330
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
334 spoolss structures.
335
336 =item charset(name)
337
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.
342
343 =back
344
345 =head2 Unsupported MIDL properties or statements
346
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 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, uidefault, 
355 usesgetlasterror, 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
373 L<http://msdn.microsoft.com/library/en-us/rpc/rpc/field_attributes.asp>,
374 L<http://wiki.wireshark.org/DCE/RPC>, 
375 L<http://www.samba.org/>,
376 L<yapp(1)>
377
378 =head1 LICENSE
379
380 pidl is licensed under the GNU General Public License L<http://www.gnu.org/licenses/gpl.html>.
381
382 =head1 AUTHOR
383
384 pidl was written by Andrew Tridgell, Stefan Metzmacher, Tim Potter and Jelmer 
385 Vernooij. The current maintainer is Jelmer Vernooij.
386
387 This manpage was written by Jelmer Vernooij, partially based on the original 
388 pidl README by Andrew Tridgell. 
389         
390 =cut
391
392
393 use strict;
394 use FindBin qw($RealBin $Script);
395 use lib "$RealBin";
396 use lib "$RealBin/lib";
397 use Getopt::Long;
398 use File::Basename;
399 use Parse::Pidl;
400 use Parse::Pidl::Util;
401 use Parse::Pidl::ODL;
402
403 #####################################################################
404 # save a data structure into a file
405 sub 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)
413 sub 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
423 sub 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
438 sub 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
448 my(@opt_incdirs) = (); 
449 my($opt_help) = 0;
450 my($opt_parse_idl_tree) = 0;
451 my($opt_dump_idl_tree);
452 my($opt_dump_ndr_tree);
453 my($opt_dump_idl) = 0;
454 my($opt_uint_enums) = 0;
455 my($opt_diff) = 0;
456 my($opt_header);
457 my($opt_samba3_header);
458 my($opt_samba3_parser);
459 my($opt_samba3_server);
460 my($opt_samba3_ndr_client);
461 my($opt_samba3_ndr_server);
462 my($opt_template) = 0;
463 my($opt_client);
464 my($opt_server);
465 my($opt_ndr_parser);
466 my($opt_tdr_parser);
467 my($opt_ws_parser);
468 my($opt_swig);
469 my($opt_dcom_proxy);
470 my($opt_com_header);
471 my($opt_ejs);
472 my($opt_quiet) = 0;
473 my($opt_outputdir) = '.';
474 my($opt_verbose) = 0;
475 my($opt_warn_compat) = 0;
476
477 #########################################
478 # display help text
479 sub ShowHelp()
480 {
481 print "perl IDL parser and code generator
482 Copyright (C) Andrew Tridgell <tridge\@samba.org>
483 Copyright (C) Jelmer Vernooij <jelmer\@samba.org>
484
485 Usage: $Script [options] [--] <idlfile> [<idlfile>...]
486
487 Generic 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
495 Debugging:
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
502 Samba 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
515 Samba 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
521 Wireshark parsers:
522  --ws-parser[=OUTFILE]  create Wireshark parser and header
523 \n";
524     exit(0);
525 }
526
527 # main program
528 my $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
556 if (not $result) {
557         exit(1);
558 }
559
560 if ($opt_help) {
561     ShowHelp();
562     exit(0);
563 }
564
565 sub 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                 defined @$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
772 if (scalar(@ARGV) == 0) {
773         print "$Script: no input files\n";
774         exit(1);
775 }
776
777 process_file($_) foreach (@ARGV);