All prototypes should call didBecomePrototype()
[WebKit.git] / Source / WebCore / bindings / scripts / InFilesCompiler.pm
1 #!/usr/bin/env perl
2
3 # Copyright (C) 2011 Adam Barth <abarth@webkit.org>
4 #
5 # Redistribution and use in source and binary forms, with or without
6 # modification, are permitted provided that the following conditions
7 # are met:
8 # 1. Redistributions of source code must retain the above copyright
9 #    notice, this list of conditions and the following disclaimer.
10 # 2. Redistributions in binary form must reproduce the above copyright
11 #    notice, this list of conditions and the following disclaimer in the
12 #    documentation and/or other materials provided with the distribution.
13 #
14 # THIS SOFTWARE IS PROVIDED BY GOOGLE, INC. ``AS IS'' AND ANY
15 # EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17 # PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
18 # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19 # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 # PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21 # PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22 # OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
25 #
26
27 use strict;
28 use warnings;
29
30 use Config;
31 use Getopt::Long;
32 use File::Path;
33 use File::Spec;
34 use IO::File;
35 use InFilesParser;
36
37 require Config;
38
39 package InFilesCompiler;
40
41 my @inputFiles;
42 my $outputDir = ".";
43 my $defaultItemFactory;
44
45 my %parsedItems;
46 my %parsedParameters;
47
48 sub itemHandler($$$)
49 {
50     my ($itemName, $property, $value) = @_;
51
52     $parsedItems{$itemName} = { &$defaultItemFactory($itemName) } if !defined($parsedItems{$itemName});
53
54     return unless $property;
55
56     die "Unknown property $property for $itemName\n" if !defined($parsedItems{$itemName}{$property});
57     $parsedItems{$itemName}{$property} = $value;
58 }
59
60 sub parameterHandler($$)
61 {
62     my ($parameter, $value) = @_;
63
64     die "Unknown parameter $parameter\n" if !defined($parsedParameters{$parameter});
65     $parsedParameters{$parameter} = $value;
66 }
67
68 sub new()
69 {
70     my $object = shift;
71     my $reference = { };
72
73     my $defaultParametersRef = shift;
74     %parsedParameters = %{ $defaultParametersRef };
75     $defaultItemFactory = shift;
76
77     %parsedItems = ();
78
79     bless($reference, $object);
80     return $reference;
81 }
82
83 sub initializeFromCommandLine()
84 {
85     ::GetOptions(
86         'input=s' => \@inputFiles,
87         'outputDir=s' => \$outputDir,
88     );
89
90     die "You must specify at least one --input <file>" unless scalar(@inputFiles);
91
92     ::mkpath($outputDir);
93
94     # FIXME: Should we provide outputDir via an accessor?
95     return $outputDir;
96 }
97
98 sub compile()
99 {
100     my $object = shift;
101     my $generateCode = shift;
102
103     my $InParser = InFilesParser->new();
104
105     foreach my $inputFile (@inputFiles) {
106         my $file = new IO::File;
107         open($file, $inputFile) or die "Failed to open file: $!";
108
109         $InParser->parse($file, \&parameterHandler, \&itemHandler);
110
111         close($file);
112         die "Failed to read from file: $inputFile" if (keys %parsedItems == 0);
113     }
114
115     &$generateCode(\%parsedParameters, \%parsedItems);
116 }
117
118 sub license()
119 {
120     return "/*
121  * THIS FILE WAS AUTOMATICALLY GENERATED, DO NOT EDIT.
122  *
123  * Copyright (C) 2011 Google Inc.  All rights reserved.
124  *
125  * Redistribution and use in source and binary forms, with or without
126  * modification, are permitted provided that the following conditions
127  * are met:
128  * 1. Redistributions of source code must retain the above copyright
129  *    notice, this list of conditions and the following disclaimer.
130  * 2. Redistributions in binary form must reproduce the above copyright
131  *    notice, this list of conditions and the following disclaimer in the
132  *    documentation and/or other materials provided with the distribution.
133  *
134  * THIS SOFTWARE IS PROVIDED BY GOOGLE, INC. ``AS IS'' AND ANY
135  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
136  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
137  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
138  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
139  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
140  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
141  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
142  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
143  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
144  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
145  */
146
147 ";
148 }
149
150 sub interfaceForItem($)
151 {
152     my $object = shift;
153     my $itemName = shift;
154
155     my $interfaceName = $parsedItems{$itemName}{"interfaceName"};
156     $interfaceName = $itemName unless $interfaceName;
157
158     return $interfaceName;
159 }
160
161 sub toMacroStyle($$)
162 {
163     my $object = shift;
164     my $camelCase = shift;
165
166     return "EVENT" if $camelCase eq "Event";
167     return "EVENT_TARGET" if $camelCase eq "EventTarget";
168     return "EXCEPTION" if $camelCase eq "Exception";
169
170     die "Ok, you got me. This script is really just a giant hack. (\$camelCase=${camelCase})";
171 }
172
173 sub preferredConditional()
174 {
175     my $object = shift;
176     my $conditional = shift;
177
178     my @conditionals = split('\\|', $conditional);
179     return $conditionals[0];
180 }
181
182 sub conditionalStringFromAttributeValue()
183 {
184     my $object = shift;
185     my $conditional = shift;
186     
187     return "ENABLE(" . join(') || ENABLE(', split('\\|', $conditional)) . ")";
188 }
189
190 sub generateInterfacesHeader()
191 {
192     my $object = shift;
193
194     my $F;
195     my $namespace = $parsedParameters{"namespace"};
196     my $useNamespaceAsSuffix = $parsedParameters{"useNamespaceAsSuffix"};
197     my $outputFile = "$outputDir/${namespace}Interfaces.h";
198
199     open F, ">$outputFile" or die "Failed to open file: $!";
200
201     print F license();
202
203     print F "#pragma once\n";
204     print F "\n";
205
206     my %unconditionalInterfaces = ();
207     my %interfacesByConditional = ();
208
209     for my $itemName (sort keys %parsedItems) {
210         my $conditional = $parsedItems{$itemName}{"conditional"};
211         my $interfaceName = $object->interfaceForItem($itemName);
212
213         if ($conditional) {
214             if (!defined($interfacesByConditional{$conditional})) {
215                 $interfacesByConditional{$conditional} = ();
216             }
217             $interfacesByConditional{$conditional}{$interfaceName} = 1;
218         } else {
219             $unconditionalInterfaces{$interfaceName} = 1
220         }
221     }
222
223     my $macroStyledNamespace = $object->toMacroStyle($namespace);
224
225     print F "namespace WebCore {\n";
226     print F "\n";
227     print F "enum ${namespace}Interface {\n";
228
229     my $suffix = "InterfaceType";
230     if ($useNamespaceAsSuffix eq "true") {
231         $suffix = $namespace . $suffix;
232     }
233
234     my $count = 1;
235     for my $conditional (sort keys %interfacesByConditional) {
236         my $preferredConditional = $object->preferredConditional($conditional);
237         print F "#if " . $object->conditionalStringFromAttributeValue($conditional) . "\n";
238         for my $interface (sort keys %{ $interfacesByConditional{$conditional} }) {
239             next if defined($unconditionalInterfaces{$interface});
240             print F "    ${interface}${suffix} = $count,\n";
241             $count++;
242         }
243         print F "#endif\n";
244     }
245
246     for my $interface (sort keys %unconditionalInterfaces) {
247         print F "    ${interface}${suffix} = $count,\n";
248         $count++;
249     }
250
251     print F "};\n";
252     print F "\n";
253     print F "} // namespace WebCore\n";
254
255     close F;
256 }
257
258 sub generateHeadersHeader()
259 {
260     my $object = shift;
261
262     my $F;
263     my $namespace = $parsedParameters{"namespace"};
264     my $outputFile = "$outputDir/${namespace}Headers.h";
265
266     open F, ">$outputFile" or die "Failed to open file: $!";
267
268     print F license();
269
270     print F "#ifndef ${namespace}Headers_h\n";
271     print F "#define ${namespace}Headers_h\n";
272     print F "\n";
273
274     my %includedInterfaces = ();
275
276     for my $itemName (sort keys %parsedItems) {
277         my $conditional = $parsedItems{$itemName}{"conditional"};
278         my $interfaceName = $object->interfaceForItem($itemName);
279
280         next if defined($includedInterfaces{$interfaceName});
281         $includedInterfaces{$interfaceName} = 1;
282
283         print F "#if " . $object->conditionalStringFromAttributeValue($conditional) . "\n" if $conditional;
284         print F "#include \"$interfaceName.h\"\n";
285         print F "#include \"JS$interfaceName.h\"\n";
286         print F "#endif\n" if $conditional;
287     }
288
289     print F "\n";
290     print F "#endif // ${namespace}Headers_h\n";
291
292     close F;
293 }
294
295 1;