1 #!/usr/bin/perl -w 2 3 # Copyright (C) 2012 Tony Chang <tony (at] chromium.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 COMPUTER, 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 use strict; 27 28 use InFilesCompiler; 29 30 my %defaultParameters = ( 31 ); 32 33 my %webcoreTypeToIdlType = ( 34 'int' => 'long', 35 'unsigned' => 'unsigned long', 36 'size_t' => 'unsigned long', 37 'double' => 'double', 38 'float' => 'float', 39 'String' => 'DOMString', 40 'bool' => 'boolean' 41 ); 42 43 sub defaultItemFactory 44 { 45 return ( 46 'conditional' => 0, 47 'initial' => '', 48 'type' => 'bool', 49 'setNeedsStyleRecalcInAllFrames' => 0, 50 ); 51 } 52 53 my $InCompiler = InFilesCompiler->new(\%defaultParameters, \&defaultItemFactory); 54 55 my $outputDir = $InCompiler->initializeFromCommandLine(); 56 $InCompiler->compile(\&generateCode); 57 58 sub generateCode() 59 { 60 my $parsedParametersRef = shift; 61 my $parsedItemsRef = shift; 62 63 generateSettingsMacrosHeader($parsedItemsRef); 64 generateInternalSettingsIdlFile($parsedItemsRef); 65 generateInternalSettingsHeaderFile($parsedItemsRef); 66 generateInternalSettingsCppFile($parsedItemsRef); 67 } 68 69 sub generateSettingsMacrosHeader($) 70 { 71 my $parsedItemsRef = shift; 72 73 my %parsedItems = %{ $parsedItemsRef }; 74 my $outputFile = "$outputDir/SettingsMacros.h"; 75 76 my %unconditionalSettings = (); 77 my %settingsByConditional = (); 78 79 for my $settingName (sort keys %parsedItems) { 80 my $conditional = $parsedItems{$settingName}{"conditional"}; 81 82 if ($conditional) { 83 if (!defined($settingsByConditional{$conditional})) { 84 $settingsByConditional{$conditional} = (); 85 } 86 $settingsByConditional{$conditional}{$settingName} = 1; 87 } else { 88 $unconditionalSettings{$settingName} = 1; 89 } 90 } 91 92 open my $file, ">$outputFile" or die "Failed to open file: $!"; 93 94 print $file $InCompiler->license(); 95 96 # FIXME: Sort by type so bools come last and are bit packed. 97 98 print $file "#ifndef SettingsMacros_h\n"; 99 print $file "#define SettingsMacros_h\n\n"; 100 101 printConditionalMacros($file, \%settingsByConditional, $parsedItemsRef); 102 103 printGettersAndSetters($file, \%unconditionalSettings, \%settingsByConditional, $parsedItemsRef); 104 printMemberVariables($file, \%unconditionalSettings, \%settingsByConditional, $parsedItemsRef); 105 printInitializerList($file, \%unconditionalSettings, \%settingsByConditional, $parsedItemsRef); 106 printSetterBodies($file, \%unconditionalSettings, \%settingsByConditional, $parsedItemsRef); 107 108 print $file "#endif // SettingsMacros_h\n"; 109 110 close $file; 111 } 112 113 sub printConditionalMacros($$$) 114 { 115 my ($file, $settingsByConditionalRef, $parsedItemsRef) = @_; 116 my %parsedItems = %{ $parsedItemsRef }; 117 my %settingsByConditional = %{ $settingsByConditionalRef }; 118 119 for my $conditional (sort keys %settingsByConditional) { 120 my $preferredConditional = $InCompiler->preferredConditional($conditional); 121 print $file "#if " . $InCompiler->conditionalStringFromAttributeValue($conditional) . "\n"; 122 123 print $file "#define ${preferredConditional}_SETTINGS_GETTER_AND_SETTERS \\\n"; 124 for my $settingName (sort keys %{ $settingsByConditional{$conditional} }) { 125 printGetterAndSetter($file, $settingName, $parsedItems{$settingName}{"type"}, $parsedItems{$settingName}{"setNeedsStyleRecalcInAllFrames"}); 126 } 127 print $file "// End of ${preferredConditional}_SETTINGS_GETTER_AND_SETTERS\n"; 128 129 print $file "#define ${preferredConditional}_SETTINGS_NON_BOOL_MEMBER_VARIABLES \\\n"; 130 for my $settingName (sort keys %{ $settingsByConditional{$conditional} }) { 131 my $type = $parsedItems{$settingName}{"type"}; 132 next if $type eq "bool"; 133 print $file " $type m_$settingName; \\\n" 134 } 135 print $file "// End of ${preferredConditional}_SETTINGS_NON_BOOL_MEMBER_VARIABLES\n"; 136 137 print $file "#define ${preferredConditional}_SETTINGS_BOOL_MEMBER_VARIABLES \\\n"; 138 for my $settingName (sort keys %{ $settingsByConditional{$conditional} }) { 139 next if $parsedItems{$settingName}{"type"} ne "bool"; 140 print $file " bool m_$settingName : 1; \\\n" 141 } 142 print $file "// End of ${preferredConditional}_SETTINGS_BOOL_MEMBER_VARIABLES\n"; 143 144 print $file "#define ${preferredConditional}_SETTINGS_NON_BOOL_INITIALIZERS \\\n"; 145 for my $settingName (sort keys %{ $settingsByConditional{$conditional} }) { 146 next if $parsedItems{$settingName}{"type"} eq "bool"; 147 printInitializer($file, $settingName, $parsedItemsRef); 148 } 149 print $file "// End of ${preferredConditional}_SETTINGS_NON_BOOL_INITIALIZERS\n"; 150 151 print $file "#define ${preferredConditional}_SETTINGS_BOOL_INITIALIZERS \\\n"; 152 for my $settingName (sort keys %{ $settingsByConditional{$conditional} }) { 153 next if $parsedItems{$settingName}{"type"} ne "bool"; 154 printInitializer($file, $settingName, $parsedItemsRef); 155 } 156 print $file "// End of ${preferredConditional}_SETTINGS_BOOL_INITIALIZERS\n"; 157 158 print $file "#define ${preferredConditional}_SETTINGS_SETTER_BODIES \\\n"; 159 for my $settingName (sort keys %{ $settingsByConditional{$conditional} }) { 160 printSetterBody($file, $settingName, $parsedItems{$settingName}{"type"}, $parsedItems{$settingName}{"setNeedsStyleRecalcInAllFrames"}); 161 } 162 print $file "// End of ${preferredConditional}_SETTINGS_SETTER_BODIES\n"; 163 164 print $file "#else\n"; 165 print $file "#define ${preferredConditional}_SETTINGS_GETTER_AND_SETTERS\n"; 166 print $file "#define ${preferredConditional}_SETTINGS_NON_BOOL_MEMBER_VARIABLES\n"; 167 print $file "#define ${preferredConditional}_SETTINGS_BOOL_MEMBER_VARIABLES\n"; 168 print $file "#define ${preferredConditional}_SETTINGS_NON_BOOL_INITIALIZERS\n"; 169 print $file "#define ${preferredConditional}_SETTINGS_BOOL_INITIALIZERS\n"; 170 print $file "#define ${preferredConditional}_SETTINGS_SETTER_BODIES\n"; 171 print $file "#endif\n"; 172 print $file "\n"; 173 } 174 } 175 176 sub printGettersAndSetters($$$$) 177 { 178 my ($file, $unconditionalSettingsRef, $settingsByConditionalRef, $parsedItemsRef) = @_; 179 my %parsedItems = %{ $parsedItemsRef }; 180 my %unconditionalSettings = %{ $unconditionalSettingsRef }; 181 my %settingsByConditional = %{ $settingsByConditionalRef }; 182 183 print $file "#define SETTINGS_GETTERS_AND_SETTERS \\\n"; 184 for my $settingName (sort keys %unconditionalSettings) { 185 printGetterAndSetter($file, $settingName, $parsedItems{$settingName}{"type"}, $parsedItems{$settingName}{"setNeedsStyleRecalcInAllFrames"}); 186 } 187 for my $conditional (sort keys %settingsByConditional) { 188 my $preferredConditional = $InCompiler->preferredConditional($conditional); 189 print $file " ${preferredConditional}_SETTINGS_GETTER_AND_SETTERS \\\n"; 190 } 191 print $file "// End of SETTINGS_GETTERS_AND_SETTERS.\n\n"; 192 } 193 194 sub printMemberVariables($$$$) 195 { 196 my ($file, $unconditionalSettingsRef, $settingsByConditionalRef, $parsedItemsRef) = @_; 197 my %parsedItems = %{ $parsedItemsRef }; 198 my %unconditionalSettings = %{ $unconditionalSettingsRef }; 199 my %settingsByConditional = %{ $settingsByConditionalRef }; 200 201 print $file "#define SETTINGS_MEMBER_VARIABLES \\\n"; 202 # We list the bools last so we can bit pack them. 203 for my $settingName (sort keys %unconditionalSettings) { 204 my $type = $parsedItems{$settingName}{"type"}; 205 next if $type eq "bool"; 206 print $file " $type m_$settingName; \\\n" 207 } 208 for my $conditional (sort keys %settingsByConditional) { 209 my $preferredConditional = $InCompiler->preferredConditional($conditional); 210 print $file " ${preferredConditional}_SETTINGS_NON_BOOL_MEMBER_VARIABLES \\\n"; 211 } 212 for my $settingName (sort keys %unconditionalSettings) { 213 next if $parsedItems{$settingName}{"type"} ne "bool"; 214 print $file " bool m_$settingName : 1; \\\n" 215 } 216 for my $conditional (sort keys %settingsByConditional) { 217 my $preferredConditional = $InCompiler->preferredConditional($conditional); 218 print $file " ${preferredConditional}_SETTINGS_BOOL_MEMBER_VARIABLES \\\n"; 219 } 220 print $file "// End of SETTINGS_MEMBER_VARIABLES.\n\n"; 221 } 222 223 sub setterFunctionName($) 224 { 225 my $settingName = shift; 226 my $setterFunctionName = "set" . $settingName; 227 substr($setterFunctionName, 3, 1) = uc(substr($setterFunctionName, 3, 1)); 228 my @prefixesToUpperCase = ("css", "xss", "ftp", "dom"); 229 foreach my $prefix (@prefixesToUpperCase) { 230 my $prefixLength = length($prefix); 231 if (substr($settingName, 0, $prefixLength) eq $prefix) { 232 substr($setterFunctionName, $prefixLength, $prefixLength) = uc(substr($setterFunctionName, 3, 3)); 233 } 234 } 235 return $setterFunctionName; 236 } 237 238 sub printGetterAndSetter($$$$) 239 { 240 my ($file, $settingName, $type, $setNeedsStyleRecalcInAllFrames) = @_; 241 my $setterFunctionName = setterFunctionName($settingName); 242 if (lc(substr($type, 0, 1)) eq substr($type, 0, 1)) { 243 print $file " $type $settingName() const { return m_$settingName; } \\\n"; 244 print $file " void $setterFunctionName($type $settingName)"; 245 } else { 246 print $file " const $type& $settingName() { return m_$settingName; } \\\n"; 247 print $file " void $setterFunctionName(const $type& $settingName)"; 248 } 249 if ($setNeedsStyleRecalcInAllFrames) { 250 print $file "; \\\n"; 251 } else { 252 print $file " { m_$settingName = $settingName; } \\\n"; 253 } 254 } 255 256 sub printInitializerList($$$$) 257 { 258 my ($file, $unconditionalSettingsRef, $settingsByConditionalRef, $parsedItemsRef) = @_; 259 my %parsedItems = %{ $parsedItemsRef }; 260 my %unconditionalSettings = %{ $unconditionalSettingsRef }; 261 my %settingsByConditional = %{ $settingsByConditionalRef }; 262 263 print $file "#define SETTINGS_INITIALIZER_LIST \\\n"; 264 for my $settingName (sort keys %unconditionalSettings) { 265 next if $parsedItems{$settingName}{"type"} eq "bool"; 266 printInitializer($file, $settingName, $parsedItemsRef); 267 } 268 for my $conditional (sort keys %settingsByConditional) { 269 my $preferredConditional = $InCompiler->preferredConditional($conditional); 270 print $file " ${preferredConditional}_SETTINGS_NON_BOOL_INITIALIZERS \\\n"; 271 } 272 for my $settingName (sort keys %unconditionalSettings) { 273 next if $parsedItems{$settingName}{"type"} ne "bool"; 274 printInitializer($file, $settingName, $parsedItemsRef); 275 } 276 for my $conditional (sort keys %settingsByConditional) { 277 my $preferredConditional = $InCompiler->preferredConditional($conditional); 278 print $file " ${preferredConditional}_SETTINGS_BOOL_INITIALIZERS \\\n"; 279 } 280 print $file "// End of SETTINGS_INITIALIZER_LIST.\n\n"; 281 } 282 283 sub printInitializer($$$) 284 { 285 my ($file, $settingName, $parsedItemsRef) = @_; 286 my %parsedItems = %{ $parsedItemsRef }; 287 288 my $initialValue = $parsedItems{$settingName}{"initial"}; 289 my $type = $parsedItems{$settingName}{"type"}; 290 die "Must provide an initial value for $settingName." if ($initialValue eq '' && lc(substr($type, 0, 1)) eq substr($type, 0, 1)); 291 return if ($initialValue eq ''); 292 print $file " , m_$settingName($initialValue) \\\n" 293 } 294 295 sub printSetterBodies($$$$) 296 { 297 my ($file, $unconditionalSettingsRef, $settingsByConditionalRef, $parsedItemsRef) = @_; 298 my %parsedItems = %{ $parsedItemsRef }; 299 my %unconditionalSettings = %{ $unconditionalSettingsRef }; 300 my %settingsByConditional = %{ $settingsByConditionalRef }; 301 302 print $file "#define SETTINGS_SETTER_BODIES \\\n"; 303 for my $settingName (sort keys %unconditionalSettings) { 304 printSetterBody($file, $settingName, $parsedItems{$settingName}{"type"}, $parsedItems{$settingName}{"setNeedsStyleRecalcInAllFrames"}); 305 } 306 for my $conditional (sort keys %settingsByConditional) { 307 my $preferredConditional = $InCompiler->preferredConditional($conditional); 308 print $file " ${preferredConditional}_SETTINGS_SETTER_BODIES \\\n"; 309 } 310 print $file "// End of SETTINGS_SETTER_BODIES.\n\n"; 311 } 312 313 sub printSetterBody($$$$) 314 { 315 my ($file, $settingName, $type, $setNeedsStyleRecalcInAllFrames) = @_; 316 return if (!$setNeedsStyleRecalcInAllFrames); 317 318 my $setterFunctionName = setterFunctionName($settingName); 319 if (lc(substr($type, 0, 1)) eq substr($type, 0, 1)) { 320 print $file "void Settings::$setterFunctionName($type $settingName) \\\n"; 321 } else { 322 print $file "void Settings::$setterFunctionName(const $type& $settingName) \\\n"; 323 } 324 print $file "{ \\\n"; 325 print $file " if (m_$settingName == $settingName) \\\n"; 326 print $file " return; \\\n"; 327 print $file " m_$settingName = $settingName; \\\n"; 328 print $file " m_page->setNeedsRecalcStyleInAllFrames(); \\\n"; 329 print $file "} \\\n"; 330 } 331 332 sub enumerateParsedItems($$$) 333 { 334 my ($file, $parsedItemsRef, $visitorFunction) = @_; 335 my %parsedItems = %{ $parsedItemsRef }; 336 337 for my $settingName (sort keys %parsedItems) { 338 my $type = $parsedItems{$settingName}{"type"}; 339 # FIXME: Learn how to auto-generate code for enumerate types. 340 next if (!defined($webcoreTypeToIdlType{$type})); 341 342 &$visitorFunction($file, $parsedItemsRef, $settingName) 343 } 344 } 345 346 sub generateInternalSettingsIdlFile($) 347 { 348 my $parsedItemsRef = shift; 349 350 my $filename = "$outputDir/InternalSettingsGenerated.idl"; 351 open my $file, ">$filename" or die "Failed to open file: $!"; 352 print $file $InCompiler->license(); 353 354 print $file "interface InternalSettingsGenerated {\n"; 355 356 sub writeIdlSetter($$$) { 357 my ($file, $parsedItemsRef, $settingName) = @_; 358 my %parsedItems = %{ $parsedItemsRef }; 359 my $type = $parsedItems{$settingName}{"type"}; 360 my $idlType = $webcoreTypeToIdlType{$type}; 361 my $setterFunctionName = setterFunctionName($settingName); 362 print $file " void $setterFunctionName($idlType $settingName);\n"; 363 }; 364 365 enumerateParsedItems($file, $parsedItemsRef, \&writeIdlSetter); 366 367 print $file "};\n"; 368 close $file; 369 } 370 371 sub generateInternalSettingsHeaderFile($) 372 { 373 my $parsedItemsRef = shift; 374 my %parsedItems = %{ $parsedItemsRef }; 375 376 my $filename = "$outputDir/InternalSettingsGenerated.h"; 377 open my $file, ">$filename" or die "Failed to open file: $!"; 378 print $file $InCompiler->license(); 379 380 print $file <<EOF; 381 #ifndef InternalSettingsGenerated_h 382 #define InternalSettingsGenerated_h 383 384 #include "core/platform/RefCountedSupplement.h" 385 #include "wtf/PassRefPtr.h" 386 #include "wtf/RefCounted.h" 387 #include "wtf/text/WTFString.h" 388 389 namespace WebCore { 390 391 class Page; 392 393 class InternalSettingsGenerated : public RefCounted<InternalSettingsGenerated> { 394 public: 395 explicit InternalSettingsGenerated(Page*); 396 virtual ~InternalSettingsGenerated(); 397 void resetToConsistentState(); 398 EOF 399 sub writeHeaderPrototypes($$$) { 400 my ($file, $parsedItemsRef, $settingName) = @_; 401 my %parsedItems = %{ $parsedItemsRef }; 402 my $type = $parsedItems{$settingName}{"type"}; 403 my $setterFunctionName = setterFunctionName($settingName); 404 $type = "const String&" if $type eq "String"; 405 print $file " void $setterFunctionName($type $settingName);\n"; 406 }; 407 enumerateParsedItems($file, $parsedItemsRef, \&writeHeaderPrototypes); 408 409 print $file <<EOF; 410 411 private: 412 Page* m_page; 413 414 EOF 415 416 sub writeBackupMembers($$$) { 417 my ($file, $parsedItemsRef, $settingName) = @_; 418 my %parsedItems = %{ $parsedItemsRef }; 419 my $type = $parsedItems{$settingName}{"type"}; 420 my $conditional = $parsedItems{$settingName}{"conditional"}; 421 if ($conditional) { 422 print $file "#if " . $InCompiler->conditionalStringFromAttributeValue($conditional) . "\n"; 423 } 424 print $file " $type m_$settingName;\n"; 425 if ($conditional) { 426 print $file "#endif\n"; 427 } 428 }; 429 enumerateParsedItems($file, $parsedItemsRef, \&writeBackupMembers); 430 431 print $file "};\n\n"; 432 print $file "} // namespace WebCore\n"; 433 print $file "#endif // InternalSettingsGenerated_h\n"; 434 435 close $file; 436 } 437 438 sub generateInternalSettingsCppFile($) 439 { 440 my $parsedItemsRef = shift; 441 my %parsedItems = %{ $parsedItemsRef }; 442 443 my $filename = "$outputDir/InternalSettingsGenerated.cpp"; 444 open my $file, ">$filename" or die "Failed to open file: $!"; 445 print $file $InCompiler->license(); 446 447 print $file <<EOF; 448 #include "config.h" 449 #include "InternalSettingsGenerated.h" 450 451 #include "core/page/Page.h" 452 #include "core/page/Settings.h" 453 454 namespace WebCore { 455 456 InternalSettingsGenerated::InternalSettingsGenerated(Page* page) 457 : m_page(page) 458 EOF 459 460 sub writeBackupInitializers($$$) { 461 my ($file, $parsedItemsRef, $settingName) = @_; 462 my %parsedItems = %{ $parsedItemsRef }; 463 my $type = $parsedItems{$settingName}{"type"}; 464 my $conditional = $parsedItems{$settingName}{"conditional"}; 465 if ($conditional) { 466 print $file "#if " . $InCompiler->conditionalStringFromAttributeValue($conditional) . "\n"; 467 } 468 print $file " , m_$settingName(page->settings()->$settingName())\n"; 469 if ($conditional) { 470 print $file "#endif\n"; 471 } 472 }; 473 enumerateParsedItems($file, $parsedItemsRef, \&writeBackupInitializers); 474 475 print $file <<EOF; 476 { 477 } 478 479 InternalSettingsGenerated::~InternalSettingsGenerated() 480 { 481 } 482 483 void InternalSettingsGenerated::resetToConsistentState() 484 { 485 EOF 486 sub writeResetToConsistentState($$$) { 487 my ($file, $parsedItemsRef, $settingName) = @_; 488 my %parsedItems = %{ $parsedItemsRef }; 489 my $type = $parsedItems{$settingName}{"type"}; 490 my $setterFunctionName = setterFunctionName($settingName); 491 my $conditional = $parsedItems{$settingName}{"conditional"}; 492 if ($conditional) { 493 print $file "#if " . $InCompiler->conditionalStringFromAttributeValue($conditional) . "\n"; 494 } 495 print $file " m_page->settings()->$setterFunctionName(m_$settingName);\n"; 496 if ($conditional) { 497 print $file "#endif\n"; 498 } 499 }; 500 enumerateParsedItems($file, $parsedItemsRef, \&writeResetToConsistentState); 501 502 print $file "}\n"; 503 504 sub writeSetterFunctions($$$) { 505 my ($file, $parsedItemsRef, $settingName) = @_; 506 my %parsedItems = %{ $parsedItemsRef }; 507 my $type = $parsedItems{$settingName}{"type"}; 508 my $conditional = $parsedItems{$settingName}{"conditional"}; 509 my $setterFunctionName = setterFunctionName($settingName); 510 $type = "const String&" if $type eq "String"; 511 512 print $file "void InternalSettingsGenerated::$setterFunctionName($type $settingName)\n"; 513 print $file "{\n"; 514 515 if ($conditional) { 516 print $file "#if " . $InCompiler->conditionalStringFromAttributeValue($conditional) . "\n"; 517 } 518 print $file " m_page->settings()->$setterFunctionName($settingName);\n"; 519 if ($conditional) { 520 print $file "#else\n"; 521 print $file " UNUSED_PARAM($settingName);\n"; 522 print $file "#endif\n"; 523 } 524 print $file "}\n\n"; 525 }; 526 enumerateParsedItems($file, $parsedItemsRef, \&writeSetterFunctions); 527 528 print $file "} // namespace WebCore\n"; 529 530 close $file; 531 } 532