r3689: Large number of COM updates:
[samba.git] / source4 / build / pidl / pidl.pl
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 # released under the GNU GPL
8
9 use strict;
10
11 use FindBin qw($RealBin);
12 use lib "$RealBin";
13 use lib "$RealBin/lib";
14 use Getopt::Long;
15 use File::Basename;
16 use idl;
17 use dump;
18 use header;
19 use server;
20 use stub;
21 use parser;
22 use eparser;
23 use validator;
24 use util;
25 use template;
26 use swig;
27
28 my($opt_help) = 0;
29 my($opt_parse) = 0;
30 my($opt_dump) = 0;
31 my($opt_diff) = 0;
32 my($opt_header) = 0;
33 my($opt_template) = 0;
34 my($opt_server) = 0;
35 my($opt_parser) = 0;
36 my($opt_eparser) = 0;
37 my($opt_keep) = 0;
38 my($opt_swig) = 0;
39 my($opt_output);
40
41 my $idl_parser = new idl;
42
43 #####################################################################
44 # parse an IDL file returning a structure containing all the data
45 sub IdlParse($)
46 {
47     my $filename = shift;
48     my $idl = $idl_parser->parse_idl($filename);
49     util::CleanData($idl);
50     return $idl;
51 }
52
53
54 #########################################
55 # display help text
56 sub ShowHelp()
57 {
58     print "
59            perl IDL parser and code generator
60            Copyright (C) tridge\@samba.org
61
62            Usage: pidl.pl [options] <idlfile>
63
64            Options:
65              --help                this help page
66              --output OUTNAME      put output in OUTNAME.*
67              --parse               parse a idl file to a .pidl file
68              --dump                dump a pidl file back to idl
69              --header              create a C header file
70              --parser              create a C parser
71              --server              create server boilerplate
72              --template            print a template for a pipe
73              --eparser             create an ethereal parser
74              --swig                create swig wrapper file
75              --diff                run diff on the idl and dumped output
76              --keep                keep the .pidl file
77            \n";
78     exit(0);
79 }
80
81 # main program
82 GetOptions (
83             'help|h|?' => \$opt_help, 
84             'output=s' => \$opt_output,
85             'parse' => \$opt_parse,
86             'dump' => \$opt_dump,
87             'header' => \$opt_header,
88             'server' => \$opt_server,
89             'template' => \$opt_template,
90             'parser' => \$opt_parser,
91             'eparser' => \$opt_eparser,
92             'diff' => \$opt_diff,
93             'keep' => \$opt_keep,
94             'swig' => \$opt_swig
95             );
96
97 if ($opt_help) {
98     ShowHelp();
99     exit(0);
100 }
101
102 sub process_file($)
103 {
104         my $idl_file = shift;
105         my $output;
106         my $pidl;
107
108         my $basename = basename($idl_file, ".idl");
109
110         if (!defined($opt_output)) {
111                 $output = $idl_file;
112         } else {
113                 $output = $opt_output . $basename;
114         }
115
116         my($pidl_file) = util::ChangeExtension($output, ".pidl");
117
118         print "Compiling $idl_file\n";
119
120         if ($opt_parse) {
121                 $pidl = IdlParse($idl_file);
122                 defined @$pidl || die "Failed to parse $idl_file";
123                 IdlValidator::Validate($pidl);
124                 if ($opt_keep && !util::SaveStructure($pidl_file, $pidl)) {
125                             die "Failed to save $pidl_file\n";
126                 }
127         } else {
128                 $pidl = util::LoadStructure($pidl_file);
129                 defined $pidl || die "Failed to load $pidl_file - maybe you need --parse\n";
130         }
131
132         if ($opt_dump) {
133                 print IdlDump::Dump($pidl);
134         }
135
136         if ($opt_header) {
137                 my($header) = util::ChangeExtension($output, ".h");
138                 util::FileSave($header, IdlHeader::Parse($pidl));
139         }
140
141         if ($opt_server) {
142                 my($server) = util::ChangeExtension($output, "_s.c");
143                 my $res = "";
144                 foreach my $x (@{$pidl}) {
145                         next if ($x->{TYPE} ne "INTERFACE");
146
147                         if (util::has_property($x, "object")) {
148                                 $res .= IdlStub::ParseInterface($x);
149                         } else {
150                                 $res .= IdlServer::ParseInterface($x);
151                         }
152                 }
153                 util::FileSave($server, $res);
154         }
155
156         if ($opt_parser) {
157                 my($parser) = util::ChangeExtension($output, ".c");
158                 IdlParser::Parse($pidl, $parser);
159         }
160
161         if ($opt_eparser) {
162                 my($parser) = dirname($output) . "/packet-dcerpc-$basename.c";
163                 IdlEParser::Parse($pidl, $parser);
164                 $parser = dirname($output) . "/packet-dcerpc-proto-$basename.h";
165                 IdlEParser::ParseHeader($pidl, $parser);
166                 my($header) = dirname($output) . "/packet-dcerpc-proto.h";
167                 open(OUT, ">>$header") || die "can't open $header";
168                 print OUT "#include \"ndr_$basename.h\"\n";
169                 print OUT "#include \"packet-dcerpc-proto-$basename.h\"\n";
170                 close(OUT);
171         }
172
173         if ($opt_swig) {
174                 my($filename) = $output;
175                 $filename =~ s/\/ndr_/\//;
176                 $filename = util::ChangeExtension($filename, ".i");
177                 util::FileSave($filename, IdlSwig::Parse($pidl));
178         }
179
180         if ($opt_diff) {
181                 my($tempfile) = util::ChangeExtension($output, ".tmp");
182                 util::FileSave($tempfile, IdlDump::Dump($pidl));
183                 system("diff -wu $idl_file $tempfile");
184                 unlink($tempfile);
185         }
186
187         if ($opt_template) {
188                 print IdlTemplate::Parse($pidl);
189         }
190 }
191
192
193 foreach my $filename (@ARGV) {
194         process_file($filename);
195 }