mirror of
https://github.com/darlinghq/darling-WTF.git
synced 2024-11-23 11:59:47 +00:00
247 lines
8.9 KiB
Ruby
247 lines
8.9 KiB
Ruby
|
#!/usr/bin/env ruby
|
||
|
#
|
||
|
# Copyright (c) 2017, 2020 Apple 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 APPLE INC. AND ITS CONTRIBUTORS ``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 ITS 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.
|
||
|
|
||
|
require "fileutils"
|
||
|
require 'erb'
|
||
|
require 'optparse'
|
||
|
require 'yaml'
|
||
|
|
||
|
options = {
|
||
|
:frontend => nil,
|
||
|
:basePreferences => nil,
|
||
|
:debugPreferences => nil,
|
||
|
:experimentalPreferences => nil,
|
||
|
:internalPreferences => nil,
|
||
|
:outputDirectory => nil,
|
||
|
:templates => []
|
||
|
}
|
||
|
optparse = OptionParser.new do |opts|
|
||
|
opts.banner = "Usage: #{File.basename($0)} --frontend <frontend> --base <base> --debug <debug> --experimental <experimental> --internal <internal> --template file"
|
||
|
|
||
|
opts.separator ""
|
||
|
|
||
|
opts.on("--frontend input", "frontend to generate preferences for (WebKit, WebKitLegacy)") { |frontend| options[:frontend] = frontend }
|
||
|
opts.on("--base input", "file to generate preferences from") { |basePreferences| options[:basePreferences] = basePreferences }
|
||
|
opts.on("--debug input", "file to generate debug preferences from") { |debugPreferences| options[:debugPreferences] = debugPreferences }
|
||
|
opts.on("--experimental input", "file to generate experimental preferences from") { |experimentalPreferences| options[:experimentalPreferences] = experimentalPreferences }
|
||
|
opts.on("--internal input", "file to generate internal preferences from") { |internalPreferences| options[:internalPreferences] = internalPreferences }
|
||
|
opts.on("--template input", "template to use for generation (may be specified multiple times)") { |template| options[:templates] << template }
|
||
|
opts.on("--outputDir output", "directory to generate file in") { |outputDir| options[:outputDirectory] = outputDir }
|
||
|
end
|
||
|
|
||
|
optparse.parse!
|
||
|
|
||
|
if !options[:frontend] || !options[:basePreferences] || !options[:debugPreferences] || !options[:experimentalPreferences] || !options[:internalPreferences]
|
||
|
puts optparse
|
||
|
exit -1
|
||
|
end
|
||
|
|
||
|
if !options[:outputDirectory]
|
||
|
options[:outputDirectory] = Dir.getwd
|
||
|
end
|
||
|
|
||
|
FileUtils.mkdir_p(options[:outputDirectory])
|
||
|
|
||
|
def load(path)
|
||
|
parsed = begin
|
||
|
YAML.load_file(path)
|
||
|
rescue ArgumentError => e
|
||
|
puts "ERROR: Could not parse input file: #{e.message}"
|
||
|
exit(-1)
|
||
|
end
|
||
|
if parsed
|
||
|
previousName = nil
|
||
|
parsed.keys.each do |name|
|
||
|
if previousName != nil and previousName > name
|
||
|
puts "ERROR: Input file #{path} is not sorted. First out of order name found is '#{name}'."
|
||
|
exit(-1)
|
||
|
end
|
||
|
previousName = name
|
||
|
end
|
||
|
end
|
||
|
parsed
|
||
|
end
|
||
|
|
||
|
parsedBasePreferences = load(options[:basePreferences])
|
||
|
parsedDebugPreferences = load(options[:debugPreferences])
|
||
|
parsedExperimentalPreferences = load(options[:experimentalPreferences])
|
||
|
parsedInternalPreferences = load(options[:internalPreferences])
|
||
|
|
||
|
|
||
|
class Preference
|
||
|
attr_accessor :name
|
||
|
attr_accessor :opts
|
||
|
attr_accessor :type
|
||
|
attr_accessor :humanReadableName
|
||
|
attr_accessor :humanReadableDescription
|
||
|
attr_accessor :webcoreBinding
|
||
|
attr_accessor :condition
|
||
|
attr_accessor :hidden
|
||
|
attr_accessor :defaultValues
|
||
|
attr_accessor :exposed
|
||
|
|
||
|
def initialize(name, opts, frontend)
|
||
|
@name = name
|
||
|
@opts = opts
|
||
|
@type = opts["type"]
|
||
|
@humanReadableName = '"' + (opts["humanReadableName"] || "") + '"'
|
||
|
@humanReadableDescription = '"' + (opts["humanReadableDescription"] || "") + '"'
|
||
|
@getter = opts["getter"]
|
||
|
@webcoreBinding = opts["webcoreBinding"]
|
||
|
@webcoreName = opts["webcoreName"]
|
||
|
@condition = opts["condition"]
|
||
|
@hidden = opts["hidden"] || false
|
||
|
@defaultValues = opts["defaultValue"][frontend]
|
||
|
@exposed = !opts["exposed"] || opts["exposed"].include?(frontend)
|
||
|
end
|
||
|
|
||
|
def nameLower
|
||
|
if @getter
|
||
|
@getter
|
||
|
elsif @name.start_with?("VP")
|
||
|
@name[0..1].downcase + @name[2..@name.length]
|
||
|
elsif @name.start_with?("CSS", "DOM", "DNS", "FTP", "ICE", "IPC", "PDF", "XSS")
|
||
|
@name[0..2].downcase + @name[3..@name.length]
|
||
|
elsif @name.start_with?("HTTP")
|
||
|
@name[0..3].downcase + @name[4..@name.length]
|
||
|
else
|
||
|
@name[0].downcase + @name[1..@name.length]
|
||
|
end
|
||
|
end
|
||
|
|
||
|
def webcoreNameUpper
|
||
|
if @webcoreName
|
||
|
@webcoreName[0].upcase + @webcoreName[1..@webcoreName.length]
|
||
|
else
|
||
|
@name
|
||
|
end
|
||
|
end
|
||
|
|
||
|
def typeUpper
|
||
|
if @type == "uint32_t"
|
||
|
"UInt32"
|
||
|
else
|
||
|
@type.capitalize
|
||
|
end
|
||
|
end
|
||
|
|
||
|
|
||
|
# WebKitLegacy specific helpers.
|
||
|
|
||
|
def preferenceKey
|
||
|
if @opts["webKitLegacyPreferenceKey"]
|
||
|
@opts["webKitLegacyPreferenceKey"]
|
||
|
else
|
||
|
"WebKit#{@name}"
|
||
|
end
|
||
|
end
|
||
|
|
||
|
def preferenceAccessor
|
||
|
case @type
|
||
|
when "bool"
|
||
|
"_boolValueForKey"
|
||
|
when "uint32_t"
|
||
|
"_integerValueForKey"
|
||
|
when "double"
|
||
|
"_floatValueForKey"
|
||
|
when "String"
|
||
|
"_stringValueForKey"
|
||
|
else
|
||
|
raise "Unknown type: #{@type}"
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
class Preferences
|
||
|
attr_accessor :preferences
|
||
|
|
||
|
def initialize(parsedBasePreferences, parsedDebugPreferences, parsedExperimentalPreferences, parsedInternalPreferences, frontend)
|
||
|
@frontend = frontend
|
||
|
|
||
|
@preferences = []
|
||
|
@preferencesNotDebug = initializeParsedPreferences(parsedBasePreferences)
|
||
|
@preferencesDebug = initializeParsedPreferences(parsedDebugPreferences)
|
||
|
@experimentalFeatures = initializeParsedPreferences(parsedExperimentalPreferences)
|
||
|
@internalFeatures = initializeParsedPreferences(parsedInternalPreferences)
|
||
|
|
||
|
@preferences.sort! { |x, y| x.name <=> y.name }
|
||
|
@preferencesNotDebug.sort! { |x, y| x.name <=> y.name }
|
||
|
@preferencesDebug.sort! { |x, y| x.name <=> y.name }
|
||
|
@experimentalFeatures.sort! { |x, y| x.name <=> y.name }.sort! { |x, y| x.humanReadableName <=> y.humanReadableName }
|
||
|
@internalFeatures.sort! { |x, y| x.name <=> y.name }.sort! { |x, y| x.humanReadableName <=> y.humanReadableName }
|
||
|
|
||
|
@exposedPreferences = @preferences.select { |p| p.exposed }
|
||
|
@exposedPreferencesNotDebug = @preferencesNotDebug.select { |p| p.exposed }
|
||
|
@exposedPreferencesDebug = @preferencesDebug.select { |p| p.exposed }
|
||
|
@exposedExperimentalFeatures = @experimentalFeatures.select { |p| p.exposed }
|
||
|
@exposedInternalFeatures = @internalFeatures.select { |p| p.exposed }
|
||
|
|
||
|
@preferencesBoundToSetting = @preferences.select { |p| !p.webcoreBinding }
|
||
|
@preferencesBoundToDeprecatedGlobalSettings = @preferences.select { |p| p.webcoreBinding == "DeprecatedGlobalSettings" }
|
||
|
@preferencesBoundToRuntimeEnabledFeatures = @preferences.select { |p| p.webcoreBinding == "RuntimeEnabledFeatures" }
|
||
|
|
||
|
@warning = "THIS FILE WAS AUTOMATICALLY GENERATED, DO NOT EDIT."
|
||
|
end
|
||
|
|
||
|
def initializeParsedPreferences(parsedPreferences)
|
||
|
result = []
|
||
|
if parsedPreferences
|
||
|
parsedPreferences.each do |name, options|
|
||
|
if !options["webcoreBinding"] && options["defaultValue"].size != 3
|
||
|
raise "ERROR: Preferences bound to WebCore::Settings must have default values for all frontends: #{name}"
|
||
|
end
|
||
|
if options["defaultValue"].include?(@frontend)
|
||
|
preference = Preference.new(name, options, @frontend)
|
||
|
@preferences << preference
|
||
|
result << preference
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
result
|
||
|
end
|
||
|
|
||
|
def renderTemplate(templateFile, outputDirectory)
|
||
|
resultFile = File.join(outputDirectory, File.basename(templateFile, ".erb"))
|
||
|
tempResultFile = resultFile + ".tmp"
|
||
|
|
||
|
output = ERB.new(File.read(templateFile), 0, "-").result(binding)
|
||
|
File.open(tempResultFile, "w+") do |f|
|
||
|
f.write(output)
|
||
|
end
|
||
|
if (!File.exist?(resultFile) || IO::read(resultFile) != IO::read(tempResultFile))
|
||
|
FileUtils.move(tempResultFile, resultFile)
|
||
|
else
|
||
|
FileUtils.remove_file(tempResultFile)
|
||
|
FileUtils.uptodate?(resultFile, [templateFile]) or FileUtils.touch(resultFile)
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
preferences = Preferences.new(parsedBasePreferences, parsedDebugPreferences, parsedExperimentalPreferences, parsedInternalPreferences, options[:frontend])
|
||
|
|
||
|
options[:templates].each do |template|
|
||
|
preferences.renderTemplate(template, options[:outputDirectory])
|
||
|
end
|