#!/usr/bin/perl -w # Copyright (C) 2012 Tony Chang # # 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 InFilesCompiler; my %defaultParameters = ( ); my %webcoreTypeToIdlType = ( 'int' => 'long', 'unsigned' => 'unsigned long', 'size_t' => 'unsigned long', 'double' => 'double', 'float' => 'float', 'String' => 'DOMString', 'bool' => 'boolean' ); sub defaultItemFactory { return ( 'conditional' => 0, 'initial' => '', 'type' => 'bool', 'setNeedsStyleRecalcInAllFrames' => 0, ); } my $InCompiler = InFilesCompiler->new(\%defaultParameters, \&defaultItemFactory); my $outputDir = $InCompiler->initializeFromCommandLine(); $InCompiler->compile(\&generateCode); sub generateCode() { my $parsedParametersRef = shift; my $parsedItemsRef = shift; generateSettingsMacrosHeader($parsedItemsRef); generateInternalSettingsIdlFile($parsedItemsRef); generateInternalSettingsHeaderFile($parsedItemsRef); generateInternalSettingsCppFile($parsedItemsRef); } sub generateSettingsMacrosHeader($) { my $parsedItemsRef = shift; my %parsedItems = %{ $parsedItemsRef }; my $outputFile = "$outputDir/SettingsMacros.h"; my %unconditionalSettings = (); my %settingsByConditional = (); for my $settingName (sort keys %parsedItems) { my $conditional = $parsedItems{$settingName}{"conditional"}; if ($conditional) { if (!defined($settingsByConditional{$conditional})) { $settingsByConditional{$conditional} = (); } $settingsByConditional{$conditional}{$settingName} = 1; } else { $unconditionalSettings{$settingName} = 1; } } open my $file, ">$outputFile" or die "Failed to open file: $!"; print $file $InCompiler->license(); # FIXME: Sort by type so bools come last and are bit packed. print $file "#ifndef SettingsMacros_h\n"; print $file "#define SettingsMacros_h\n\n"; printConditionalMacros($file, \%settingsByConditional, $parsedItemsRef); printGettersAndSetters($file, \%unconditionalSettings, \%settingsByConditional, $parsedItemsRef); printMemberVariables($file, \%unconditionalSettings, \%settingsByConditional, $parsedItemsRef); printInitializerList($file, \%unconditionalSettings, \%settingsByConditional, $parsedItemsRef); printSetterBodies($file, \%unconditionalSettings, \%settingsByConditional, $parsedItemsRef); print $file "#endif // SettingsMacros_h\n"; close $file; } sub printConditionalMacros($$$) { my ($file, $settingsByConditionalRef, $parsedItemsRef) = @_; my %parsedItems = %{ $parsedItemsRef }; my %settingsByConditional = %{ $settingsByConditionalRef }; for my $conditional (sort keys %settingsByConditional) { my $preferredConditional = $InCompiler->preferredConditional($conditional); print $file "#if " . $InCompiler->conditionalStringFromAttributeValue($conditional) . "\n"; print $file "#define ${preferredConditional}_SETTINGS_GETTER_AND_SETTERS \\\n"; for my $settingName (sort keys %{ $settingsByConditional{$conditional} }) { printGetterAndSetter($file, $settingName, $parsedItems{$settingName}{"type"}, $parsedItems{$settingName}{"setNeedsStyleRecalcInAllFrames"}); } print $file "// End of ${preferredConditional}_SETTINGS_GETTER_AND_SETTERS\n"; print $file "#define ${preferredConditional}_SETTINGS_NON_BOOL_MEMBER_VARIABLES \\\n"; for my $settingName (sort keys %{ $settingsByConditional{$conditional} }) { my $type = $parsedItems{$settingName}{"type"}; next if $type eq "bool"; print $file " $type m_$settingName; \\\n" } print $file "// End of ${preferredConditional}_SETTINGS_NON_BOOL_MEMBER_VARIABLES\n"; print $file "#define ${preferredConditional}_SETTINGS_BOOL_MEMBER_VARIABLES \\\n"; for my $settingName (sort keys %{ $settingsByConditional{$conditional} }) { next if $parsedItems{$settingName}{"type"} ne "bool"; print $file " bool m_$settingName : 1; \\\n" } print $file "// End of ${preferredConditional}_SETTINGS_BOOL_MEMBER_VARIABLES\n"; print $file "#define ${preferredConditional}_SETTINGS_NON_BOOL_INITIALIZERS \\\n"; for my $settingName (sort keys %{ $settingsByConditional{$conditional} }) { next if $parsedItems{$settingName}{"type"} eq "bool"; printInitializer($file, $settingName, $parsedItemsRef); } print $file "// End of ${preferredConditional}_SETTINGS_NON_BOOL_INITIALIZERS\n"; print $file "#define ${preferredConditional}_SETTINGS_BOOL_INITIALIZERS \\\n"; for my $settingName (sort keys %{ $settingsByConditional{$conditional} }) { next if $parsedItems{$settingName}{"type"} ne "bool"; printInitializer($file, $settingName, $parsedItemsRef); } print $file "// End of ${preferredConditional}_SETTINGS_BOOL_INITIALIZERS\n"; print $file "#define ${preferredConditional}_SETTINGS_SETTER_BODIES \\\n"; for my $settingName (sort keys %{ $settingsByConditional{$conditional} }) { printSetterBody($file, $settingName, $parsedItems{$settingName}{"type"}, $parsedItems{$settingName}{"setNeedsStyleRecalcInAllFrames"}); } print $file "// End of ${preferredConditional}_SETTINGS_SETTER_BODIES\n"; print $file "#else\n"; print $file "#define ${preferredConditional}_SETTINGS_GETTER_AND_SETTERS\n"; print $file "#define ${preferredConditional}_SETTINGS_NON_BOOL_MEMBER_VARIABLES\n"; print $file "#define ${preferredConditional}_SETTINGS_BOOL_MEMBER_VARIABLES\n"; print $file "#define ${preferredConditional}_SETTINGS_NON_BOOL_INITIALIZERS\n"; print $file "#define ${preferredConditional}_SETTINGS_BOOL_INITIALIZERS\n"; print $file "#define ${preferredConditional}_SETTINGS_SETTER_BODIES\n"; print $file "#endif\n"; print $file "\n"; } } sub printGettersAndSetters($$$$) { my ($file, $unconditionalSettingsRef, $settingsByConditionalRef, $parsedItemsRef) = @_; my %parsedItems = %{ $parsedItemsRef }; my %unconditionalSettings = %{ $unconditionalSettingsRef }; my %settingsByConditional = %{ $settingsByConditionalRef }; print $file "#define SETTINGS_GETTERS_AND_SETTERS \\\n"; for my $settingName (sort keys %unconditionalSettings) { printGetterAndSetter($file, $settingName, $parsedItems{$settingName}{"type"}, $parsedItems{$settingName}{"setNeedsStyleRecalcInAllFrames"}); } for my $conditional (sort keys %settingsByConditional) { my $preferredConditional = $InCompiler->preferredConditional($conditional); print $file " ${preferredConditional}_SETTINGS_GETTER_AND_SETTERS \\\n"; } print $file "// End of SETTINGS_GETTERS_AND_SETTERS.\n\n"; } sub printMemberVariables($$$$) { my ($file, $unconditionalSettingsRef, $settingsByConditionalRef, $parsedItemsRef) = @_; my %parsedItems = %{ $parsedItemsRef }; my %unconditionalSettings = %{ $unconditionalSettingsRef }; my %settingsByConditional = %{ $settingsByConditionalRef }; print $file "#define SETTINGS_MEMBER_VARIABLES \\\n"; # We list the bools last so we can bit pack them. for my $settingName (sort keys %unconditionalSettings) { my $type = $parsedItems{$settingName}{"type"}; next if $type eq "bool"; print $file " $type m_$settingName; \\\n" } for my $conditional (sort keys %settingsByConditional) { my $preferredConditional = $InCompiler->preferredConditional($conditional); print $file " ${preferredConditional}_SETTINGS_NON_BOOL_MEMBER_VARIABLES \\\n"; } for my $settingName (sort keys %unconditionalSettings) { next if $parsedItems{$settingName}{"type"} ne "bool"; print $file " bool m_$settingName : 1; \\\n" } for my $conditional (sort keys %settingsByConditional) { my $preferredConditional = $InCompiler->preferredConditional($conditional); print $file " ${preferredConditional}_SETTINGS_BOOL_MEMBER_VARIABLES \\\n"; } print $file "// End of SETTINGS_MEMBER_VARIABLES.\n\n"; } sub setterFunctionName($) { my $settingName = shift; my $setterFunctionName = "set" . $settingName; substr($setterFunctionName, 3, 1) = uc(substr($setterFunctionName, 3, 1)); my @prefixesToUpperCase = ("css", "xss", "ftp", "dom"); foreach my $prefix (@prefixesToUpperCase) { my $prefixLength = length($prefix); if (substr($settingName, 0, $prefixLength) eq $prefix) { substr($setterFunctionName, $prefixLength, $prefixLength) = uc(substr($setterFunctionName, 3, 3)); } } return $setterFunctionName; } sub printGetterAndSetter($$$$) { my ($file, $settingName, $type, $setNeedsStyleRecalcInAllFrames) = @_; my $setterFunctionName = setterFunctionName($settingName); my $webcoreExport = ""; if ($setNeedsStyleRecalcInAllFrames) { $webcoreExport = "WEBCORE_EXPORT"; # Export is only needed if the definition is not in the header. } if (lc(substr($type, 0, 1)) eq substr($type, 0, 1)) { print $file " $type $settingName() const { return m_$settingName; } \\\n"; print $file " $webcoreExport void $setterFunctionName($type $settingName)"; } else { print $file " const $type& $settingName() { return m_$settingName; } \\\n"; print $file " $webcoreExport void $setterFunctionName(const $type& $settingName)"; } if ($setNeedsStyleRecalcInAllFrames) { print $file "; \\\n"; } else { print $file " { m_$settingName = $settingName; } \\\n"; } } sub printInitializerList($$$$) { my ($file, $unconditionalSettingsRef, $settingsByConditionalRef, $parsedItemsRef) = @_; my %parsedItems = %{ $parsedItemsRef }; my %unconditionalSettings = %{ $unconditionalSettingsRef }; my %settingsByConditional = %{ $settingsByConditionalRef }; print $file "#define SETTINGS_INITIALIZER_LIST \\\n"; for my $settingName (sort keys %unconditionalSettings) { next if $parsedItems{$settingName}{"type"} eq "bool"; printInitializer($file, $settingName, $parsedItemsRef); } for my $conditional (sort keys %settingsByConditional) { my $preferredConditional = $InCompiler->preferredConditional($conditional); print $file " ${preferredConditional}_SETTINGS_NON_BOOL_INITIALIZERS \\\n"; } for my $settingName (sort keys %unconditionalSettings) { next if $parsedItems{$settingName}{"type"} ne "bool"; printInitializer($file, $settingName, $parsedItemsRef); } for my $conditional (sort keys %settingsByConditional) { my $preferredConditional = $InCompiler->preferredConditional($conditional); print $file " ${preferredConditional}_SETTINGS_BOOL_INITIALIZERS \\\n"; } print $file "// End of SETTINGS_INITIALIZER_LIST.\n\n"; } sub printInitializer($$$) { my ($file, $settingName, $parsedItemsRef) = @_; my %parsedItems = %{ $parsedItemsRef }; my $initialValue = $parsedItems{$settingName}{"initial"}; my $type = $parsedItems{$settingName}{"type"}; die "Must provide an initial value for $settingName." if ($initialValue eq '' && lc(substr($type, 0, 1)) eq substr($type, 0, 1)); return if ($initialValue eq ''); print $file " , m_$settingName($initialValue) \\\n" } sub printSetterBodies($$$$) { my ($file, $unconditionalSettingsRef, $settingsByConditionalRef, $parsedItemsRef) = @_; my %parsedItems = %{ $parsedItemsRef }; my %unconditionalSettings = %{ $unconditionalSettingsRef }; my %settingsByConditional = %{ $settingsByConditionalRef }; print $file "#define SETTINGS_SETTER_BODIES \\\n"; for my $settingName (sort keys %unconditionalSettings) { printSetterBody($file, $settingName, $parsedItems{$settingName}{"type"}, $parsedItems{$settingName}{"setNeedsStyleRecalcInAllFrames"}); } for my $conditional (sort keys %settingsByConditional) { my $preferredConditional = $InCompiler->preferredConditional($conditional); print $file " ${preferredConditional}_SETTINGS_SETTER_BODIES \\\n"; } print $file "// End of SETTINGS_SETTER_BODIES.\n\n"; } sub printSetterBody($$$$) { my ($file, $settingName, $type, $setNeedsStyleRecalcInAllFrames) = @_; return if (!$setNeedsStyleRecalcInAllFrames); my $setterFunctionName = setterFunctionName($settingName); if (lc(substr($type, 0, 1)) eq substr($type, 0, 1)) { print $file "void Settings::$setterFunctionName($type $settingName) \\\n"; } else { print $file "void Settings::$setterFunctionName(const $type& $settingName) \\\n"; } print $file "{ \\\n"; print $file " if (m_$settingName == $settingName) \\\n"; print $file " return; \\\n"; print $file " m_$settingName = $settingName; \\\n"; print $file " m_page->setNeedsRecalcStyleInAllFrames(); \\\n"; print $file "} \\\n"; } sub enumerateParsedItems($$$) { my ($file, $parsedItemsRef, $visitorFunction) = @_; my %parsedItems = %{ $parsedItemsRef }; for my $settingName (sort keys %parsedItems) { my $type = $parsedItems{$settingName}{"type"}; # FIXME: Learn how to auto-generate code for enumerate types. next if (!defined($webcoreTypeToIdlType{$type})); &$visitorFunction($file, $parsedItemsRef, $settingName) } } sub generateInternalSettingsIdlFile($) { my $parsedItemsRef = shift; my $filename = "$outputDir/InternalSettingsGenerated.idl"; open my $file, ">$filename" or die "Failed to open file: $!"; print $file $InCompiler->license(); print $file "[\n"; print $file " NoInterfaceObject,\n"; print $file "] interface InternalSettingsGenerated {\n"; sub writeIdlSetter($$$) { my ($file, $parsedItemsRef, $settingName) = @_; my %parsedItems = %{ $parsedItemsRef }; my $type = $parsedItems{$settingName}{"type"}; my $idlType = $webcoreTypeToIdlType{$type}; my $setterFunctionName = setterFunctionName($settingName); print $file " void $setterFunctionName(in $idlType $settingName);\n"; }; enumerateParsedItems($file, $parsedItemsRef, \&writeIdlSetter); print $file "};\n"; close $file; } sub generateInternalSettingsHeaderFile($) { my $parsedItemsRef = shift; my %parsedItems = %{ $parsedItemsRef }; my $filename = "$outputDir/InternalSettingsGenerated.h"; open my $file, ">$filename" or die "Failed to open file: $!"; print $file $InCompiler->license(); print $file < #include namespace WebCore { class Page; class InternalSettingsGenerated : public RefCounted { public: explicit InternalSettingsGenerated(Page*); virtual ~InternalSettingsGenerated(); void resetToConsistentState(); EOF sub writeHeaderPrototypes($$$) { my ($file, $parsedItemsRef, $settingName) = @_; my %parsedItems = %{ $parsedItemsRef }; my $type = $parsedItems{$settingName}{"type"}; my $setterFunctionName = setterFunctionName($settingName); $type = "const String&" if $type eq "String"; print $file " void $setterFunctionName($type $settingName);\n"; }; enumerateParsedItems($file, $parsedItemsRef, \&writeHeaderPrototypes); print $file <conditionalStringFromAttributeValue($conditional) . "\n"; } print $file " $type m_$settingName;\n"; if ($conditional) { print $file "#endif\n"; } }; enumerateParsedItems($file, $parsedItemsRef, \&writeBackupMembers); print $file "};\n\n"; print $file "} // namespace WebCore\n"; print $file "#endif // InternalSettingsGenerated_h\n"; close $file; } sub generateInternalSettingsCppFile($) { my $parsedItemsRef = shift; my %parsedItems = %{ $parsedItemsRef }; my $filename = "$outputDir/InternalSettingsGenerated.cpp"; open my $file, ">$filename" or die "Failed to open file: $!"; print $file $InCompiler->license(); print $file <conditionalStringFromAttributeValue($conditional) . "\n"; } print $file " , m_$settingName(page->settings().$settingName())\n"; if ($conditional) { print $file "#endif\n"; } }; enumerateParsedItems($file, $parsedItemsRef, \&writeBackupInitializers); print $file <conditionalStringFromAttributeValue($conditional) . "\n"; } print $file " m_page->settings().$setterFunctionName(m_$settingName);\n"; if ($conditional) { print $file "#endif\n"; } }; enumerateParsedItems($file, $parsedItemsRef, \&writeResetToConsistentState); print $file "}\n"; sub writeSetterFunctions($$$) { my ($file, $parsedItemsRef, $settingName) = @_; my %parsedItems = %{ $parsedItemsRef }; my $type = $parsedItems{$settingName}{"type"}; my $conditional = $parsedItems{$settingName}{"conditional"}; my $setterFunctionName = setterFunctionName($settingName); $type = "const String&" if $type eq "String"; print $file "void InternalSettingsGenerated::$setterFunctionName($type $settingName)\n"; print $file "{\n"; if ($conditional) { print $file "#if " . $InCompiler->conditionalStringFromAttributeValue($conditional) . "\n"; } print $file " m_page->settings().$setterFunctionName($settingName);\n"; if ($conditional) { print $file "#else\n"; print $file " UNUSED_PARAM($settingName);\n"; print $file "#endif\n"; } print $file "}\n\n"; }; enumerateParsedItems($file, $parsedItemsRef, \&writeSetterFunctions); print $file "} // namespace WebCore\n"; close $file; }