blob: cf5f1af0f16c01d6f47c593f1fc37d0f80fd8137 [file] [log] [blame]
#!/usr/bin/env ruby
#
# Copyright (c) 2017 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 = {
:input => nil,
:outputDirectory => nil
}
optparse = OptionParser.new do |opts|
opts.banner = "Usage: #{File.basename($0)} --input file"
opts.separator ""
opts.on("--input input", "file to generate settings from") { |input| options[:input] = input }
opts.on("--outputDir output", "directory to generate file in") { |output| options[:outputDirectory] = output }
end
optparse.parse!
if !options[:input]
puts optparse
exit -1
end
if !options[:outputDirectory]
options[:outputDirectory] = Dir.getwd
end
FileUtils.mkdir_p(options[:outputDirectory])
parsedSettings = begin
YAML.load_file(options[:input])
rescue ArgumentError => e
puts "Could not parse input file: #{e.message}"
exit(-1)
end
class Setting
attr_accessor :name
attr_accessor :type
attr_accessor :initial
attr_accessor :conditional
attr_accessor :onChange
attr_accessor :getter
def initialize(name, opts)
@name = name
@type = opts["type"] || "bool"
@initial = opts["initial"]
@conditional = opts["conditional"]
@onChange = opts["onChange"]
@getter = opts["getter"]
end
def valueType?
@type != "String" && @type != "URL"
end
def idlType
# FIXME: Add support for more types including enumerate types.
if @type == "int"
"long"
elsif @type == "unsigned"
"unsigned long"
elsif @type == "double"
"double"
elsif @type == "float"
"float"
elsif @type == "String"
"DOMString"
elsif @type == "bool"
"boolean"
else
nil
end
end
def parameterType
if valueType?
@type
else
"const #{@type}&"
end
end
def hasComplexSetter?
@onChange != nil
end
def setterFunctionName
if @name.start_with?("css", "xss", "ftp", "dom", "dns")
"set" + @name[0..2].upcase + @name[3..@name.length]
else
"set" + @name[0].upcase + @name[1..@name.length]
end
end
def getterFunctionName
@getter || @name
end
end
class Conditional
attr_accessor :condition
attr_accessor :settings
attr_accessor :boolSettings
attr_accessor :nonBoolSettings
attr_accessor :settingsWithComplexSetters
def initialize(condition, settings)
@condition = condition
@settings = settings
@boolSettings = @settings.select { |setting| setting.type == "bool" }
@nonBoolSettings = @settings.reject { |setting| setting.type == "bool" }
@settingsWithComplexSetters = @settings.select { |setting| setting.hasComplexSetter? }
end
end
class Settings
attr_accessor :settings
attr_accessor :unconditionalSetting
attr_accessor :unconditionalBoolSetting
attr_accessor :unconditionalNonBoolSetting
attr_accessor :unconditionalSettingWithComplexSetters
attr_accessor :conditionals
def initialize(hash)
@settings = []
hash.each do |name, options|
@settings << Setting.new(name, options)
end
@settings.sort! { |x, y| x.name <=> y.name }
@unconditionalSetting = @settings.reject { |setting| setting.conditional }
@unconditionalBoolSetting = @unconditionalSetting.select { |setting| setting.type == "bool" }
@unconditionalNonBoolSetting = @unconditionalSetting.reject { |setting| setting.type == "bool" }
@unconditionalSettingWithComplexSetters = @unconditionalSetting.select { |setting| setting.hasComplexSetter? }
@conditionals = []
conditionalsMap = {}
@settings.select { |setting| setting.conditional }.each do |setting|
if !conditionalsMap[setting.conditional]
conditionalsMap[setting.conditional] = []
end
conditionalsMap[setting.conditional] << setting
end
conditionalsMap.each do |key, value|
@conditionals << Conditional.new(key, value)
end
@conditionals.sort! { |x, y| x.condition <=> y.condition }
end
def renderToFile(template, file)
template = File.join(File.dirname(__FILE__), template)
output = ERB.new(File.read(template), 0, "-").result(binding)
File.open(file, "w+") do |f|
f.write(output)
end
end
end
settings = Settings.new(parsedSettings)
settings.renderToFile("SettingsTemplates/Settings.h.erb", File.join(options[:outputDirectory], "Settings.h"))
settings.renderToFile("SettingsTemplates/Settings.cpp.erb", File.join(options[:outputDirectory], "Settings.cpp"))
settings.renderToFile("SettingsTemplates/InternalSettingsGenerated.idl.erb", File.join(options[:outputDirectory], "InternalSettingsGenerated.idl"))
settings.renderToFile("SettingsTemplates/InternalSettingsGenerated.h.erb", File.join(options[:outputDirectory], "InternalSettingsGenerated.h"))
settings.renderToFile("SettingsTemplates/InternalSettingsGenerated.cpp.erb", File.join(options[:outputDirectory], "InternalSettingsGenerated.cpp"))