Skip to content

Instantly share code, notes, and snippets.

@tmtm
Last active September 30, 2015 07:27
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tmtm/7f850b0052c23bbc4c5d to your computer and use it in GitHub Desktop.
Save tmtm/7f850b0052c23bbc4c5d to your computer and use it in GitHub Desktop.
Postfixのパラメータ抽出
require 'strscan'
dir, = ARGV
@macro = {}
def extract_value(value)
val = []
ss = StringScanner.new(value)
until ss.eos?
if ss.scan(/\"(([^\"]|\\.)*)\"/)
val.push [ss[1]]
elsif ss.scan(/\'(.)\'/)
val.push [ss[1].ord]
elsif ss.scan(/(\d+)(?=\W|\z)/)
val.push [ss[1].to_i]
elsif ss.scan(/\s+/)
# skip
elsif s = ss.scan(/\w+/)
val.push @macro.key?(s) ? extract_macro_(s) : [s]
else
val.push [ss.scan(/./)]
end
end
[''].product(*val).map(&:join)
end
def extract_macro_(name)
unless @macro.key? name
raise "undefined macro: #{name}"
end
if @macro[name].size == 1
extract_value(@macro[name][0])
else
@macro[name].map{|_| extract_value(_)}.flatten
end
end
def extract_macro(name)
v = extract_macro_(name).uniq
if v.size == 1
v[0]
else
'ENVIRONMENT:'+v.to_s
end
end
def read_macro(line)
if line.chomp =~ /\A#define\s+([A-Za-z0-9_]+)\s+(.+?)(\s*\/\*.*\*\/)?\z/
n, v = $1, $2
if @macro.key? n
@macro[n].push v
@macro[n].uniq!
else
@macro[n] = [v]
end
end
end
["util/sys_defs.h", "global/mail_addr.h", "global/mail_proto.h", "global/server_acl.h", "global/mail_params.h", "global/mail_version.h"].each do |f|
begin
File.read("#{dir}/src/#{f}").gsub(/\/\*.*?\*\//m, '').scan(/^[ \t]*\#define(?:\\[\s\S]|.)*\n/) do |line|
read_macro line.gsub(/\\\n/, '')
end
rescue Errno::ENOENT
# ignore
end
end
Parameter = Struct.new(:name, :type, :default, :min, :max)
@var = {}
@def = {}
@macro.each do |k, v|
@var[k] = extract_macro(k).to_s if k =~ /\AVAR_/
@def[k] = extract_macro(k).to_s if k =~ /\ADEF_/
end
param = {}
(File.read("#{dir}/src/postconf/install_table.h").split(/[,\s]+/)-['']).each_slice(5) do |a|
name, default, _, min, max = a
next unless @var[name]
param[@var[name]] = Parameter.new(@var[name], 'STR', @def[default], min, max)
end
Dir.glob("#{dir}/src/*/*.c").each do |fname|
c = File.read(fname).gsub(/\/\*.*?\*\//m, '')
c.gsub!(/^#.*\n/, '')
c.scan(/^ *(?:static +)?(?:const +)?CONFIG_([0-9A-Z_]+)_TABLE.*?\{(.*?)\}/m) do |type, values|
cnt = type == 'BOOL' || type == 'NBOOL' ? 3 : 5
(values.split(/[,\s]+/)-['']).each_slice(cnt) do |a|
break if a == ['0']
name, default, _, min, max = a
next unless @var[name]
param[@var[name]] = Parameter.new(@var[name], type, @def[default], min, max)
end
end
end
param.keys.sort.each do |k|
p = param[k]
puts [p.name, p.type, p.default, p.min, p.max].join("\t")
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment