r15260: Don't dereference NULL pointers to obtain array lengths - found by
[samba.git] / source / pidl / pidl
index 5d248ce7a3c334580897c9864033321c4669be68..314ab7c60b190f92cddc5aa38af82240d642abd9 100755 (executable)
@@ -7,6 +7,396 @@
 # Copyright jelmer@samba.org 2005
 # released under the GNU GPL
 
+=pod
+
+=head1 NAME
+
+pidl - An IDL compiler written in Perl
+
+=head1 SYNOPSIS
+
+pidl --help
+
+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]...
+
+=head1 DESCRIPTION
+
+pidl is an IDL compiler written in Perl that aims to be somewhat 
+compatible with the midl compiler. IDL is short for 
+"Interface Definition Language".
+
+pidl can generate stubs for DCE/RPC server code, DCE/RPC 
+client code and ethereal dissectors for DCE/RPC traffic.
+
+IDL compilers like pidl take a description 
+of an interface as their input and use it to generate C 
+(though support for other languages may be added later) code that 
+can use these interfaces, pretty print data sent 
+using these interfaces, or even generate ethereal 
+dissectors that can parse data sent over the 
+wire by these interfaces. 
+
+pidl takes IDL files in the same format as is used by midl, 
+converts it to a .pidl file (which contains pidl's internal representation of the interface) and can then generate whatever output you need.
+.pidl files should be used for debugging purposes only. Write your 
+interface definitions in .idl format.
+
+The goal of pidl is to implement a IDL compiler that can be used 
+while developing the RPC subsystem in Samba (for 
+both marshalling/unmarshalling and debugging purposes).
+
+=head1 OPTIONS
+
+=over 4
+
+=item I<--help>
+
+Show list of available options.
+               
+=item I<--outputdir OUTNAME>
+
+Write output files to the specified directory.  Defaults to the current 
+directory.
+               
+=item I<--parse-idl-tree>
+
+Read internal tree structure from input files rather 
+then assuming they contain IDL.
+
+=item I<--dump-idl>
+
+Generate a new IDL file. File will be named OUTNAME.idl.
+
+=item I<--header>
+
+Generate a C header file for the specified interface. Filename defaults to OUTNAME.h.
+
+=item I<--ndr-parser>
+
+Generate a C file and C header containing NDR parsers. The filename for 
+the parser defaults to ndr_OUTNAME.c. The header filename will be the 
+parser filename with the extension changed from .c to .h.
+
+=item I<--tdr-parser>
+
+Generate a C file and C header containing TDR parsers. The filename for 
+the parser defaults to tdr_OUTNAME.c. The header filename will be the 
+parser filename with the extension changed from .c to .h.
+
+=item I<--server>
+
+Generate boilerplate for the RPC server that implements 
+the interface. Filename defaults to ndr_OUTNAME_s.c.
+
+=item I<--template>
+
+Generate stubs for a RPC server that implements the interface. Output will 
+be written to stdout.
+
+=item I<--eth-parser>
+
+Generate an Ethereal dissector (in C) and header file. The dissector filename
+defaults to packet-dcerpc-OUTNAME.c while the header filename defaults to 
+packet-dcerpc-OUTNAME.h.
+       
+Pidl will read additional data from an ethereal conformance file if present. 
+Such a file should have the same location as the IDL file but with the 
+extension I<cnf> rather then I<idl>. See L<Parse::Pidl::Ethereal::Conformance>
+for details on the format of this file.
+
+=item I<--diff>
+
+Parse an IDL file,  generate a new IDL file based on the internal data 
+structures and see if there are any differences with the original IDL file. 
+Useful for debugging pidl.
+
+=item I<--dump-idl-tree>
+
+Tell pidl to dump the internal tree representation of an IDL 
+file the to disk. Useful for debugging pidl.
+
+=item I<--dump-ndr-tree>
+
+Tell pidl to dump the internal NDR information tree it generated 
+from the IDL file to disk.  Useful for debugging pidl.
+
+=item I<--samba3-header>
+
+Generate Samba3-style RPC header file. Filename defaults to rpc_BASENAME.h.
+
+=item I<--samba3-parser>
+
+Generate parser file for Samba3, to be placed in rpc_parse/. Filename defaults 
+to parse_BASENAME.c.
+
+=item I<--samba3-server>
+
+Generate server file for Samba3, to be placed in rpc_server/. Filename defaults 
+to srv_BASENAME.c.
+
+=item I<--samba3-template>
+
+Generate template for server-side implementation in Samba3, to be placed in 
+rpc_server/. Filename defaults to srv_BASENAME_nt.c
+
+=item I<--samba3-client>
+
+Generate client calls for Samba 3, to be placed in rpc_client/. Filename 
+defaults to cli_BASENAME.c.
+
+=back
+
+=head1 IDL SYNTAX
+
+IDL files are always preprocessed using the C preprocessor.
+
+Pretty much everything in an interface (the interface itself, functions, 
+parameters) can have attributes (or properties whatever name you give them). 
+Attributes always prepend the element they apply to and are surrounded 
+by square brackets ([]). Multiple attributes are separated by comma's; 
+arguments to attributes are specified between parentheses. 
+
+See the section COMPATIBILITY for the list of attributes that 
+pidl supports.
+
+C-style comments can be used.
+       
+=head2 CONFORMANT ARRAYS
+
+A conformant array is one with that ends in [*] or []. The strange
+things about conformant arrays are that they can only appear as the last 
+element of a structure (unless there is a pointer to the conformant array, 
+of course) and the array size appears before the structure itself on the wire. 
+
+So, in this example:
+
+       typedef struct {
+               long abc;
+               long count;     
+               long foo;
+               [size_is(count)] long s[*];
+       } Struct1;
+
+it appears like this:
+
+       [size_is] [abc] [count] [foo] [s...]
+
+the first [size_is] field is the allocation size of the array, and
+occurs before the array elements and even before the structure
+alignment.
+
+Note that size_is() can refer to a constant, but that doesn't change
+the wire representation. It does not make the array a fixed array.
+
+midl.exe would write the above array as the following C header:
+
+   typedef struct {
+               long abc;
+               long count;     
+               long foo;
+               long s[1];
+       } Struct1;
+
+pidl takes a different approach, and writes it like this:
+
+    typedef struct {
+               long abc;
+               long count;     
+               long foo;
+               long *s;
+       } Struct1;
+
+=head2 VARYING ARRAYS
+
+A varying array looks like this:
+
+       typedef struct {
+               long abc;
+               long count;     
+               long foo;
+               [size_is(count)] long *s;
+       } Struct1;
+
+This will look like this on the wire:
+
+       [abc] [count] [foo] [PTR_s]    [count] [s...]
+
+=head2 FIXED ARRAYS
+
+A fixed array looks like this:
+
+    typedef struct {
+           long s[10];
+    } Struct1;
+
+The NDR representation looks just like 10 separate long
+declarations. The array size is not encoded on the wire.
+
+pidl also supports "inline" arrays, which are not part of the IDL/NDR
+standard. These are declared like this:
+
+    typedef struct {
+           uint32 foo;
+           uint32 count;
+           uint32 bar;
+           long s[count];
+    } Struct1;
+
+This appears like this:
+
+       [foo] [count] [bar] [s...]
+
+Fixed arrays are an extension added to support some of the strange
+embedded structures in security descriptors and spoolss. 
+
+This section is by no means complete. See the OpenGroup and MSDN 
+       documentation for additional information.
+
+=head1 COMPATIBILITY WITH MIDL
+
+=head2 Missing features in pidl
+
+The following MIDL features are not (yet) implemented in pidl 
+or are implemented with an incompatible interface:
+
+=over
+
+=item *
+
+Asynchronous communication
+
+=item * 
+
+Typelibs (.tlb files)
+
+=item *
+
+Datagram support (ncadg_*)
+
+=back
+
+=head2 Supported attributes
+
+in, out, ref, length_is, switch_is, size_is, uuid, case, default, string, 
+unique, ptr, pointer_default, v1_enum, object, helpstring, range, local, 
+call_as, endpoint, switch_type, progid, coclass, iid_is, represent_as, 
+transmit_as.
+
+=head2 PIDL Specific properties
+
+=over 4
+
+=item public
+
+The [public] property on a structure or union is a pidl extension that
+forces the generated pull/push functions to be non-static. This allows
+you to declare types that can be used between modules. If you don't
+specify [public] then pull/push functions for other than top-level
+functions are declared static.
+                               
+=item noprint
+
+The [noprint] property is a pidl extension that allows you to specify
+that pidl should not generate a ndr_print_*() function for that
+structure or union. This is used when you wish to define your own
+print function that prints a structure in a nicer manner. A good
+example is the use of [noprint] on dom_sid, which allows the
+pretty-printing of SIDs.
+
+=item value
+
+The [value(expression)] property is a pidl extension that allows you
+to specify the value of a field when it is put on the wire. This
+allows fields that always have a well-known value to be automatically
+filled in, thus making the API more programmer friendly. The
+expression can be any C expression.
+
+=item relative
+
+The [relative] property can be supplied on a pointer. When it is used
+it declares the pointer as a spoolss style "relative" pointer, which
+means it appears on the wire as an offset within the current
+encapsulating structure. This is not part of normal IDL/NDR, but it is
+a very useful extension as it avoids the manual encoding of many
+complex structures.
+
+=item subcontext(length)
+
+Specifies that a size of I<length>
+bytes should be read, followed by a blob of that size, 
+which will be parsed as NDR.
+
+=item flag
+
+Specify boolean options, mostly used for 
+low-level NDR options. Several options 
+can be specified using the | character.
+Note that flags are inherited by substructures!
+
+=item nodiscriminant
+
+The [nodiscriminant] property on a union means that the usual uint16
+discriminent field at the start of the union on the wire is
+omitted. This is not normally allowed in IDL/NDR, but is used for some
+spoolss structures.
+
+=item charset(name)
+
+Specify that the array or string uses the specified 
+charset. If this attribute is specified, pidl will 
+take care of converting the character data from this format 
+to the host format. Commonly used values are UCS2, DOS and UTF8.
+
+=back
+
+=head2 Unsupported MIDL properties
+
+aggregatable, appobject, async_uuid, bindable, control, cpp_quote, 
+defaultbind, defaultcollelem, defaultvalue, defaultvtable, dispinterface, 
+displaybind, dual, entry, first_is, helpcontext, helpfile, helpstringcontext, 
+helpstringdll, hidden, idl_module, idl_quote, id, immediatebind, importlib, 
+import, include, includelib, last_is, lcid, licensed, max_is, module, 
+ms_union, no_injected_text, nonbrowsable, noncreatable, nonextensible, odl, 
+oleautomation, optional, pragma, propget, propputref, propput, readonly, 
+requestedit, restricted, retval, source, uidefault, 
+usesgetlasterror, vararg, vi_progid, wire_marshal. 
+
+=head1 EXAMPLES
+
+       # Generating an ethereal parser
+       $ ./pidl --eth-parser -- atsvc.idl
+       
+       # Generating a TDR parser and header
+       $ ./pidl --tdr-parser --header -- regf.idl
+
+       # Generating a Samba3 parser, client and server
+       $ ./pidl --samba3-parser --samba3-server --samba3-client -- dfs.idl
+
+       # Generating a Samba4 NDR parser, client and server
+       $ ./pidl --ndr-parser --ndr-client --ndr-server -- samr.idl
+
+=head1 SEE ALSO
+
+L<http://msdn.microsoft.com/library/en-us/rpc/rpc/field_attributes.asp>,
+L<http://wiki.ethereal.com/DCE/RPC>, 
+L<http://www.samba.org/>,
+L<yapp(1)>
+
+=head1 LICENSE
+
+pidl is licensed under the GNU General Public License L<http://www.gnu.org/licenses/gpl.html>.
+
+=head1 AUTHOR
+
+pidl was written by Andrew Tridgell, Stefan Metzmacher, Tim Potter and Jelmer 
+Vernooij. The current maintainer is Jelmer Vernooij.
+
+This manpage was written by Jelmer Vernooij, partially based on the original 
+pidl README by Andrew Tridgell. 
+       
+=cut
+
+
 use strict;
 use FindBin qw($RealBin);
 use lib "$RealBin";
@@ -70,12 +460,15 @@ my($opt_dump_idl) = 0;
 my($opt_uint_enums) = 0;
 my($opt_diff) = 0;
 my($opt_header);
-my($opt_ndr_header);
+my($opt_samba3_header);
+my($opt_samba3_parser);
+my($opt_samba3_server);
+my($opt_samba3_template);
+my($opt_samba3_client);
 my($opt_template) = 0;
 my($opt_client);
 my($opt_server);
 my($opt_ndr_parser);
-my($opt_tdr_header);
 my($opt_tdr_parser);
 my($opt_eth_parser);
 my($opt_swig);
@@ -92,7 +485,8 @@ my($opt_warn_compat) = 0;
 sub ShowHelp()
 {
 print "perl IDL parser and code generator
-Copyright (C) tridge\@samba.org
+Copyright (C) Andrew Tridgell <tridge\@samba.org>
+Copyright (C) Jelmer Vernooij <jelmer\@samba.org>
 
 Usage: pidl [options] [--] <idlfile> [<idlfile>...]
 
@@ -113,10 +507,8 @@ Debugging:
 Samba 4 output:
  --header[=OUTFILE]      create generic header file [BASENAME.h]
  --uint-enums            don't use C enums, instead use uint* types
- --ndr-header[=OUTFILE]  create a C NDR-specific header file [ndr_BASENAME.h]
  --ndr-parser[=OUTFILE]  create a C NDR parser [ndr_BASENAME.c]
  --client[=OUTFILE]      create a C NDR client [ndr_BASENAME_c.c]
- --tdr-header[=OUTFILE]  create a C TDR header file [tdr_BASENAME.h]
  --tdr-parser[=OUTFILE]  create a C TDR parser [tdr_BASENAME.c]
  --ejs[=OUTFILE]         create ejs wrapper file [BASENAME_ejs.c]
  --swig[=OUTFILE]        create swig wrapper file [BASENAME.i]
@@ -125,6 +517,13 @@ Samba 4 output:
  --dcom-proxy[=OUTFILE]  create DCOM proxy [ndr_BASENAME_p.c]
  --com-header[=OUTFILE]  create header for COM [com_BASENAME.h]
 
+Samba 3 output:
+ --samba3-header[=OUTF]  create Samba3-style header [rpc_BASENAME.h]
+ --samba3-parser[=OUTF]  create parser for Samba3 [parse_BASENAME.c]
+ --samba3-template[=OUTF]create template implementation [srv_BASENAME_nt.c]
+ --samba3-server[=OUTF]  create server side wrappers for Samba3 [srv_BASENAME.c]
+ --samba3-client[=OUTF]  create client calls for Samba3 [cli_BASENAME.c]
+
 Ethereal parsers:
  --eth-parser[=OUTFILE]  create ethereal parser and header
 \n";
@@ -132,7 +531,7 @@ Ethereal parsers:
 }
 
 # main program
-GetOptions (
+my $result = GetOptions (
            'help|h|?' => \$opt_help, 
            'outputdir=s' => \$opt_outputdir,
            'dump-idl' => \$opt_dump_idl,
@@ -140,10 +539,13 @@ GetOptions (
                'parse-idl-tree' => \$opt_parse_idl_tree,
                'dump-ndr-tree:s' => \$opt_dump_ndr_tree,
            'uint-enums' => \$opt_uint_enums,
-           'ndr-header:s' => \$opt_ndr_header,
+               'samba3-header:s' => \$opt_samba3_header,
+               'samba3-parser:s' => \$opt_samba3_parser,
+               'samba3-server:s' => \$opt_samba3_server,
+               'samba3-template:s' => \$opt_samba3_template,
+               'samba3-client:s' => \$opt_samba3_client,
                'header:s' => \$opt_header,
            'server:s' => \$opt_server,
-           'tdr-header:s' => \$opt_tdr_header,
            'tdr-parser:s' => \$opt_tdr_parser,
            'template' => \$opt_template,
            'ndr-parser:s' => \$opt_ndr_parser,
@@ -159,6 +561,10 @@ GetOptions (
            'warn-compat' => \$opt_warn_compat
            );
 
+if (not $result) {
+       exit(1);
+}
+
 if ($opt_help) {
     ShowHelp();
     exit(0);
@@ -180,9 +586,8 @@ sub process_file($)
                defined $pidl || die "Failed to load $idl_file";
        } else {
                require Parse::Pidl::IDL;
-               my $idl_parser = new Parse::Pidl::IDL;
 
-               $pidl = $idl_parser->parse_idl($idl_file);
+               $pidl = Parse::Pidl::IDL::parse_file($idl_file);
                defined @$pidl || die "Failed to parse $idl_file";
                require Parse::Pidl::Typelist;
                Parse::Pidl::Typelist::LoadIdl($pidl);
@@ -209,27 +614,22 @@ sub process_file($)
                unlink($tempfile);
        }
 
+
+       my $comh_filename = ($opt_com_header or "$outputdir/com_$basename.h");
        if (defined($opt_com_header)) {
-               require Parse::Pidl::Samba::COM::Header;
-               my $res = Parse::Pidl::Samba::COM::Header::Parse($pidl);
+               require Parse::Pidl::Samba4::COM::Header;
+               my $res = Parse::Pidl::Samba4::COM::Header::Parse($pidl,"$outputdir/ndr_$basename.h");
                if ($res) {
-                       my $comh_filename = ($opt_com_header or "$outputdir/com_$basename.h");
-                       FileSave($comh_filename, 
-                       "#include \"librpc/gen_ndr/ndr_orpc.h\"\n" . 
-                       "#include \"$outputdir/ndr_$basename.h\"\n" . 
-                       $res);
+                       FileSave($comh_filename, $res);
                }
        }
 
        if (defined($opt_dcom_proxy)) {
-               require Parse::Pidl::Samba::COM::Proxy;
-               my $res = Parse::Pidl::Samba::COM::Proxy::Parse($pidl);
+               require Parse::Pidl::Samba4::COM::Proxy;
+               my $res = Parse::Pidl::Samba4::COM::Proxy::Parse($pidl,$comh_filename);
                if ($res) {
                        my ($client) = ($opt_dcom_proxy or "$outputdir/$basename\_p.c");
-                       FileSave($client, 
-                       "#include \"includes.h\"\n" .
-                       "#include \"$outputdir/com_$basename.h\"\n" . 
-                       "#include \"lib/com/dcom/dcom.h\"\n" .$res);
+                       FileSave($client, $res);
                }
        }
 
@@ -240,12 +640,13 @@ sub process_file($)
 
        $pidl = Parse::Pidl::ODL::ODL2IDL($pidl);
 
-       if (defined($opt_ndr_header) or defined($opt_eth_parser) or 
+       if (defined($opt_eth_parser) or 
            defined($opt_client) or defined($opt_server) or 
            defined($opt_ndr_parser) or defined($opt_ejs) or 
-               defined($opt_dump_ndr_tree)) {
+               defined($opt_dump_ndr_tree) or defined($opt_samba3_header) or 
+           defined($opt_samba3_parser) or defined($opt_samba3_server) or 
+               defined($opt_samba3_template) or defined($opt_samba3_client)) {
                require Parse::Pidl::NDR;
-               Parse::Pidl::NDR::Validate($pidl);
                $ndr = Parse::Pidl::NDR::Parse($pidl);
        }
 
@@ -254,53 +655,47 @@ sub process_file($)
                SaveStructure($ndr_file, $ndr) or die "Failed to save $ndr_file\n";
        }
 
+       my $gen_header = ($opt_header or "$outputdir/$basename.h");
        if (defined($opt_header)) {
-               my $header = ($opt_header or "$outputdir/$basename.h");
-               require Parse::Pidl::Samba::Header;
-               FileSave($header, Parse::Pidl::Samba::Header::Parse($pidl));
-       }
-
-       if (defined($opt_ndr_header)) {
-               my $header = ($opt_ndr_header or "$outputdir/ndr_$basename.h");
-               require Parse::Pidl::Samba::NDR::Header;
-               FileSave($header, Parse::Pidl::Samba::NDR::Header::Parse($pidl, $basename));
-               if (defined($opt_swig)) {
-                 require Parse::Pidl::Samba::SWIG;
-                 my($filename) = ($opt_swig or "$outputdir/$basename.i");
-                 Parse::Pidl::Samba::SWIG::RewriteHeader($pidl, $header, $filename);
-               }
+               require Parse::Pidl::Samba4::Header;
+               FileSave($gen_header, Parse::Pidl::Samba4::Header::Parse($pidl));
        }
 
        my $h_filename = "$outputdir/ndr_$basename.h";
        if (defined($opt_client)) {
-               require Parse::Pidl::Samba::NDR::Client;
-               my ($client) = ($opt_client or "$outputdir/ndr_$basename\_c.c");
+               require Parse::Pidl::Samba4::NDR::Client;
+               my ($c_client) = ($opt_client or "$outputdir/ndr_$basename\_c.c");
+               my ($c_header) = $c_client;
+               $c_header =~ s/\.c$/.h/;
 
-               FileSave($client, Parse::Pidl::Samba::NDR::Client::Parse($ndr,$h_filename));
+               my ($srcd,$hdrd) = Parse::Pidl::Samba4::NDR::Client::Parse(
+                       $ndr,$gen_header,$h_filename,$c_header);
+
+               FileSave($c_client, $srcd);
+               FileSave($c_header, $hdrd);
        }
 
        if (defined($opt_ejs)) {
-               require Parse::Pidl::Samba::EJS;
-               require Parse::Pidl::Samba::EJSHeader;
-               FileSave("$outputdir/ndr_$basename\_ejs.c", Parse::Pidl::Samba::EJS::Parse($ndr, $h_filename));
-
-               FileSave("$outputdir/ndr_$basename\_ejs.h", Parse::Pidl::Samba::EJSHeader::Parse($ndr));
+               require Parse::Pidl::Samba4::EJS;
+               my ($hdr,$prsr) = Parse::Pidl::Samba4::EJS::Parse($ndr, $h_filename);
+               FileSave("$outputdir/ndr_$basename\_ejs.c", $prsr);
+               FileSave("$outputdir/ndr_$basename\_ejs.h", $hdr);
        }
 
        if (defined($opt_server)) {
-               require Parse::Pidl::Samba::NDR::Server;
+               require Parse::Pidl::Samba4::NDR::Server;
                my $dcom = "";
 
-               foreach my $x (@{$pidl}) {
-                       next if ($x->{TYPE} ne "INTERFACE");
+               foreach (@{$pidl}) {
+                       next if ($_->{TYPE} ne "INTERFACE");
 
-                       if (Parse::Pidl::Util::has_property($x, "object")) {
-                               require Parse::Pidl::Samba::COM::Stub;
-                               $dcom .= Parse::Pidl::Samba::COM::Stub::ParseInterface($x);
+                       if (Parse::Pidl::Util::has_property($_, "object")) {
+                               require Parse::Pidl::Samba4::COM::Stub;
+                               $dcom .= Parse::Pidl::Samba4::COM::Stub::ParseInterface($_);
                        }
                }
 
-               FileSave(($opt_server or "$outputdir/ndr_$basename\_s.c"), Parse::Pidl::Samba::NDR::Server::Parse($ndr,$h_filename));
+               FileSave(($opt_server or "$outputdir/ndr_$basename\_s.c"), Parse::Pidl::Samba4::NDR::Server::Parse($ndr,$h_filename));
 
                if ($dcom ne "") {
                        $dcom = "
@@ -316,9 +711,19 @@ $dcom
        }
 
        if (defined($opt_ndr_parser)) {
-               my $parser = ($opt_ndr_parser or "$outputdir/ndr_$basename.c");
-               require Parse::Pidl::Samba::NDR::Parser;
-               FileSave($parser, Parse::Pidl::Samba::NDR::Parser::Parse($ndr, $parser));
+               my $parser_fname = ($opt_ndr_parser or "$outputdir/ndr_$basename.c");
+               require Parse::Pidl::Samba4::NDR::Parser;
+               my ($header,$parser) = Parse::Pidl::Samba4::NDR::Parser::Parse($ndr, $gen_header, $h_filename);
+
+
+               FileSave($parser_fname, $parser);
+               FileSave($h_filename, $header);
+
+               if (defined($opt_swig)) {
+                 require Parse::Pidl::Samba4::SWIG;
+                 my($filename) = ($opt_swig or "$outputdir/$basename.i");
+                 Parse::Pidl::Samba4::SWIG::RewriteHeader($pidl, $h_filename, $filename);
+               }
        }
 
        if (defined($opt_eth_parser)) {
@@ -334,27 +739,63 @@ $dcom
          FileSave($eheader, $dh) if defined($dh);
        }
 
-       my $tdr_parser = ($opt_tdr_parser or "$outputdir/tdr_$basename.c");
-       my $tdr_header = ($opt_tdr_header or "$outputdir/tdr_$basename.h");
        if (defined($opt_tdr_parser)) {
-               require Parse::Pidl::Samba::TDR;
-               FileSave($tdr_parser, Parse::Pidl::Samba::TDR::Parser($pidl, $tdr_header));
+               my $tdr_parser = ($opt_tdr_parser or "$outputdir/tdr_$basename.c");
+               my $tdr_header = $tdr_parser;
+               $tdr_header =~ s/\.c$/\.h/;
+               require Parse::Pidl::Samba4::TDR;
+               my ($hdr,$prsr) = Parse::Pidl::Samba4::TDR::Parser($pidl, $tdr_header, $gen_header);
+               FileSave($tdr_parser, $prsr);
+               FileSave($tdr_header, $hdr);
        }
 
-       if (defined($opt_tdr_header)) {
-               require Parse::Pidl::Samba::TDR;
-               FileSave($tdr_header, Parse::Pidl::Samba::TDR::Header($pidl, $outputdir,$basename));
+       if ($opt_template) {
+               require Parse::Pidl::Samba4::Template;
+               print Parse::Pidl::Samba4::Template::Parse($pidl);
        }
 
-       if ($opt_template) {
-               require Parse::Pidl::Samba::Template;
-               print Parse::Pidl::Samba::Template::Parse($pidl);
+       if (defined($opt_samba3_header) or defined($opt_samba3_parser) or
+               defined($opt_samba3_server) or defined($opt_samba3_client) or
+               defined($opt_samba3_template)) {
+               require Parse::Pidl::Samba3::Types;
+               Parse::Pidl::Samba3::Types::LoadTypes($ndr);
+       }
+
+       if (defined($opt_samba3_header)) {
+               my $header = ($opt_samba3_header or "$outputdir/rpc_$basename.h");
+               require Parse::Pidl::Samba3::Header;
+               FileSave($header, Parse::Pidl::Samba3::Header::Parse($ndr, $basename));
        }
+
+       if (defined($opt_samba3_parser)) {
+               my $header = ($opt_samba3_parser or "$outputdir/parse_$basename.c");
+               require Parse::Pidl::Samba3::Parser;
+               FileSave($header, Parse::Pidl::Samba3::Parser::Parse($ndr, $basename));
+       }
+
+       if (defined($opt_samba3_server)) {
+               my $header = ($opt_samba3_server or "$outputdir/srv_$basename.c");
+               require Parse::Pidl::Samba3::Server;
+               FileSave($header, Parse::Pidl::Samba3::Server::Parse($ndr, $basename));
+       }
+
+       if (defined($opt_samba3_template)) {
+               my $header = ($opt_samba3_template or "$outputdir/srv_$basename\_nt.c");
+               require Parse::Pidl::Samba3::Template;
+               FileSave($header, Parse::Pidl::Samba3::Template::Parse($ndr, $basename));
+       }
+
+       if (defined($opt_samba3_client)) {
+               my $header = ($opt_samba3_client or "$outputdir/cli_$basename.c");
+               require Parse::Pidl::Samba3::Client;
+               FileSave($header, Parse::Pidl::Samba3::Client::Parse($ndr, $basename));
+       }
+
 }
 
 if (scalar(@ARGV) == 0) {
        print "pidl: no input files\n";
-       exit(0);
+       exit(1);
 }
 
 process_file($_) foreach (@ARGV);