| #!/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, \¶meterHandler, \&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; |