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