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