class PackageConfig

def all_required_packages

def all_required_packages
  (requires_private + requires.reverse).reject do |package|
    @name == package
  end.uniq
end

def cflags

def cflags
  path_flags, other_flags = collect_cflags
  (other_flags + path_flags).join(" ")
end

def cflags_only_I

def cflags_only_I
  collect_cflags[0].join(" ")
end

def clear_configure_args_cache

def clear_configure_args_cache
  @native_pkg_config = nil
  @custom_override_variables = nil
end

def collect_cflags

def collect_cflags
  cflags_set = [declaration("Cflags")]
  cflags_set += all_required_packages.collect do |package|
    self.class.new(package, @options).cflags
  end
  all_cflags = normalize_cflags(Shellwords.split(cflags_set.join(" ")))
  path_flags, other_flags = all_cflags.partition {|flag| /\A-I/ =~ flag}
  path_flags = remove_duplicated_include_paths(path_flags)
  path_flags = path_flags.reject do |flag|
    flag == "-I/usr/include"
  end
  if @msvc_syntax
    path_flags = path_flags.collect do |flag|
      flag.gsub(/\A-I/, "/I")
    end
  end
  [path_flags, other_flags]
end

def collect_libs

def collect_libs
  all_libs = required_packages.collect do |package|
    self.class.new(package, @options).libs
  end
  all_libs = [declaration("Libs")] + all_libs
  all_libs = all_libs.join(" ").gsub(/-([Ll]) /, '\1').split.uniq
  path_flags, other_flags = all_libs.partition {|flag| /\A-L/ =~ flag}
  path_flags = path_flags.reject do |flag|
    /\A-L\/usr\/lib(?:64)?\z/ =~ flag
  end
  if @msvc_syntax
    path_flags = path_flags.collect do |flag|
      flag.gsub(/\A-L/, "/libpath:")
    end
    other_flags = other_flags.collect do |flag|
      if /\A-l/ =~ flag
        "#{$POSTMATCH}.lib"
      else
        flag
      end
    end
  end
  [path_flags, other_flags]
end

def custom_override_variables

def custom_override_variables
  @custom_override_variables ||= with_config("override-variables", "")
end

def declaration(name)

def declaration(name)
  parse_pc if @declarations.nil?
  expand_value(@declarations[name])
end

def description

def description
  declaration("Description")
end

def exist?

def exist?
  not pc_path.nil?
end

def expand_value(value)

def expand_value(value)
  return nil if value.nil?
  value.gsub(/\$\{(#{IDENTIFIER_RE})\}/) do
    variable($1)
  end
end

def guess_default_path

def guess_default_path
  arch_depended_path = Dir.glob('/usr/lib/*/pkgconfig').join(SEPARATOR)
  default_paths = [
    "/usr/local/lib64/pkgconfig",
    "/usr/local/lib/pkgconfig",
    "/usr/local/libdata/pkgconfig",
    "/opt/local/lib/pkgconfig",
    arch_depended_path,
    "/usr/lib64/pkgconfig",
    "/usr/lib/pkgconfig",
    "/usr/libdata/pkgconfig",
    "/usr/X11/lib/pkgconfig",
    "/opt/X11/lib/pkgconfig",
    "/usr/share/pkgconfig",
  ]
  default_path = default_paths.join(SEPARATOR)
  libdir = ENV["PKG_CONFIG_LIBDIR"]
  default_path = [libdir, default_path].join(SEPARATOR) if libdir
  pkg_config = self.class.native_pkg_config
  return default_path unless pkg_config.absolute?
  pkg_config_prefix = pkg_config.parent.parent
  pkg_config_arch_depended_path =
    Dir.glob((pkg_config_prefix + "lib/*/pkgconfig").to_s).join(SEPARATOR)
  [pkg_config_arch_depended_path,
   (pkg_config_prefix + "lib64/pkgconfig").to_s,
   (pkg_config_prefix + "lib/pkgconfig").to_s,
   (pkg_config_prefix + "libdata/pkgconfig").to_s,
   default_path].join(SEPARATOR)
end

def guess_native_pkg_config

def guess_native_pkg_config
  pkg_config = with_config("pkg-config", ENV["PKG_CONFIG"] || "pkg-config")
  pkg_config = Pathname.new(pkg_config)
  unless pkg_config.absolute?
    found_pkg_config = search_pkg_config_from_path(pkg_config)
    pkg_config = found_pkg_config if found_pkg_config
  end
  unless pkg_config.absolute?
    found_pkg_config = search_pkg_config_by_dln_find_exe(pkg_config)
    pkg_config = found_pkg_config if found_pkg_config
  end
  pkg_config
end

def initialize(name, options={})

def initialize(name, options={})
  @name = name
  @options = options
  path = @options[:path] || ENV["PKG_CONFIG_PATH"]
  @paths = [path, guess_default_path].compact.join(SEPARATOR).split(SEPARATOR)
  @paths.unshift(*(@options[:paths] || []))
  @paths = normalize_paths(@paths)
  @msvc_syntax = @options[:msvc_syntax]
  @variables = @declarations = nil
  override_variables = self.class.custom_override_variables
  @override_variables = parse_override_variables(override_variables)
  default_override_variables = @options[:override_variables] || {}
  @override_variables = default_override_variables.merge(@override_variables)
end

def libs

def libs
  path_flags, other_flags = collect_libs
  (path_flags + other_flags).join(" ")
end

def libs_only_L

def libs_only_L
  collect_libs[0].find_all do |arg|
    if @msvc_syntax
      /\A\/libpath:/ =~ arg
    else
      /\A-L/ =~ arg
    end
  end.join(" ")
end

def libs_only_l

def libs_only_l
  collect_libs[1].find_all do |arg|
    if @msvc_syntax
      /\.lib\z/ =~ arg
    else
      /\A-l/ =~ arg
    end
  end.join(" ")
end

def native_pkg_config

def native_pkg_config
  @native_pkg_config ||= guess_native_pkg_config
end

def normalize_cflags(cflags)

def normalize_cflags(cflags)
  normalized_cflags = []
  enumerator = cflags.to_enum
  begin
    loop do
      cflag = enumerator.next
      normalized_cflags << cflag
      case cflag
      when "-I"
        normalized_cflags << enumerator.next
      end
    end
  rescue StopIteration
  end
  normalized_cflags
end

def normalize_paths(paths)

def normalize_paths(paths)
  paths.reject do |path|
    path.empty? or !File.exist?(path)
  end
end

def parse_override_variables(override_variables)

def parse_override_variables(override_variables)
  variables = {}
  override_variables.split(",").each do |variable|
    name, value = variable.split("=", 2)
    variables[name] = value
  end
  variables
end

def parse_pc

def parse_pc
  raise ".pc for #{@name} doesn't exist." unless exist?
  @variables = {}
  @declarations = {}
  File.open(pc_path) do |input|
    input.each_line do |line|
      line = line.gsub(/#.*/, '').strip
      next if line.empty?
      case line
      when /^(#{IDENTIFIER_RE})=/
        @variables[$1] = $POSTMATCH.strip
      when /^(#{IDENTIFIER_RE}):/
        @declarations[$1] = $POSTMATCH.strip
      end
    end
  end
end

def parse_requires(requires)

def parse_requires(requires)
  return [] if requires.nil?
  requires_without_version = requires.gsub(/[<>]?=\s*[\d.]+\s*/, '')
  requires_without_version.split(/[,\s]+/)
end

def pc_path

def pc_path
  @paths.each do |path|
    _pc_path = File.join(path, "#{@name}.pc")
    return _pc_path if File.exist?(_pc_path)
  end
  nil
end

def remove_duplicated_include_paths(path_flags)

def remove_duplicated_include_paths(path_flags)
  path_flags.uniq
end

def required_packages

def required_packages
  requires.reject do |package|
    @name == package
  end.uniq
end

def requires

def requires
  parse_requires(declaration("Requires"))
end

def requires_private

def requires_private
  parse_requires(declaration("Requires.private"))
end

def search_pkg_config_by_dln_find_exe(pkg_config)

def search_pkg_config_by_dln_find_exe(pkg_config)
  begin
    require "dl/import"
  rescue LoadError
    return nil
  end
  dln = Module.new
  dln.module_eval do
    if DL.const_defined?(:Importer)
      extend DL::Importer
    else
      extend DL::Importable
    end
    begin
      dlload RbConfig::CONFIG["LIBRUBY"]
    rescue RuntimeError
      return nil if $!.message == "unknown error"
      return nil if /: image not found\z/ =~ $!.message
      raise
    rescue DL::DLError
      return nil
    end
    begin
      extern "const char *dln_find_exe(const char *, const char *)"
    rescue DL::DLError
      return nil
    end
  end
  path = dln.dln_find_exe(pkg_config.to_s, nil)
  if path.nil? or path.size.zero?
    nil
  else
    Pathname(path.to_s)
  end
end

def search_pkg_config_from_path(pkg_config)

def search_pkg_config_from_path(pkg_config)
  (ENV["PATH"] || "").split(SEPARATOR).each do |path|
    try_pkg_config = Pathname(path) + pkg_config
    return try_pkg_config if try_pkg_config.exist?
  end
  nil
end

def variable(name)

def variable(name)
  parse_pc if @variables.nil?
  expand_value(@override_variables[name] || @variables[name])
end

def version

def version
  declaration("Version")
end