r15260: Don't dereference NULL pointers to obtain array lengths - found by
[samba.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
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]] [--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] [--eth-parser[=OUTPUT]] [--diff] [--dump-idl] [--tdr-parser[=OUTPUT]] [--samba3-header[=OUTPUT]] [--samba3-parser=[OUTPUT]] [--samba3-server=[OUTPUT]] [--samba3-template[=OUTPUT]] [--samba3-client[=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 ethereal 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 ethereal 
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<--parse-idl-tree>
62
63 Read internal tree structure from input files rather 
64 then assuming they contain IDL.
65
66 =item I<--dump-idl>
67
68 Generate a new IDL file. File will be named OUTNAME.idl.
69
70 =item I<--header>
71
72 Generate a C header file for the specified interface. Filename defaults to OUTNAME.h.
73
74 =item I<--ndr-parser>
75
76 Generate a C file and C header containing NDR parsers. The filename for 
77 the parser defaults to ndr_OUTNAME.c. The header filename will be the 
78 parser filename with the extension changed from .c to .h.
79
80 =item I<--tdr-parser>
81
82 Generate a C file and C header containing TDR parsers. The filename for 
83 the parser defaults to tdr_OUTNAME.c. The header filename will be the 
84 parser filename with the extension changed from .c to .h.
85
86 =item I<--server>
87
88 Generate boilerplate for the RPC server that implements 
89 the interface. Filename defaults to ndr_OUTNAME_s.c.
90
91 =item I<--template>
92
93 Generate stubs for a RPC server that implements the interface. Output will 
94 be written to stdout.
95
96 =item I<--eth-parser>
97
98 Generate an Ethereal dissector (in C) and header file. The dissector filename
99 defaults to packet-dcerpc-OUTNAME.c while the header filename defaults to 
100 packet-dcerpc-OUTNAME.h.
101         
102 Pidl will read additional data from an ethereal conformance file if present. 
103 Such a file should have the same location as the IDL file but with the 
104 extension I<cnf> rather then I<idl>. See L<Parse::Pidl::Ethereal::Conformance>
105 for details on the format of this file.
106
107 =item I<--diff>
108
109 Parse an IDL file,  generate a new IDL file based on the internal data 
110 structures and see if there are any differences with the original IDL file. 
111 Useful for debugging pidl.
112
113 =item I<--dump-idl-tree>
114
115 Tell pidl to dump the internal tree representation of an IDL 
116 file the to disk. Useful for debugging pidl.
117
118 =item I<--dump-ndr-tree>
119
120 Tell pidl to dump the internal NDR information tree it generated 
121 from the IDL file to disk.  Useful for debugging pidl.
122
123 =item I<--samba3-header>
124
125 Generate Samba3-style RPC header file. Filename defaults to rpc_BASENAME.h.
126
127 =item I<--samba3-parser>
128
129 Generate parser file for Samba3, to be placed in rpc_parse/. Filename defaults 
130 to parse_BASENAME.c.
131
132 =item I<--samba3-server>
133
134 Generate server file for Samba3, to be placed in rpc_server/. Filename defaults 
135 to srv_BASENAME.c.
136
137 =item I<--samba3-template>
138
139 Generate template for server-side implementation in Samba3, to be placed in 
140 rpc_server/. Filename defaults to srv_BASENAME_nt.c
141
142 =item I<--samba3-client>
143
144 Generate client calls for Samba 3, to be placed in rpc_client/. Filename 
145 defaults to cli_BASENAME.c.
146
147 =back
148
149 =head1 IDL SYNTAX
150
151 IDL files are always preprocessed using the C preprocessor.
152
153 Pretty much everything in an interface (the interface itself, functions, 
154 parameters) can have attributes (or properties whatever name you give them). 
155 Attributes always prepend the element they apply to and are surrounded 
156 by square brackets ([]). Multiple attributes are separated by comma's; 
157 arguments to attributes are specified between parentheses. 
158
159 See the section COMPATIBILITY for the list of attributes that 
160 pidl supports.
161
162 C-style comments can be used.
163         
164 =head2 CONFORMANT ARRAYS
165
166 A conformant array is one with that ends in [*] or []. The strange
167 things about conformant arrays are that they can only appear as the last 
168 element of a structure (unless there is a pointer to the conformant array, 
169 of course) and the array size appears before the structure itself on the wire. 
170
171 So, in this example:
172
173         typedef struct {
174                 long abc;
175                 long count;     
176                 long foo;
177                 [size_is(count)] long s[*];
178         } Struct1;
179
180 it appears like this:
181
182         [size_is] [abc] [count] [foo] [s...]
183
184 the first [size_is] field is the allocation size of the array, and
185 occurs before the array elements and even before the structure
186 alignment.
187
188 Note that size_is() can refer to a constant, but that doesn't change
189 the wire representation. It does not make the array a fixed array.
190
191 midl.exe would write the above array as the following C header:
192
193    typedef struct {
194                 long abc;
195                 long count;     
196                 long foo;
197                 long s[1];
198         } Struct1;
199
200 pidl takes a different approach, and writes it like this:
201
202     typedef struct {
203                 long abc;
204                 long count;     
205                 long foo;
206                 long *s;
207         } Struct1;
208
209 =head2 VARYING ARRAYS
210
211 A varying array looks like this:
212
213         typedef struct {
214                 long abc;
215                 long count;     
216                 long foo;
217                 [size_is(count)] long *s;
218         } Struct1;
219
220 This will look like this on the wire:
221
222         [abc] [count] [foo] [PTR_s]    [count] [s...]
223
224 =head2 FIXED ARRAYS
225
226 A fixed array looks like this:
227
228     typedef struct {
229             long s[10];
230     } Struct1;
231
232 The NDR representation looks just like 10 separate long
233 declarations. The array size is not encoded on the wire.
234
235 pidl also supports "inline" arrays, which are not part of the IDL/NDR
236 standard. These are declared like this:
237
238     typedef struct {
239             uint32 foo;
240             uint32 count;
241             uint32 bar;
242             long s[count];
243     } Struct1;
244
245 This appears like this:
246
247         [foo] [count] [bar] [s...]
248
249 Fixed arrays are an extension added to support some of the strange
250 embedded structures in security descriptors and spoolss. 
251
252 This section is by no means complete. See the OpenGroup and MSDN 
253         documentation for additional information.
254
255 =head1 COMPATIBILITY WITH MIDL
256
257 =head2 Missing features in pidl
258
259 The following MIDL features are not (yet) implemented in pidl 
260 or are implemented with an incompatible interface:
261
262 =over
263
264 =item *
265
266 Asynchronous communication
267
268 =item * 
269
270 Typelibs (.tlb files)
271
272 =item *
273
274 Datagram support (ncadg_*)
275
276 =back
277
278 =head2 Supported attributes
279
280 in, out, ref, length_is, switch_is, size_is, uuid, case, default, string, 
281 unique, ptr, pointer_default, v1_enum, object, helpstring, range, local, 
282 call_as, endpoint, switch_type, progid, coclass, iid_is, represent_as, 
283 transmit_as.
284
285 =head2 PIDL Specific properties
286
287 =over 4
288
289 =item public
290
291 The [public] property on a structure or union is a pidl extension that
292 forces the generated pull/push functions to be non-static. This allows
293 you to declare types that can be used between modules. If you don't
294 specify [public] then pull/push functions for other than top-level
295 functions are declared static.
296                                 
297 =item noprint
298
299 The [noprint] property is a pidl extension that allows you to specify
300 that pidl should not generate a ndr_print_*() function for that
301 structure or union. This is used when you wish to define your own
302 print function that prints a structure in a nicer manner. A good
303 example is the use of [noprint] on dom_sid, which allows the
304 pretty-printing of SIDs.
305
306 =item value
307
308 The [value(expression)] property is a pidl extension that allows you
309 to specify the value of a field when it is put on the wire. This
310 allows fields that always have a well-known value to be automatically
311 filled in, thus making the API more programmer friendly. The
312 expression can be any C expression.
313
314 =item relative
315
316 The [relative] property can be supplied on a pointer. When it is used
317 it declares the pointer as a spoolss style "relative" pointer, which
318 means it appears on the wire as an offset within the current
319 encapsulating structure. This is not part of normal IDL/NDR, but it is
320 a very useful extension as it avoids the manual encoding of many
321 complex structures.
322
323 =item subcontext(length)
324
325 Specifies that a size of I<length>
326 bytes should be read, followed by a blob of that size, 
327 which will be parsed as NDR.
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
353
354 aggregatable, appobject, async_uuid, bindable, control, cpp_quote, 
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 import, include, 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 ethereal parser
367         $ ./pidl --eth-parser -- atsvc.idl
368         
369         # Generating a TDR parser and header
370         $ ./pidl --tdr-parser --header -- regf.idl
371
372         # Generating a Samba3 parser, client and server
373         $ ./pidl --samba3-parser --samba3-server --samba3-client -- 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.ethereal.com/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);
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 use Parse::Pidl::ODL;
409
410 #####################################################################
411 # save a data structure into a file
412 sub SaveStructure($$)
413 {
414         my($filename,$v) = @_;
415         FileSave($filename, Parse::Pidl::Util::MyDumper($v));
416 }
417
418 #####################################################################
419 # load a data structure from a file (as saved with SaveStructure)
420 sub LoadStructure($)
421 {
422         my $f = shift;
423         my $contents = FileLoad($f);
424         defined $contents || return undef;
425         return eval "$contents";
426 }
427
428 #####################################################################
429 # read a file into a string
430 sub FileLoad($)
431 {
432     my($filename) = shift;
433     local(*INPUTFILE);
434     open(INPUTFILE, $filename) || return undef;
435     my($saved_delim) = $/;
436     undef $/;
437     my($data) = <INPUTFILE>;
438     close(INPUTFILE);
439     $/ = $saved_delim;
440     return $data;
441 }
442
443 #####################################################################
444 # write a string into a file
445 sub FileSave($$)
446 {
447     my($filename) = shift;
448     my($v) = shift;
449     local(*FILE);
450     open(FILE, ">$filename") || die "can't open $filename";    
451     print FILE $v;
452     close(FILE);
453 }
454
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_uint_enums) = 0;
461 my($opt_diff) = 0;
462 my($opt_header);
463 my($opt_samba3_header);
464 my($opt_samba3_parser);
465 my($opt_samba3_server);
466 my($opt_samba3_template);
467 my($opt_samba3_client);
468 my($opt_template) = 0;
469 my($opt_client);
470 my($opt_server);
471 my($opt_ndr_parser);
472 my($opt_tdr_parser);
473 my($opt_eth_parser);
474 my($opt_swig);
475 my($opt_dcom_proxy);
476 my($opt_com_header);
477 my($opt_ejs);
478 my($opt_quiet) = 0;
479 my($opt_outputdir) = '.';
480 my($opt_verbose) = 0;
481 my($opt_warn_compat) = 0;
482
483 #########################################
484 # display help text
485 sub ShowHelp()
486 {
487 print "perl IDL parser and code generator
488 Copyright (C) Andrew Tridgell <tridge\@samba.org>
489 Copyright (C) Jelmer Vernooij <jelmer\@samba.org>
490
491 Usage: pidl [options] [--] <idlfile> [<idlfile>...]
492
493 Generic Options:
494  --help                  this help page
495  --outputdir=OUTDIR      put output in OUTDIR/ [.]
496  --warn-compat           warn about incompatibility with other compilers
497  --quiet                 be quiet
498  --verbose               be verbose
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
507 Samba 4 output:
508  --header[=OUTFILE]      create generic header file [BASENAME.h]
509  --uint-enums            don't use C enums, instead use uint* types
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  --swig[=OUTFILE]        create swig wrapper file [BASENAME.i]
515  --server[=OUTFILE]      create server boilerplate [ndr_BASENAME_s.c]
516  --template              print a template for a pipe
517  --dcom-proxy[=OUTFILE]  create DCOM proxy [ndr_BASENAME_p.c]
518  --com-header[=OUTFILE]  create header for COM [com_BASENAME.h]
519
520 Samba 3 output:
521  --samba3-header[=OUTF]  create Samba3-style header [rpc_BASENAME.h]
522  --samba3-parser[=OUTF]  create parser for Samba3 [parse_BASENAME.c]
523  --samba3-template[=OUTF]create template implementation [srv_BASENAME_nt.c]
524  --samba3-server[=OUTF]  create server side wrappers for Samba3 [srv_BASENAME.c]
525  --samba3-client[=OUTF]  create client calls for Samba3 [cli_BASENAME.c]
526
527 Ethereal parsers:
528  --eth-parser[=OUTFILE]  create ethereal parser and header
529 \n";
530     exit(0);
531 }
532
533 # main program
534 my $result = GetOptions (
535             'help|h|?' => \$opt_help, 
536             'outputdir=s' => \$opt_outputdir,
537             'dump-idl' => \$opt_dump_idl,
538                 'dump-idl-tree:s' => \$opt_dump_idl_tree,
539                 'parse-idl-tree' => \$opt_parse_idl_tree,
540                 'dump-ndr-tree:s' => \$opt_dump_ndr_tree,
541             'uint-enums' => \$opt_uint_enums,
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-parser:s' => \$opt_tdr_parser,
550             'template' => \$opt_template,
551             'ndr-parser:s' => \$opt_ndr_parser,
552             'client:s' => \$opt_client,
553             'eth-parser:s' => \$opt_eth_parser,
554             'ejs' => \$opt_ejs,
555             'diff' => \$opt_diff,
556             'swig:s' => \$opt_swig,
557             'dcom-proxy:s' => \$opt_dcom_proxy,
558             'com-header:s' => \$opt_com_header,
559             'quiet' => \$opt_quiet,
560                 'verbose' => \$opt_verbose,
561             'warn-compat' => \$opt_warn_compat
562             );
563
564 if (not $result) {
565         exit(1);
566 }
567
568 if ($opt_help) {
569     ShowHelp();
570     exit(0);
571 }
572
573 sub process_file($)
574 {
575         my $idl_file = shift;
576         my $outputdir = $opt_outputdir;
577         my $pidl;
578         my $ndr;
579
580         my $basename = basename($idl_file, ".idl");
581
582         unless ($opt_quiet) { print "Compiling $idl_file\n"; }
583
584         if ($opt_parse_idl_tree) {
585                 $pidl = LoadStructure($idl_file);
586                 defined $pidl || die "Failed to load $idl_file";
587         } else {
588                 require Parse::Pidl::IDL;
589
590                 $pidl = Parse::Pidl::IDL::parse_file($idl_file);
591                 defined @$pidl || die "Failed to parse $idl_file";
592                 require Parse::Pidl::Typelist;
593                 Parse::Pidl::Typelist::LoadIdl($pidl);
594         }
595         
596         if (defined($opt_dump_idl_tree)) {
597                 my($pidl_file) = ($opt_dump_idl_tree or "$outputdir/$basename.pidl");
598                 SaveStructure($pidl_file, $pidl) or die "Failed to save $pidl_file\n";
599         }
600
601         if ($opt_uint_enums) {
602                 Parse::Pidl::Util::setUseUintEnums(1);
603         }
604
605         if ($opt_dump_idl) {
606                 require Parse::Pidl::Dump;
607                 print Parse::Pidl::Dump($pidl);
608         }
609
610         if ($opt_diff) {
611                 my($tempfile) = "$outputdir/$basename.tmp";
612                 FileSave($tempfile, IdlDump::Dump($pidl));
613                 system("diff -wu $idl_file $tempfile");
614                 unlink($tempfile);
615         }
616
617
618         my $comh_filename = ($opt_com_header or "$outputdir/com_$basename.h");
619         if (defined($opt_com_header)) {
620                 require Parse::Pidl::Samba4::COM::Header;
621                 my $res = Parse::Pidl::Samba4::COM::Header::Parse($pidl,"$outputdir/ndr_$basename.h");
622                 if ($res) {
623                         FileSave($comh_filename, $res);
624                 }
625         }
626
627         if (defined($opt_dcom_proxy)) {
628                 require Parse::Pidl::Samba4::COM::Proxy;
629                 my $res = Parse::Pidl::Samba4::COM::Proxy::Parse($pidl,$comh_filename);
630                 if ($res) {
631                         my ($client) = ($opt_dcom_proxy or "$outputdir/$basename\_p.c");
632                         FileSave($client, $res);
633                 }
634         }
635
636         if ($opt_warn_compat) {
637                 require Parse::Pidl::Compat;
638                 Parse::Pidl::Compat::Check($pidl);
639         }
640
641         $pidl = Parse::Pidl::ODL::ODL2IDL($pidl);
642
643         if (defined($opt_eth_parser) or 
644             defined($opt_client) or defined($opt_server) or 
645             defined($opt_ndr_parser) or defined($opt_ejs) or 
646                 defined($opt_dump_ndr_tree) or defined($opt_samba3_header) or 
647             defined($opt_samba3_parser) or defined($opt_samba3_server) or 
648                 defined($opt_samba3_template) or defined($opt_samba3_client)) {
649                 require Parse::Pidl::NDR;
650                 $ndr = Parse::Pidl::NDR::Parse($pidl);
651         }
652
653         if (defined($opt_dump_ndr_tree)) {
654                 my($ndr_file) = ($opt_dump_ndr_tree or "$outputdir/$basename.ndr");
655                 SaveStructure($ndr_file, $ndr) or die "Failed to save $ndr_file\n";
656         }
657
658         my $gen_header = ($opt_header or "$outputdir/$basename.h");
659         if (defined($opt_header)) {
660                 require Parse::Pidl::Samba4::Header;
661                 FileSave($gen_header, Parse::Pidl::Samba4::Header::Parse($pidl));
662         }
663
664         my $h_filename = "$outputdir/ndr_$basename.h";
665         if (defined($opt_client)) {
666                 require Parse::Pidl::Samba4::NDR::Client;
667                 my ($c_client) = ($opt_client or "$outputdir/ndr_$basename\_c.c");
668                 my ($c_header) = $c_client;
669                 $c_header =~ s/\.c$/.h/;
670
671                 my ($srcd,$hdrd) = Parse::Pidl::Samba4::NDR::Client::Parse(
672                         $ndr,$gen_header,$h_filename,$c_header);
673
674                 FileSave($c_client, $srcd);
675                 FileSave($c_header, $hdrd);
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                 if (defined($opt_swig)) {
723                   require Parse::Pidl::Samba4::SWIG;
724                   my($filename) = ($opt_swig or "$outputdir/$basename.i");
725                   Parse::Pidl::Samba4::SWIG::RewriteHeader($pidl, $h_filename, $filename);
726                 }
727         }
728
729         if (defined($opt_eth_parser)) {
730           require Parse::Pidl::Ethereal::NDR;
731           my($eparser) = ($opt_eth_parser or "$outputdir/packet-dcerpc-$basename.c");
732           my $eheader = $eparser;
733           $eheader =~ s/\.c$/\.h/;
734           my $cnffile = $idl_file;
735           $cnffile =~ s/\.idl$/\.cnf/;
736
737           my ($dp, $dh) = Parse::Pidl::Ethereal::NDR::Parse($ndr, $idl_file, $eheader, $cnffile);
738           FileSave($eparser, $dp) if defined($dp);
739           FileSave($eheader, $dh) if defined($dh);
740         }
741
742         if (defined($opt_tdr_parser)) {
743                 my $tdr_parser = ($opt_tdr_parser or "$outputdir/tdr_$basename.c");
744                 my $tdr_header = $tdr_parser;
745                 $tdr_header =~ s/\.c$/\.h/;
746                 require Parse::Pidl::Samba4::TDR;
747                 my ($hdr,$prsr) = Parse::Pidl::Samba4::TDR::Parser($pidl, $tdr_header, $gen_header);
748                 FileSave($tdr_parser, $prsr);
749                 FileSave($tdr_header, $hdr);
750         }
751
752         if ($opt_template) {
753                 require Parse::Pidl::Samba4::Template;
754                 print Parse::Pidl::Samba4::Template::Parse($pidl);
755         }
756
757         if (defined($opt_samba3_header) or defined($opt_samba3_parser) or
758                 defined($opt_samba3_server) or defined($opt_samba3_client) or
759                 defined($opt_samba3_template)) {
760                 require Parse::Pidl::Samba3::Types;
761                 Parse::Pidl::Samba3::Types::LoadTypes($ndr);
762         }
763
764         if (defined($opt_samba3_header)) {
765                 my $header = ($opt_samba3_header or "$outputdir/rpc_$basename.h");
766                 require Parse::Pidl::Samba3::Header;
767                 FileSave($header, Parse::Pidl::Samba3::Header::Parse($ndr, $basename));
768         }
769
770         if (defined($opt_samba3_parser)) {
771                 my $header = ($opt_samba3_parser or "$outputdir/parse_$basename.c");
772                 require Parse::Pidl::Samba3::Parser;
773                 FileSave($header, Parse::Pidl::Samba3::Parser::Parse($ndr, $basename));
774         }
775
776         if (defined($opt_samba3_server)) {
777                 my $header = ($opt_samba3_server or "$outputdir/srv_$basename.c");
778                 require Parse::Pidl::Samba3::Server;
779                 FileSave($header, Parse::Pidl::Samba3::Server::Parse($ndr, $basename));
780         }
781
782         if (defined($opt_samba3_template)) {
783                 my $header = ($opt_samba3_template or "$outputdir/srv_$basename\_nt.c");
784                 require Parse::Pidl::Samba3::Template;
785                 FileSave($header, Parse::Pidl::Samba3::Template::Parse($ndr, $basename));
786         }
787
788         if (defined($opt_samba3_client)) {
789                 my $header = ($opt_samba3_client or "$outputdir/cli_$basename.c");
790                 require Parse::Pidl::Samba3::Client;
791                 FileSave($header, Parse::Pidl::Samba3::Client::Parse($ndr, $basename));
792         }
793
794 }
795
796 if (scalar(@ARGV) == 0) {
797         print "pidl: no input files\n";
798         exit(1);
799 }
800
801 process_file($_) foreach (@ARGV);