Skip to content

Instantly share code, notes, and snippets.

Created May 15, 2014 21:04
Show Gist options
  • Save anonymous/4ea45482121a2c1d8a6b to your computer and use it in GitHub Desktop.
Save anonymous/4ea45482121a2c1d8a6b to your computer and use it in GitHub Desktop.
Preprocess an exim4 config file, expanding .ifdefs etc.
#!/usr/bin/ruby -w
# Won't expand .include!
# Usage on Debian 7: update-exim4.conf && ./preprocess-exim4.conf </var/lib/exim4/config.autogenerated
lines = STDIN.each_line.to_a
# simplify ".if(n)def foo bar" to ".if(n) true/false"
definition = /^([A-Z]\S*)\s*=\s*(.*?)\s*$/
defined = {}
lines.map! do |line|
l = line.strip
if (m = definition.match l)
defined[m[1]] = m[2]
line
elsif (m = /^(\.ifn?)def\s+(.+?)\s*$/.match l)
vars = m[2].split(/\s+/)
m[1] + " " + (vars.any? {|v| defined[v] } ? "true" : "false")
else
line
end
end.compact!
# canonicalize
lines.map! {|l| l.gsub(/^\.ifn false$/, '.if true') }
lines.map! {|l| l.gsub(/^\.ifn true$/, '.if false') }
# remove unused branches
print = []
lines.map! do |line|
case line.strip
when ".if true" then print << true; nil
when ".if false" then print << false; nil
when ".else" then print[-1] = !print[-1]; nil
when ".endif" then print.pop; nil
else line if print.all?
end
end.compact!
# merge split lines
lines = lines.join.gsub("\\\n", "{LINE_CONTINUATION}").each_line.to_a
# rebuild definition cache
defined = {}
lines.each do |line|
l = line.strip
if (m = definition.match l)
defined[m[1]] = m[2]
end
end
# count macro uses
usages = Hash.new 0
defined.keys.each do |k|
usages[k] = lines.join.scan(/\b#{k}\b/).length - 1
end
# expand macros if used only once
lines.map! do |line|
l = line.strip
if (m = definition.match l)
line if usages[m[1]] > 1
else
defined.each_pair do |k, v|
line.gsub!(/\b#{k}\b/, v) if usages[k] == 1
end
line
end
end.compact!
# remove comments
lines.reject!{|line| line.match(/^\s*#/) }
# split merged lines again
lines = lines.join.gsub("{LINE_CONTINUATION}", "\\\n")
puts lines
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment