blob: f42bdd3af1472efc7b5c6148fe5e6ea73edce696 [file] [log] [blame]
#!/usr/bin/env perl
# Copyright (C) 2011 Adam Barth <abarth@webkit.org>
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY GOOGLE, INC. ``AS IS'' AND ANY
# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
# OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
use strict;
use warnings;
use Config;
use Getopt::Long;
use File::Path;
use File::Spec;
use IO::File;
use InFilesParser;
require Config;
package InFilesCompiler;
my @inputFiles;
my $outputDir = ".";
my $defaultItemFactory;
my %parsedItems;
my %parsedParameters;
sub itemHandler($$$)
{
my ($itemName, $property, $value) = @_;
$parsedItems{$itemName} = { &$defaultItemFactory($itemName) } if !defined($parsedItems{$itemName});
return unless $property;
die "Unknown property $property for $itemName\n" if !defined($parsedItems{$itemName}{$property});
$parsedItems{$itemName}{$property} = $value;
}
sub parameterHandler($$)
{
my ($parameter, $value) = @_;
die "Unknown parameter $parameter\n" if !defined($parsedParameters{$parameter});
$parsedParameters{$parameter} = $value;
}
sub new()
{
my $object = shift;
my $reference = { };
my $defaultParametersRef = shift;
%parsedParameters = %{ $defaultParametersRef };
$defaultItemFactory = shift;
%parsedItems = ();
bless($reference, $object);
return $reference;
}
sub initializeFromCommandLine()
{
::GetOptions(
'input=s' => \@inputFiles,
'outputDir=s' => \$outputDir,
);
die "You must specify at least one --input <file>" unless scalar(@inputFiles);
::mkpath($outputDir);
# FIXME: Should we provide outputDir via an accessor?
return $outputDir;
}
sub compile()
{
my $object = shift;
my $generateCode = shift;
my $InParser = InFilesParser->new();
foreach my $inputFile (@inputFiles) {
my $file = new IO::File;
open($file, $inputFile) or die "Failed to open file: $!";
$InParser->parse($file, \&parameterHandler, \&itemHandler);
close($file);
die "Failed to read from file: $inputFile" if (keys %parsedItems == 0);
}
&$generateCode(\%parsedParameters, \%parsedItems);
}
sub license()
{
return "/*
* THIS FILE WAS AUTOMATICALLY GENERATED, DO NOT EDIT.
*
* Copyright (C) 2011 Google Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY GOOGLE, INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
";
}
sub interfaceForItem($)
{
my $object = shift;
my $itemName = shift;
my $interfaceName = $parsedItems{$itemName}{"interfaceName"};
$interfaceName = $itemName unless $interfaceName;
return $interfaceName;
}
sub toMacroStyle($$)
{
my $object = shift;
my $camelCase = shift;
return "EVENT" if $camelCase eq "Event";
return "EVENT_TARGET" if $camelCase eq "EventTarget";
return "EXCEPTION" if $camelCase eq "Exception";
die "Ok, you got me. This script is really just a giant hack. (\$camelCase=${camelCase})";
}
sub preferredConditional()
{
my $object = shift;
my $conditional = shift;
my @conditionals = split('\\|', $conditional);
return $conditionals[0];
}
sub conditionalStringFromAttributeValue()
{
my $object = shift;
my $conditional = shift;
return "ENABLE(" . join(') || ENABLE(', split('\\|', $conditional)) . ")";
}
sub generateInterfacesHeader()
{
my $object = shift;
my $F;
my $namespace = $parsedParameters{"namespace"};
my $outputFile = "$outputDir/${namespace}Interfaces.h";
open F, ">$outputFile" or die "Failed to open file: $!";
print F license();
print F "#ifndef ${namespace}Interfaces_h\n";
print F "#define ${namespace}Interfaces_h\n";
print F "\n";
my %unconditionalInterfaces = ();
my %interfacesByConditional = ();
for my $itemName (sort keys %parsedItems) {
my $conditional = $parsedItems{$itemName}{"conditional"};
my $interfaceName = $object->interfaceForItem($itemName);
if ($conditional) {
if (!defined($interfacesByConditional{$conditional})) {
$interfacesByConditional{$conditional} = ();
}
$interfacesByConditional{$conditional}{$interfaceName} = 1;
} else {
$unconditionalInterfaces{$interfaceName} = 1
}
}
my $macroStyledNamespace = $object->toMacroStyle($namespace);
for my $conditional (sort keys %interfacesByConditional) {
my $preferredConditional = $object->preferredConditional($conditional);
print F "#if " . $object->conditionalStringFromAttributeValue($conditional) . "\n";
print F "#define DOM_${macroStyledNamespace}_INTERFACES_FOR_EACH_$preferredConditional(macro) \\\n";
for my $interface (sort keys %{ $interfacesByConditional{$conditional} }) {
next if defined($unconditionalInterfaces{$interface});
print F " macro($interface) \\\n";
}
print F "// End of DOM_${macroStyledNamespace}_INTERFACES_FOR_EACH_$preferredConditional\n";
print F "#else\n";
print F "#define DOM_${macroStyledNamespace}_INTERFACES_FOR_EACH_$preferredConditional(macro)\n";
print F "#endif\n";
print F "\n";
}
print F "#define DOM_${macroStyledNamespace}_INTERFACES_FOR_EACH(macro) \\\n";
print F " \\\n";
for my $interface (sort keys %unconditionalInterfaces) {
print F " macro($interface) \\\n";
}
print F " \\\n";
for my $conditional (sort keys %interfacesByConditional) {
my $preferredConditional = $object->preferredConditional($conditional);
print F " DOM_${macroStyledNamespace}_INTERFACES_FOR_EACH_$preferredConditional(macro) \\\n";
}
print F "\n";
print F "#endif // ${namespace}Interfaces_h\n";
close F;
}
sub generateHeadersHeader()
{
my $object = shift;
my $F;
my $namespace = $parsedParameters{"namespace"};
my $outputFile = "$outputDir/${namespace}Headers.h";
open F, ">$outputFile" or die "Failed to open file: $!";
print F license();
print F "#ifndef ${namespace}Headers_h\n";
print F "#define ${namespace}Headers_h\n";
print F "\n";
my %includedInterfaces = ();
for my $itemName (sort keys %parsedItems) {
my $conditional = $parsedItems{$itemName}{"conditional"};
my $interfaceName = $object->interfaceForItem($itemName);
next if defined($includedInterfaces{$interfaceName});
$includedInterfaces{$interfaceName} = 1;
print F "#if " . $object->conditionalStringFromAttributeValue($conditional) . "\n" if $conditional;
print F "#include \"$interfaceName.h\"\n";
print F "#include \"JS$interfaceName.h\"\n";
print F "#endif\n" if $conditional;
}
print F "\n";
print F "#endif // ${namespace}Headers_h\n";
close F;
}
1;