# frozen_string_literal: false
##############################################################
# extconf.rb for tcltklib
# release date: 2010-07-30
##############################################################
require 'mkmf'

$CFLAGS << " -DNO_TAINT" if RUBY_VERSION >= '2.7'

TkLib_Config = {}
TkLib_Config['search_versions'] =
  # %w[8.9 8.8 8.7 8.6 8.5 8.4 8.3 8.2 8.1 8.0 7.6 4.2]
  # %w[8.7 8.6 8.5 8.4 8.3 8.2 8.1 8.0]
  # %w[8.7 8.6 8.5 8.4 8.0] # to shorten search steps
  %w[8.6 8.5 8.4 9.0]

TkLib_Config['unsupported_versions'] =
  %w[8.8 8.7]

TkLib_Config['major_nums'] = '90'


##############################################################

TkLib_Config['enable-shared'] = enable_config("shared")


##############################################################
# use old extconf.rb ?
##############################################################
if with_config('tk-old-extconf')
  require File.join(File.dirname(__FILE__), 'old-extconf.rb')
  exit
end


##############################################################
# check configs
##############################################################
($cleanfiles ||= "") << 'config_list'
config_list_file = 'config_list'
config_list_file_source = File.join(File.dirname(__FILE__),'config_list.in')
if !File.exist?(config_list_file) ||
    File.ctime(config_list_file_source) > File.ctime(config_list_file)
  old_config_list_file = config_list_file_source
else
  old_config_list_file = config_list_file
end

current_configs = {'with'=>{}, 'enable'=>{}}

# setup keys by config_list.in
IO.foreach(config_list_file_source){|line|
  line.chomp!
  line.lstrip!
  next if line.empty? || line =~ /^\#/ #
  mode, key, value = line.split(/\s+/, 3)
  value ||= ""
  current_configs[mode][key] = value rescue nil
}

# define current value of keys
IO.foreach(old_config_list_file){|line|
  line.chomp!
  line.lstrip!
  next if line.empty? || line =~ /^\#/ #
  mode, key, value = line.split(/\s+/, 3)
  value ||= ""
  if current_configs[mode] && current_configs[mode].has_key?(key)
    current_configs[mode][key] = value
  end
}

update_flag = false
current_configs['with'].each_key{|key|
  if (value = with_config(key).to_s) != current_configs['with'][key]
    update_flag = true
    current_configs['with'][key] = value
  end
}
current_configs['enable'].each_key{|key|
  if (value = enable_config(key).to_s) != current_configs['enable'][key]
    update_flag = true
    current_configs['enable'][key] = value
  end
}

# update current_configs
if update_flag || !File.exist?(config_list_file)
  open(config_list_file, 'w'){|fobj|
    fobj.print("# values of current configure options (generated by extconf.rb)\n");
    ['with', 'enable'].each{|mode|
      current_configs[mode].each_key{|key|
        fobj.print("#{mode} #{key} #{current_configs[mode][key]}\n")
      }
    }
  }
end

if update_flag
  puts "Configure options for Ruby/Tk may be updated."
  puts "So, delete files which depend on old configs."
  File.delete(*Dir.glob("*.#{CONFIG['DLEXT']}", File::FNM_CASEFOLD))
  File.delete(*Dir.glob("*.#{$OBJEXT}", File::FNM_CASEFOLD))
  File.delete('Makefile') rescue nil

else
  makefile = 'Makefile'
  if File.exist?(makefile) &&
      File.ctime(config_list_file) > File.ctime(makefile)
    # no need to update Makefile
    exit
  end
end


##############################################################
# functions
##############################################################
def is_win32?
  /mswin|mingw|cygwin|bccwin/ =~ RUBY_PLATFORM
end

def is_macosx?
 /darwin/ =~ RUBY_PLATFORM
end

def maybe_64bit?
  /64|universal|s390x/ =~ RUBY_PLATFORM
end

if defined?(Logging.quiet) and Logging.quiet and /--jobserver-fds=/ !~ ENV["MAKEFLAGS"]
  def progress(s)
    print(s)
  end
  def newline
  end
else
  def progress(s)
  end
  def newline
    puts
  end
end

def check_tcltk_version(version)
  return [nil, nil] unless version.kind_of? String

  tclver, tkver = version.split(',')
  tclver = tclver.strip
  return [tclver, tkver.strip] if tkver

  dot = major = minor_dot = minor = plvl_dot = plvl = ext = nil
  if tclver =~ /^(\d)(\.?)(\d)(\.?)(\d*)(.*)$/
    major = $1; minor_dot = $2; minor = $3; plvl_dot = $4; plvl = $5; ext = $6
    dot = ! minor_dot.empty?
    if plvl_dot.empty? && ! plvl.empty?
      minor << plvl
    end
  elsif tclver =~ /^(\d)(\.?)(\d?)(.*)$/
    major = $1; minor_dot = $2; minor = $3; ext = $4
    dot = ! minor_dot.empty?
  else # unknown -> believe user
    return [tclver, tkver]
  end

  # check Tcl7.6 / Tk4.2 ?
  if major == "7" # Tcl7.6 ( not support Tclversion < 7.6 )
    # Tk4.2
    tkver  = "4" + ((dot)? ".": "") + ((minor.empty)? "": "2") + ext
  elsif major == "4" # Tk4.2 ( not support Tkversion < 4.2 )
    # Tcl7.6
    tkver = tclver
    tclver = "7" + ((dot)? ".": "") + ((minor.empty)? "": "6") + ext
  end

  tkver = tclver unless tkver

  [tclver, tkver]
end

def get_shlib_versions(major = 8, minor_max = 9, minor_min = 0, ext = "")
  if tclcfg = TkLib_Config["tclConfig_info"]
    major = tclcfg['TCL_MAJOR_VERSION'].to_i
    minor_min = tclcfg['TCL_MINOR_VERSION'].to_i

  elsif TkLib_Config["tcltkversion"]
    tclver, tkver = TkLib_Config["tcltkversion"]
    if tclver =~ /8\.?(\d)(.*)/
      minor_min = $1.to_i
      ext = $2
    else
      # unsupported version
      return [""]
    end
  end

  # if disable-stubs, version is fixed.
  minor_max = minor_min unless TkLib_Config["tcltk-stubs"]

  vers = []
  minor_max.downto(minor_min){|minor|
    vers << "#{major}.#{minor}#{ext}" unless ext.empty?
    vers << "#{major}.#{minor}"
  }

  vers << ""
end

def get_shlib_path_head
  path_head = []
  path_dirs = []

  if TkLib_Config["ActiveTcl"].kind_of?(String)  # glob path
    # path_head << TkLib_Config["ActiveTcl"]
    path_head.concat Dir.glob(TkLib_Config["ActiveTcl"], File::FNM_CASEFOLD).sort.reverse
    # path_dirs.concat Dir.glob(File.join(TkLib_Config["ActiveTcl"], 'lib'), File::FNM_CASEFOLD).sort.reverse
  end

  if CROSS_COMPILING
  elsif is_win32?
    if TkLib_Config["ActiveTcl"]
      path_head.concat ["c:/ActiveTcl", "c:/Program Files/ActiveTcl",
                        "c:/Program Files (x86)/ActiveTcl"]
    end
    path_head.concat [
      "c:/Tcl", "c:/Program Files/Tcl", "c:/Program Files (x86)/Tcl",
      "/Tcl", "/Program Files/Tcl", "/Program Files (x86)/Tcl"
    ]
    path_head.uniq!
    #path_head.each{|dir| path_dirs << dir.dup if File.directory? dir}
    path_head.each{|dir| path_dirs << File.expand_path(dir) if File.directory? dir}

    # for MinGW
    ["/usr/local/lib64", "/usr/lib64", "/usr/local/lib", "/usr/lib"].each{|dir|
      #path_dirs << dir if File.directory? dir
      path_dirs << File.expand_path(dir) if File.directory? dir
    }
    path_dirs |= ENV['LIBRARY_PATH'].split(';').find_all{|dir| File.directory? dir}.map{|dir| File.expand_path(dir)} if ENV['LIBRARY_PATH']
    path_dirs |= ENV['PATH'].split(';').find_all{|dir| File.directory? dir}.map{|dir| File.expand_path(dir)} if ENV['PATH']

  else
    [
      '/opt', '/pkg', '/share',
      '/usr/local/opt', '/usr/local/pkg', '/usr/local/share', '/usr/local',
      '/usr/opt', '/usr/pkg', '/usr/share', '/usr/contrib', '/usr'
    ].each{|dir|
      next unless File.directory?(dir)

      path_dirs << "#{dir}/lib64" if maybe_64bit?
      path_dirs << "#{dir}/lib"
      path_dirs << "#{dir}" unless Dir.glob("#{dir}/lib*.*", File::FNM_CASEFOLD).empty?

      dirnames = []
      if TkLib_Config["ActiveTcl"]
        dirnames.concat ["ActiveTcl"]
      end
      dirnames.concat ["TclTk","Tcl_Tk","Tcl-Tk"]

      dirnames.each{|name|
        path_dirs << "#{dir}/#{name}" if File.directory?("#{dir}/#{name}")
        path_head << "#{dir}/#{name}" unless Dir.glob("#{dir}/#{name}[-89_]*", File::FNM_CASEFOLD).empty?
      }
    }
  end

  unless TkLib_Config["space-on-tk-libpath"]
    path_head.delete_if{|path| path =~ / /}
    path_dirs.delete_if{|path| path =~ / /}
  end

  [path_head, path_dirs]
end

def find_macosx_framework
  use_framework = is_macosx? && TkLib_Config["ActiveTcl"]

  use_framework ||= (tcl_hdr = with_config("tcl-framework-header"))
  use_framework ||= (tk_hdr  = with_config("tk-framework-header"))
  tcl_hdr = nil unless tcl_hdr.kind_of? String
  tk_hdr  = nil unless tk_hdr.kind_of? String
  TkLib_Config["tcl-framework-header"] = tcl_hdr
  TkLib_Config["tk-framework-header"]  = tk_hdr

  use_framework ||= (tcl_dir = with_config("tcl-framework-dir"))
  tcl_dir = nil unless tcl_dir.kind_of? String
  if !tcl_dir && tcl_hdr
    # e.g. /Library/Frameworks/Tcl.framework/Headers
    #       ==> /Library/Frameworks/Tcl.framework
    tcl_dir = File.dirname(tcl_hdr.strip.chomp('/'))
  end
  TkLib_Config["tcl-framework-dir"] = tcl_dir

  use_framework ||= (tk_dir = with_config("tk-framework-dir"))
  tk_dir = nil unless tk_dir.kind_of? String
  if !tk_dir && tk_hdr
    # e.g. /Library/Frameworks/Tk.framework/Headers
    #       ==> /Library/Frameworks/Tk.framework
    tk_dir = File.dirname(tk_hdr.strip.chomp('/'))
  end
  TkLib_Config["tk-framework-dir"] = tk_dir

  if tcl_dir && !tk_dir
    tk_dir = File.join(File.dirname(tcl_dir), 'Tk.framework')
    TkLib_Config["tk-framework-dir"] = tk_dir
  elsif !tcl_dir && tk_dir
    tcl_dir = File.join(File.dirname(tk_dir), 'Tcl.framework')
    TkLib_Config["tcl-framework-dir"] = tcl_dir
  end
  if tcl_dir && tk_dir
    TkLib_Config["tcltk-framework"] = File.dirname(tcl_dir) unless TkLib_Config["tcltk-framework"]
    return [tcl_dir, tk_dir]
  end

  # framework is disabled?
  if with_config("tcltk-framework") == false ||
      enable_config("tcltk-framework") == false
   return false
  end

  use_framework ||= (framework_dir = with_config("tcltk-framework"))
  if framework_dir.kind_of? String
    TkLib_Config["tcltk-framework"] = framework_dir.strip.chomp('/')
    return [File.join(TkLib_Config["tcltk-framework"], 'Tcl.framework'),
            File.join(TkLib_Config["tcltk-framework"], 'Tk.framework')]
  end

  unless enable_config("tcltk-framework", use_framework) ||
      enable_config("mac-tcltk-framework", use_framework)
    TkLib_Config["tcltk-framework"] = false
    return false
  end

  paths = [
    #"~/Library/Frameworks",
    "/Library/Frameworks",
    "/Network/Library/Frameworks", "/System/Library/Frameworks"
  ]
  paths.reverse! unless TkLib_Config["ActiveTcl"] # system has higher priority

  paths.map{|dir| dir.strip.chomp('/')}.each{|dir|
    next unless File.exist?(File.join(dir, "Tcl.framework", "Headers"))
    next unless File.directory?(tcldir = File.join(dir, "Tcl.framework"))
    next unless File.exist?(File.join(dir, "Tk.framework", "Headers"))
    next unless File.directory?(tkdir  = File.join(dir, "Tk.framework"))
    TkLib_Config["tcltk-framework"] = dir
    return [tcldir, tkdir]
  }

  nil
end

def collect_tcltk_defs(tcl_defs_str, tk_defs_str)
  conflicts = [
    'PACKAGE_NAME', 'PACKAGE_TARNAME', 'PACKAGE_VERSION',
    'PACKAGE_STRING', 'PACKAGE_BUGREPORT'
  ]

  begin
    # Ruby 1.9.x or later
    arch_config_h = RbConfig.expand($arch_hdrdir + "/ruby/config.h")
    if File.exist?(arch_config_h)
      keys = []
      IO.foreach(arch_config_h){|line|
        if line =~ /^#define +([^ ]+)/
            keys << $1
        end
      }
      conflicts = keys
    end
  rescue
    # ignore, use default
  end

  if tcl_defs_str
    tcl_defs = tcl_defs_str.split(/(?:\A|\s)\s*-D/).map{|s|
      s =~ /^([^=]+)(.*)$/
      [$1, $2]
    }
  else
    tcl_defs = []
  end

  if tk_defs_str
    tk_defs = tk_defs_str.split(/(?:\A|\s)\s*-D/).map{|s|
      s =~ /^([^=]+)(.*)$/
      [$1, $2]
    }
  else
    tk_defs = []
  end

  defs = tcl_defs | tk_defs

  defs.delete_if{|name,value|
    conflicts.include?(name) ||
      ( (vtcl = tcl_defs.assoc(name)) && (vtk = tk_defs.assoc(name)) &&
          vtcl != vtk )
  }

  defs.map{|ary| /\S/ =~ (s = ary.join('')) and "-D" << s.strip}.compact
end

def parse_tclConfig(file)
  # check tclConfig.sh/tkConfig.sh
  tbl = Hash.new{|h,k| h[k] = ""}
  return tbl unless file
  IO.foreach(file){|line|
    line.strip!
    next if line !~ /^([^\#=][^=]*)=(['"]|)(.*)\2$/
    key, val = $1, $3
    tbl[key] = val.gsub(/\$\{([^}]+)\}/){|s|
      subst = $1
      (tbl[subst])? tbl[subst]: s
    } rescue nil
  }
  tbl
end

def get_libpath(lib_flag, lib_spec)
  # get libpath from {TCL,Tk}_LIB_FLAG and {TCL,Tk}_LIB_SPEC
  lib_spec.gsub(/(#{lib_flag}|-L)/, "").strip
end

def get_tclConfig_dirs
  config_dir = []

  if CROSS_COMPILING
  elsif is_win32?
    if TkLib_Config["ActiveTcl"]
      dirs = []
      if TkLib_Config["ActiveTcl"].kind_of?(String)
        dirs << File.join(TkLib_Config["ActiveTcl"], 'lib')
      end
      dirs.concat [
        "c:/ActiveTcl*/lib", "c:/Tcl*/lib",
        "c:/Program Files*/ActiveTcl*/lib", "c:/Program Files*/Tcl*/lib",
        "/ActiveTcl*/lib", "/Tcl*/lib",
        "/Program Files*/ActiveTcl*/lib", "/Program Files*/Tcl*/lib"
      ]
    else
      dirs = [
        "c:/Tcl*/lib", "c:/Program Files*/Tcl*/lib",
        "/Tcl*/lib", "/Program Files*/Tcl*/lib"
      ]
    end
    dirs = dirs.collect{|d| Dir.glob(d, File::FNM_CASEFOLD)}.flatten.uniq

    dirs |= ENV['LIBRARY_PATH'].split(';')  if ENV['LIBRARY_PATH']
    dirs |= ENV['PATH'].split(';')  if ENV['PATH']

    exeext = RbConfig::CONFIG['EXEEXT']
    ENV['PATH'].split(File::PATH_SEPARATOR).each{|dir|
      dir.tr!(File::ALT_SEPARATOR, File::SEPARATOR) if File::ALT_SEPARATOR
      next if Dir.glob(File.join(dir, "{tclsh,wish}*#{exeext}"), File::FNM_CASEFOLD).empty?
      dirs << File.expand_path(File.join(dir, '..', 'lib'))
      dirs << dir
      # dirs << File.expand_path(File.join(dir, '..'))
    }

    unless TkLib_Config["space-on-tk-libpath"]
      dirs.delete_if{|path| path =~ / /}
    end

    config_dir.concat(dirs.zip(dirs))

  else
    if framework = find_macosx_framework()
      config_dir.unshift(framework)
    end

    if activeTcl = TkLib_Config['ActiveTcl']
      # check latest version at first
      if is_macosx?
        base = File.expand_path(activeTcl)
        config_dir << [
          File.join(base, 'Tcl.framework'), File.join(base, 'Tk.framework')
        ]

        config_dir << [
          File.join(base, 'Tcl.framework', 'Versions', 'Current'),
          File.join(base, 'Tk.framework', 'Versions', 'Current')
        ]

        Dir.glob(File.join(base, 'Tcl.framework',
                           'Versions', '*')).sort.reverse.each{|dir|
          next if dir =~ /Current/
          config_dir << [dir, dir.gsub(/Tcl/, 'Tk')]
        }
      else
        config_dir.concat(Dir.glob(File.join(activeTcl, 'lib'), File::FNM_CASEFOLD).sort.reverse)
      end
    end

    config_dir << RbConfig::CONFIG['libdir']

    ((maybe_64bit?)? ['lib64', 'lib']: ['lib']).each{|dir|
      config_dir.concat [
        File.join(RbConfig::CONFIG['exec_prefix'], dir),
        File.join(RbConfig::CONFIG['prefix'], dir),
        "/usr/local/opt/#{dir}", "/usr/local/pkg/#{dir}",
        "/usr/local/share/#{dir}", "/usr/local/#{dir}",
        "/usr/opt/#{dir}", "/usr/pkg/#{dir}", "/usr/share/#{dir}",
        "/usr/contrib/#{dir}", "/usr/#{dir}"
      ]
    }

    config_dir.concat [
      '/opt', '/pkg', '/share',
      '/usr/local/opt', '/usr/local/pkg', '/usr/local/share', '/usr/local',
      '/usr/opt', '/usr/pkg', '/usr/share', '/usr/contrib', '/usr'
    ].map{|dir|
      Dir.glob(dir + "/{tcltk,tcl,tk}[#{TkLib_Config['major_nums']}]*/lib",
               File::FNM_CASEFOLD)
      Dir.glob(dir + "/{tcltk,tcl,tk}[#{TkLib_Config['major_nums']}]*",
               File::FNM_CASEFOLD)
      Dir.glob(dir + '/{tcltk,tcl,tk}/lib', File::FNM_CASEFOLD)
      Dir.glob(dir + '/{tcltk,tcl,tk}', File::FNM_CASEFOLD)
    }.flatten!

    exeext = RbConfig::CONFIG['EXEEXT']
    ENV['PATH'].split(File::PATH_SEPARATOR).each{|dir|
      dir.tr!(File::ALT_SEPARATOR, File::SEPARATOR) if File::ALT_SEPARATOR
      next if Dir.glob(File.join(dir, "{tclsh,wish}*#{exeext}"), File::FNM_CASEFOLD).empty?
      config_dir << File.expand_path(File.join(dir, '..', 'lib'))
    }

    # for MacOS X
    paths = [
      #"~/Library/Tcl",
      "/Library/Tcl", "/Network/Library/Tcl", "/System/Library/Tcl"
    ]
    paths.reverse! unless TkLib_Config["ActiveTcl"]

    paths.each{|path|
      config_dir << path
      config_dir.concat(Dir.glob(File.join(path, '{tcl,tk}*'), File::FNM_CASEFOLD).sort.reverse.find_all{|d| File.directory?(d)})
    }

    paths = [
      #"~/Library/Frameworks",
      "/Library/Frameworks",
      "/Network/Library/Frameworks", "/System/Library/Frameworks"
    ]
    paths.reverse! unless TkLib_Config["ActiveTcl"]

    paths.each{|frmwk|
      base = File.expand_path(frmwk)
      config_dir << [
        File.join(base, 'Tcl.framework'), File.join(base, 'Tk.framework')
      ]

      config_dir << [
        File.join(base, 'Tcl.framework', 'Versions', 'Current'),
        File.join(base, 'Tk.framework', 'Versions', 'Current')
      ]

      Dir.glob(File.join(base, 'Tcl.framework',
                         'Versions', '*')).sort.reverse.each{|dir|
        next if dir =~ /Current/
        config_dir << [dir, dir.gsub(/Tcl/, 'Tk')]
      }
    }
  end

  config_dir
end

def get_ext_list()
  exts = [CONFIG['DLEXT']]
  exts.concat %w(dll) if is_win32?
  exts.concat %w(bundle dylib) if is_macosx?

  if TkLib_Config["tcltk-stubs"] || TkLib_Config['enable-shared'] == false
    exts.unshift "lib" if is_win32?
    exts.unshift "a"
    exts.unshift CONFIG['LIBEXT']
  end

  if is_win32?
    exts.map!{|ext| [ext.downcase, ext.upcase]}.flatten!
  end

  exts
end

def libcheck_for_tclConfig(tcldir, tkdir, tclconf, tkconf)
  tcllib_ok = tklib_ok = false

  if TkLib_Config["tcltk-stubs"]
    stub = "stub"
    tclfunc = "Tcl_InitStubs"
    tkfunc  = "Tk_InitStubs"
  else
    stub = ""
    tclfunc = "Tcl_FindExecutable"
    tkfunc  = "Tk_Init"
  end

  incflags = ($INCFLAGS ||= "").dup
  libpath = ($LIBPATH ||= []).dup
  libs_param = ($libs ||= "").dup
  tcllibs = nil
  mkmf_param = nil

  tclver, tkver = TkLib_Config["tcltkversion"]
  exts = "(" + get_ext_list.join('|') + ")"

  if tclver
    tcl_glob = "*tcl#{stub}#{tclver}.*"
    tcl_regexp = /(tcl#{stub}#{tclver}.*)\.(#{exts})/
  elsif tclconf
    tcl_glob = "*tcl#{stub}#{tclconf['TCL_MAJOR_VERSION']}{.,}#{tclconf['TCL_MINOR_VERSION']}*.*"
    tcl_regexp = /(tcl#{stub}#{tclconf['TCL_MAJOR_VERSION']}(?:\.|)#{tclconf['TCL_MINOR_VERSION']}.*)\.(#{exts})/
  end
  if tkver
    tk_glob = "*tk#{stub}#{tkver}.*"
    tk_regexp = /(tk#{stub}#{tkver}.*)\.(#{exts})/
  elsif tkconf
    tk_glob = "*tk#{stub}#{tkconf['TK_MAJOR_VERSION']}{.,}#{tkconf['TK_MINOR_VERSION']}*.*"
    tk_regexp = /((?:tcl#{tclconf['TCL_MAJOR_VERSION']})?tk#{stub}#{tkconf['TK_MAJOR_VERSION']}\.?#{tkconf['TK_MINOR_VERSION']}.*)\.#{exts}/
  end

  tcllib_ok ||= !tclconf || Dir.glob(File.join(tcldir, tcl_glob), File::FNM_CASEFOLD).find{|file|
    if file =~ tcl_regexp
      libname = $1
      ext = $2.downcase
      begin
        $INCFLAGS = incflags.dup << " " << tclconf["TCL_INCLUDE_SPEC"]
        #puts "check #{file} #{$1} #{tclfunc} #{tcldir}"
        #find_library($1, tclfunc, tcldir)
        if (tclconf && tclconf["TCL_SHARED_BUILD"] == "0") ||
            (ext != CONFIG['DLEXT'] && ext == CONFIG['LIBEXT']) || ext == "a"
          # static link
          tcllibs = $libs + " -DSTATIC_BUILD " + file.quote

          # FIX ME: avoid pathname trouble (fail to find) on MinGW.
          #   e.g. TCL_INCLUDE_SPEC describes "-I/usr/local/include",
          #        but compiler can find "-IC:/msys/1.0/local/include" only.
          $INCFLAGS << " -I" << File.join(File.dirname(File.dirname(file)),"include") if is_win32?
        else
          tcllibs = append_library($libs, libname)
          tcllibs = "#{libpathflag([tcldir])} #{tcllibs}"

          # FIX ME: avoid pathname trouble (fail to find) on MinGW.
          $INCFLAGS << " -I" << File.join(File.dirname(tcldir),"include") if is_win32?
        end

        $LIBPATH = libpath | [tcldir]
        try_func(tclfunc, tcllibs, ["tcl.h"]) ||
          ( try_func(tclfunc, tcllibs << " " << tclconf['TCL_LIBS'], ["tcl.h"]) if tclconf['TCL_LIBS'] )

      ensure
        mkmf_param = {
          'PATH' => file,
          'LIBNAME' => libname,
          'libs' => tcllibs.dup,
          'INCFLAGS' => $INCFLAGS.dup,
          'LIBPATH' => $LIBPATH.dup,
        }
        $LIBPATH = libpath.dup
        $libs = libs_param.dup
      end
    end
  }
  tclconf['MKMF_PARAMS'] = mkmf_param if tclconf && tcllib_ok

  tklib_ok ||= !tkconf || Dir.glob(File.join(tkdir, tk_glob), File::FNM_CASEFOLD).find{|file|
    if file =~ tk_regexp
      libname = $1
      ext = $2.downcase
      begin
        #puts "check #{file} #{$1} #{tkfunc} #{tkdir}"
        # find_library($1, tkfunc, tkdir)
        if (tkconf && tkconf["TCL_SHARED_BUILD"] == "0") ||
            (ext != CONFIG['DLEXT'] && ext == CONFIG['LIBEXT']) || ext == "a"
          # static link
          tklibs = " -DSTATIC_BUILD " + file.quote

          # FIX ME: avoid pathname trouble (fail to find) on MinGW.
          $INCFLAGS << " -I" << File.join(File.dirname(File.dirname(file)),"include") if is_win32?
        else
          tklibs = append_library("", libname)
          #tklibs = append_library("", $1)
          tklibs = "#{libpathflag([tkdir])} #{tklibs}"

          # FIX ME: avoid pathname trouble (fail to find) on MinGW.
          $INCFLAGS << " -I" << File.join(File.dirname(tcldir),"include") if is_win32?
        end

        tklibs << " " <<  tcllibs if tcllibs
        tmp_tklibs = tklibs.dup
        $LIBPATH = libpath | [tkdir]
        try_func(tkfunc, tklibs, ["tcl.h", "tk.h"]) ||
          ( try_func(tkfunc, tklibs << " " << tkconf['TK_LIBS'], ["tcl.h", "tk.h"]) if tkconf['TK_LIBS'] ) ||
          ( try_func(tkfunc, (tklibs = tmp_tklibs.dup) << " " << tkconf['TK_XLIBSW'], ["tcl.h", "tk.h"]) if tkconf['TK_XLIBSW'] ) ||
          ( try_func(tkfunc, tklibs << " " << tkconf['TK_LIBS'], ["tcl.h", "tk.h"]) if tkconf['TK_LIBS'] )

      ensure
        mkmf_param = {
          'PATH' => file,
          'LIBNAME' => libname,
          'libs' => tklibs.dup,
          'INCFLAGS' => $INCFLAGS.dup,
          'LIBPATH' => $LIBPATH.dup,
        }
        $LIBPATH = libpath.dup
        $libs = libs_param.dup
      end
    end
  }

  $INCFLAGS = incflags.dup
  tkconf['MKMF_PARAMS'] = mkmf_param if tkconf && tklib_ok

  [tcllib_ok, tklib_ok]
end

def search_tclConfig(*paths) # libdir list or [tcl-libdir|file, tk-libdir|file]
  TkLib_Config["tclConfig_paths"] = []

  paths.compact!
  if paths.empty?
    config_dir = get_tclConfig_dirs
  elsif paths.length == 1 && !paths[0][0] && !paths[0][1]
    config_dir = get_tclConfig_dirs.map{|dir|
      if dir.kind_of? Array
        [ (paths[0][0] == false)? nil: dir[0],
          (paths[0][1] == false)? nil: dir[1] ]
      else
        [ (paths[0][0] == false)? nil: dir,
          (paths[0][1] == false)? nil: dir ]
      end
    }
  else
    # fixed tclConfig
    config_dir = []
    paths.each{|path|
      if path.kind_of?(Array)
        config_dir << path
      else
        dirs = Dir.glob(path, File::FNM_CASEFOLD)
        config_dir.concat(dirs.zip(dirs))
      end
    }
  end

  tclver, tkver = TkLib_Config['tcltkversion']
  if tclver && tclver =~ /^\D*(\d)\.?(\d)?/  # ignore PATCH_LEVEL
    tclver_major = $1
    tclver_minor = $2
  else
    tclver_major = nil
    tclver_minor = nil
  end
  if tkver && tkver =~ /^\D*(\d)\.?(\d)?/  # ignore PATCH_LEVEL
    tkver_major = $1
    tkver_minor = $2
  else
    tkver_major = nil
    tkver_minor = nil
  end

  conf = nil
  progress_flag = false

  config_dir.uniq!
  config_dir.map{|dir|
    if dir.kind_of? Array
      [ (dir[0])? dir[0].strip.chomp('/'): nil,
        (dir[1])? dir[1].strip.chomp('/'): nil ]
    else
      dir.strip.chomp('/')
    end
  }.each{|dir|
    progress("."); progress_flag = true
    # print("check #{dir} ==>");
    if dir.kind_of? Array
      tcldir, tkdir = dir
    else
      tcldir = tkdir = dir
    end

    tails = ['Config-shared.sh', 'config-shared.sh', 'Config.sh', 'config.sh']

    if tcldir
      if File.file?(tcldir)
        tclcfg_files = [tcldir] * tails.length
      else
        tclcfg_files = tails.map{|f| File.join(tcldir, 'tcl' << f)}
      end
    else
      tclcfg_files = [nil] * tails.length
    end

    if tkdir
      if File.file?(tkdir)
        tkcfg_files = [tkdir] * tails.length
      else
        tkcfg_files = tails.map{|f| File.join(tkdir, 'tk' << f)}
      end
    else
      tkcfg_files = [nil] * tails.length
    end

    tclcfg_files.zip(tkcfg_files).map{|tclpath, tkpath|
      [ (tclpath && File.exist?(tclpath))? File.expand_path(tclpath): tclpath,
        (tkpath && File.exist?(tkpath))? File.expand_path(tkpath): tkpath ]
    }.uniq.each{|tclpath, tkpath|
      next if tclpath && !File.exist?(tclpath)
      next if tkpath && !File.exist?(tkpath)

      # parse tclConfig.sh/tkConfig.sh
      tclconf = (tclpath)? parse_tclConfig(tclpath): nil
      if tclconf
        if tclver && ((tclver_major && tclver_major != tclconf['TCL_MAJOR_VERSION']) || (tclver_minor && tclver_minor != tclconf['TCL_MINOR_VERSION']))
          print("\n") if progress_flag
          puts "Ignore \"#{tclpath}\" (unmatch with configured version)."
          progress_flag = false
          next
        end
        if TkLib_Config['unsupported_versions'].find{|ver| ver == "#{tclconf['TCL_MAJOR_VERSION']}.#{tclconf['TCL_MINOR_VERSION']}"}
          print("\n") if progress_flag
          puts "Ignore \"#{tclpath}\" (unsupported version of Tcl/Tk)."
          progress_flag = false
          next
        end
      end

      tkconf = (tkpath)? parse_tclConfig(tkpath): nil
      if tkconf
        if tkver && ((tkver_major && tkver_major != tkconf['TK_MAJOR_VERSION']) || (tkver_minor && tkver_minor != tkconf['TK_MINOR_VERSION']))
          print("\n") if progress_flag
          puts "Ignore \"#{tkpath}\" (unmatch with configured version)."
          progress_flag = false
          next
        end
        if TkLib_Config['unsupported_versions'].find{|ver| ver == "#{tkconf['TK_MAJOR_VERSION']}.#{tkconf['TK_MINOR_VERSION']}"}
          print("\n") if progress_flag
          puts "Ignore \"#{tkpath}\" (unsupported version of Tcl/Tk)."
          progress_flag = false
          next
        end
      end

      # nativethread check
      if !TkLib_Config["ruby_with_thread"]
        if tclconf
          if tclconf['TCL_THREADS'] == '1'
            puts "\nWARNING: found #{tclpath.inspect}, but it WITH nativethread-support under ruby WITHOUT nativethread-support. So, ignore it."
            TkLib_Config["tcl-NG-path"] << File.dirname(tclpath)
            next
          end
        else
          puts "\nWARNING: When not refer tclConfig.sh, cannot check native-thread support on Tcl/Tk libraries. Ruby, which is used now, does NOT support native-thread. So, if Tcl/Tk libraries support native-thread, it will NOT work properly."
        end
      end

      # find tclConfig.sh & tkConfig.sh
      conf = [tclconf, tkconf] unless conf

      # check Tcl library
      if is_macosx? && TkLib_Config["tcltk-framework"]
        # if use framework, not check (believe it is installed properly)
        tcllib_ok = tklib_ok = true
      else
        tcllib_ok, tklib_ok =
          libcheck_for_tclConfig((tclpath)? File.dirname(tclpath): nil,
                                 (tkpath)? File.dirname(tkpath): nil,
                                 tclconf, tkconf)
      end

      unless tcllib_ok && tklib_ok
        unless tcllib_ok
          puts "\nWARNING: found #{tclpath.inspect}, but cannot find valid Tcl library for the tclConfig.sh. So, ignore it."
          TkLib_Config["tcl-NG-path"] << File.dirname(tclpath)
        end
        unless tklib_ok
          puts "\nWARNING: found #{tkpath.inspect}, but cannot find valid Tk library for the tkConfig.sh. So, ignore it."
          TkLib_Config["tk-NG-path"] << File.dirname(tkpath)
        end
        next
      end

      #return [tclpath, tkpath]
      # print(" #{[tclpath, tkpath].inspect}");
      TkLib_Config["tclConfig_paths"] << [tclpath, tkpath]
    }

    # print("\n");
  }

  if is_macosx? && TkLib_Config["tcltk-stubs"]
    CONFIG['LDSHARED'] << " -Xlinker -bind_at_load"
    if config_string('LDSHAREDXX')
      config_string('LDSHAREDXX') << " -Xlinker -bind_at_load"
    end
  end

  if TkLib_Config["tclConfig_paths"].empty?
    [nil, nil]
  else
    # find tclConfig.sh and tkConfig.sh
    TkLib_Config["tclConfig_info"], TkLib_Config["tkConfig_info"] = conf
    TkLib_Config["tclConfig_paths"][0]
  end
end

def get_tclConfig(tclConfig_file, tkConfig_file, tclConfig_dir, tkConfig_dir)
  use_tclConfig = tclConfig_file != false && tclConfig_dir != false
  use_tkConfig  = tkConfig_file  != false && tkConfig_dir  != false

  unless use_tclConfig || use_tkConfig
    puts("Don't use [tclConfig.sh, tkConfig.sh]")
    return [nil, nil]
  end

  tclConfig_file = nil unless tclConfig_file.kind_of? String
  tkConfig_file = nil unless tkConfig_file.kind_of? String
  tclConfig_dir = nil unless tclConfig_dir.kind_of? String
  tkConfig_dir = nil unless tkConfig_dir.kind_of? String

  if use_tclConfig && !tclConfig_dir
    if tclConfig_file
      tclConfig_dir = File.dirname(tclConfig_file)
    elsif tkConfig_dir
      tclConfig_dir = tkConfig_dir
    end
  end
  if use_tkConfig && !tkConfig_dir
    if tkConfig_file
      tkConfig_dir = File.dirname(tkConfig_file)
    elsif tclConfig_dir
      tkConfig_dir = tclConfig_dir
    end
  end
  tkConfig_dir ||= tclConfig_dir

  if use_tclConfig
    TkLib_Config["tclConfig-file"] = tclConfig_file
    TkLib_Config["tclConfig-dir"] = tclConfig_dir
  else
    tclConfig_file = false
    tclConfig_dir = false
  end
  if use_tkConfig
    TkLib_Config["tkConfig-file"] = tkConfig_file
    TkLib_Config["tkConfig-dir"] = tkConfig_dir
  else
    tkConfig_file = false
    tkConfig_dir = false
  end

  print ("Don't use tclConfig.sh (specified by configure option).\n") unless use_tclConfig
  print ("Don't use tkConfig.sh (specified by configure option).\n") unless use_tkConfig
  print("Search ")
  print("tclConfig.sh", (tclConfig_dir)? " (in #{tclConfig_dir})": "") if use_tclConfig
  print((use_tclConfig)? " and ": "", "tkConfig.sh", (tkConfig_dir)? " (in #{tkConfig_dir})": "") if use_tkConfig
  print(".")

  if tclConfig_dir || tkConfig_dir || !use_tclConfig || !use_tkConfig
    tclConfig, tkConfig =
      search_tclConfig([ ((tclConfig_file)? tclConfig_file: tclConfig_dir),
                         ((tkConfig_file)?  tkConfig_file:  tkConfig_dir) ])
  else
    tclConfig, tkConfig = search_tclConfig()
  end
  print("\n")
  # TclConfig_Info = TkLib_Config["tclConfig_info"]
  # TkConfig_Info  = TkLib_Config["tkConfig_info"]

  if tclConfig || tkConfig
    dirs = TkLib_Config["tclConfig_paths"].map{|tclpath, tkpath|
      [ (tclpath)? File.dirname(tclpath): nil,
        (tkpath)? File.dirname(tkpath): nil ]
    }
    dirs |= dirs
    puts("Valid [tclConfig.sh, tkConfig.sh] are found in #{dirs.inspect}")
    puts("Use [tclConfig.sh, tkConfig.sh] == #{[tclConfig, tkConfig].inspect}")
    $LIBPATH ||= []
    $LIBPATH |= [File.dirname(tclConfig)] if tclConfig
    $LIBPATH |= [File.dirname(tkConfig)]  if tkConfig
    #TkLib_Config["tclConfig_paths"].each{|tclcfg, tkcfg|
    #  $LIBPATH |= [File.dirname(tclcfg)] | [File.dirname(tkcfg)]
    #}
  else
    puts("Fail to find [tclConfig.sh, tkConfig.sh]")
  end

  [tclConfig, tkConfig]
end

def check_tcl_NG_path(path_list)
  path_list.find_all{|path| not TkLib_Config["tcl-NG-path"].include?(path) }
end

def check_tk_NG_path(path_list)
  path_list.find_all{|path| not TkLib_Config["tk-NG-path"].include?(path) }
end

def check_NG_path(path_list)
  path_list.find_all{|path|
    not (TkLib_Config["tcl-NG-path"].include?(path) &&
         TkLib_Config["tk-NG-path"].include?(path))
  }
end

def check_shlib_search_path(paths)
  if !paths || paths.empty?
    path_list = []

    #if TkLib_Config["ActiveTcl"]
    #  path_list.concat Dir.glob(TkLib_Config["ActiveTcl"], File::FNM_CASEFOLD).sort.reverse
    #end
    if TkLib_Config["ActiveTcl"].kind_of?(String)  # glob path
      path_list.concat Dir.glob(TkLib_Config["ActiveTcl"], File::FNM_CASEFOLD).sort.reverse
    end

    vers = get_shlib_versions
    path_head, path_dirs = get_shlib_path_head

    path_list.concat vers.map{|ver|
      path_head.map{|head|
        if ver.empty?
          head + "/lib"
        else
          dirs = []

          if Dir.glob(head, File::FNM_CASEFOLD).find{|dir| dir == head}
            dirs << head + "/lib"
          end

          if !Dir.glob(head + "-*", File::FNM_CASEFOLD).empty?
            dirs << head + "-#{ver}/lib" if !Dir.glob(head + "-[89].*", File::FNM_CASEFOLD).empty?
            dirs << head + "-#{ver.delete('.')}/lib" if !Dir.glob(head + "-[89][0-9]*", File::FNM_CASEFOLD).empty?
          end

          if !Dir.glob(head + "[_-]*", File::FNM_CASEFOLD).empty?
            dirs << head + "_#{ver}/lib" if !Dir.glob(head + "_[89].*", File::FNM_CASEFOLD).empty?
            dirs << head + "-#{ver}/lib" if !Dir.glob(head + "-[89].*", File::FNM_CASEFOLD).empty?
            dirs << head + "_#{ver.delete('.')}/lib" if !Dir.glob(head + "_[89][0-9]*", File::FNM_CASEFOLD).empty?
            dirs << head + "-#{ver.delete('.')}/lib" if !Dir.glob(head + "-[89][0-9]*", File::FNM_CASEFOLD).empty?
          end

          dirs
        end
      }
    }.flatten!

    path_list.concat path_dirs

  else
    # paths is a string with PATH environment style
    path_list = paths.split((is_win32?)? ';': ':')
  end

  path_list = check_NG_path(path_list)
  path_list.map!{|path| path.strip}

  if !CROSS_COMPILING and (is_win32? || is_macosx?)
    # exist-dir only
    path_list.delete_if{|path| Dir.glob(File.join(path, "*.{a,so,dll,lib}")).empty?}
  end

  # keep paths for searching dynamic libs
  #$LIBPATH |= path_list
  path_list.uniq
end

def search_vers_on_path(vers, path, *heads)
  exts = get_ext_list.join(',')
  files = Dir.glob(File.join(path, "*{#{heads.join(',')}}*.{#{exts}}"), File::FNM_CASEFOLD)
  vers.find_all{|ver| files.find{|f| f =~ /(#{ver}|#{ver.delete('.')})/} }
end

def find_tcl(tcllib, stubs, version, *opt_paths)
  if TclConfig_Info['MKMF_PARAMS']
    # already checked existence of tcl library based on tclConfig.sh
    ($INCFLAGS ||= "") << " " << TclConfig_Info['MKMF_PARAMS']['INCFLAGS']
    $LIBPATH ||= []; $LIBPATH |= TclConfig_Info['MKMF_PARAMS']['LIBPATH']
    ($libs ||= "") << " " << TclConfig_Info['MKMF_PARAMS']['libs']
    return [true, nil, nil, nil]
  end
  # else, no available tclConfig.sh on the system

  print "Search Tcl library"

  if stubs
    func = "Tcl_InitStubs"
    lib = "tclstub"
  else
    func = "Tcl_FindExecutable"
    lib = "tcl"
  end

  if version && ! version.empty?
    versions = [version]
  else
    versions = TkLib_Config['search_versions']
  end

  default_paths = []

  default_paths.concat [
    RbConfig::CONFIG['libdir'],
    File.join(RbConfig::CONFIG['exec_prefix'], 'lib'),
    File.join(RbConfig::CONFIG['prefix'], 'lib'),
    "/usr/local/lib", "/usr/pkg/lib", "/usr/contrib/lib", "/usr/lib"
  ].find_all{|dir| File.directory?(dir)} unless CROSS_COMPILING

  if TkLib_Config["ActiveTcl"].kind_of?(String)  # glob path
    default_paths.concat Dir.glob(TkLib_Config["ActiveTcl"]).sort.reverse.map{|d| d << "/lib"}
  end

  if !CROSS_COMPILING and is_win32?
    default_paths.concat [
      "c:/Tcl/lib","c:/Program Files/Tcl/lib","c:/Program Files (x86)/Tcl/lib",
      "/Tcl/lib","/Program Files/Tcl/lib","/Program Files (x86)/Tcl/lib"
    ].find_all{|dir| File.directory?(dir)}.map{|dir| File.expand_path(dir)}

    # for MinGW
    ["/usr/local/lib64", "/usr/lib64", "/usr/local/lib", "/usr/lib"].each{|dir|
      default_paths << File.expand_path(dir) if File.directory? dir
    }

    default_paths |= ENV['LIBRARY_PATH'].split(';').find_all{|dir| File.directory? dir}.map{|dir| File.expand_path(dir)} if ENV['LIBRARY_PATH']
    default_paths |= ENV['PATH'].split(';').find_all{|dir| File.directory? dir}.map{|dir| File.expand_path(dir)} if ENV['PATH']
  end

  default_paths |= TkLib_Config["checked_shlib_dirs"]

  unless TkLib_Config["space-on-tk-libpath"]
    default_paths.delete_if{|path| path =~ / /}
  end

  if (paths = opt_paths.compact).empty?
    paths = check_tcl_NG_path(default_paths)
  end

  incflags = ($INCFLAGS ||= "").dup
  libpath = ($LIBPATH ||= []).dup
  libs_param = ($libs ||= "").dup
  tcllibs = nil

  exts = "(" + get_ext_list.join('|') + ")"

  paths.map{|path|
    lib_w_sufx = lib
    begin
      $LIBPATH |= [path]
      inc = [File.join(File.dirname(path),"include"), File.dirname(path)]
      inc.each{|f| $INCFLAGS << " -I" << f }

      if tcllib
        print(".")
        if have_library(tcllib, func, ["tcl.h"])
          return [true, path, tcllib, nil, *inc]
        end
      else
        sufx_list = ['', 't', 'g', 's', 'x']
        search_vers_on_path(versions, path, lib, 'tcl').find{|ver|
          dir_enum = Dir.foreach(path)
          no_dot_ver = ver.delete('.')
          libnames = ["#{lib}#{ver}", "#{lib}#{no_dot_ver}"]
          libnames << "tcl#{ver}" << "tcl#{no_dot_ver}"  if lib != "tcl"
          libnames.find{|libname|
            sufx_list.find{|sufx|
              print(".")
              dir_enum.map{|fname|
                if fname =~ /^.*(#{libname}.*#{sufx})\.(#{exts}).*$/
                  [fname, $1, $2]
                end
              }.compact.find{|fname, lib_w_sufx, ext|
                ext.downcase!
                if (ext != CONFIG['DLEXT'] && ext == CONFIG['LIBEXT']) ||
                    ext == "a"
                  # static link
                  tcllibs = libs_param + " -DSTATIC_BUILD " + fname.quote
                else
                  tcllibs = append_library($libs, lib_w_sufx)
                  tcllibs = "#{libpathflag([path])} #{tcllibs}"
                end
                if try_func(func, tcllibs, ["tcl.h"])
                  return [true, path, nil, tcllibs, *inc]
                end
              }
            }
          }
        }
        if (!version && (print(".");try_func(func, libs_param, ["tcl.h"])))
          return [true, path, lib_w_sufx, nil, *inc]
        end
      end
    ensure
      $LIBPATH = libpath.dup
      $libs = libs_param.dup
      $INCFLAGS = incflags.dup
    end
  }

  progress("\n")
  [false, nil, nil, nil]
end

def parse_TK_LIBS(tklibs)
  sfx = "lib|shlib|dll|so"
  re = /(("|')[^"']+\.(#{sfx})\2|[^"' ]+\.(#{sfx})|-l("|')[^"']+\5|-l[^" ]+)/#'

  tklibs.scan(re).map{|lib,|
    if lib =~ /^("|')([^"]+)\.(#{sfx})\1/
        "\"-l#{$2}\""
    elsif lib =~ /([^" ]+)\.(#{sfx})/
        "-l#{$1}"
    else
      lib
    end
  }.join(' ')
end

def find_tk(tklib, stubs, version, *opt_paths)
  if TkConfig_Info['MKMF_PARAMS']
    # already checked existence of tcl library based on tkConfig.sh
    ($INCFLAGS ||= "") << " " << TkConfig_Info['MKMF_PARAMS']['INCFLAGS']
    $LIBPATH ||= []; $LIBPATH |= TkConfig_Info['MKMF_PARAMS']['LIBPATH']
    ($libs ||= "") << " " << TkConfig_Info['MKMF_PARAMS']['libs']
    return [true, nil, nil, nil]
  end
  # else, no available tkConfig.sh on the system

  print "Search Tk library"

  if stubs
    func = "Tk_InitStubs"
    lib = "tkstub"
  else
    func = "Tk_Init"
    lib = "tk"
  end

  if version && ! version.empty?
    versions = [version]
  else
    versions = TkLib_Config['search_versions']
  end

  default_paths = []

  default_paths.concat [
    RbConfig::CONFIG['libdir'],
    File.join(RbConfig::CONFIG['exec_prefix'], 'lib'),
    File.join(RbConfig::CONFIG['prefix'], 'lib'),
    "/usr/local/lib", "/usr/pkg/lib", "/usr/contrib/lib", "/usr/lib"
  ].find_all{|dir| File.directory?(dir)} unless CROSS_COMPILING

  if !CROSS_COMPILING and is_win32?
    default_paths.concat [
      "c:/Tcl/lib","c:/Program Files/Tcl/lib","c:/Program Files (x86)/Tcl/lib",
      "/Tcl/lib","/Program Files/Tcl/lib","/Program Files (x86)/Tcl/lib"
    ].find_all{|dir| File.directory?(dir)}

    # for MinGW
    ["/usr/local/lib64", "/usr/lib64", "/usr/local/lib", "/usr/lib"].each{|dir|
      default_paths << File.expand_path(dir) if File.directory? dir
    }

    default_paths |= ENV['LIBRARY_PATH'].split(';').find_all{|dir| File.directory? dir}.map{|dir| File.expand_path(dir)} if ENV['LIBRARY_PATH']
    default_paths |= ENV['PATH'].split(';').find_all{|dir| File.directory? dir}.map{|dir| File.expand_path(dir)} if ENV['PATH']
  end

  default_paths |= TkLib_Config["checked_shlib_dirs"]

  unless TkLib_Config["space-on-tk-libpath"]
    default_paths.delete_if{|path| path =~ / /}
  end

  if (paths = opt_paths.compact).empty?
    paths = check_tk_NG_path(default_paths)
  end

  incflags = ($INCFLAGS ||= "").dup
  libpath = ($LIBPATH ||= []).dup
  libs_param = ($libs ||= "").dup
  tcllibs = nil

  exts = "(" + get_ext_list.join('|') + ")"

  paths.map{|path|
    lib_w_sufx = lib
    begin
      $LIBPATH |= [path]
      inc = [File.join(File.dirname(path),"include"), File.dirname(path)]
      inc.each{|f| $INCFLAGS << " -I" << f }

      if tklib
        print(".")
        if have_library(tklib, func, ["tcl.h", "tk.h"])
          return [true, path, tklib, nil, *inc]
        end
      else
        sufx_list = ['', 't', 'g', 's', 'x']
        search_vers_on_path(versions, path, lib, 'tk').find{|ver|
          dir_enum = Dir.foreach(path)
          no_dot_ver = ver.delete('.')
          libnames = ["#{lib}#{ver}", "#{lib}#{no_dot_ver}"]
          libnames << "tk#{ver}" << "tk#{no_dot_ver}"  if lib != "tk"
          libnames.find{|libname|
            sufx_list.find{|sufx|
              print(".")
              dir_enum.map{|fname|
                if fname =~ /^.*(#{libname}.*#{sufx})\.(#{exts}).*$/
                  [fname, $1, $2]
                end
              }.compact.find{|fname, lib_w_sufx, ext|
                if (ext != CONFIG['DLEXT'] && ext == CONFIG['LIBEXT']) ||
                    ext == "a"
                  # static link
                  tklibs = libs_param + " -DSTATIC_BUILD " + fname.quote
                else
                  tklibs = append_library($libs, lib_w_sufx)
                  tklibs = "#{libpathflag([path])} #{tklibs}"
                end
                if try_func(func, tklibs, ["tcl.h", "tk.h"])
                  return [true, path, nil, tklibs, *inc]
                end
              }
            }
          }
        }
        if (!version && (print(".");try_func(func, libs_param, ["tcl.h", "tk.h"])))
          return [true, path, lib_w_sufx, nil, *inc]
        end
      end
    ensure
      $LIBPATH = libpath
      $libs = libs_param
      $INCFLAGS = incflags.dup
    end
  }

  progress("\n")
  [false, nil, nil, nil]
end

def find_tcltk_library(tcllib, tklib, stubs, tclversion, tkversion,
                       tcl_opt_paths, tk_opt_paths)
  st,path,lib,libs,*inc = find_tcl(tcllib, stubs, tclversion, *tcl_opt_paths)
  if !st && TkLib_Config['enable-shared'] == nil
    TkLib_Config['enable-shared'] = false
    st,path,lib,libs,*inc = find_tcl(tcllib, stubs, tclversion, *tcl_opt_paths)
  end
  unless st
    puts("\n""Warning:: cannot find Tcl library. tcltklib will not be compiled (tcltklib is disabled on your Ruby. That is, Ruby/Tk will not work). Please check configure options.")
    return false
  else
    ($LIBPATH ||= []; $LIBPATH |= [path]) if path
    $libs = append_library($libs, lib) if lib
    ($libs ||= "") << " " << libs if libs
    $INCFLAGS ||= ""
    inc.each{|f| $INCFLAGS << " -I" << f}
  end

  st,path,lib,libs,*inc = find_tk(tklib, stubs, tkversion, *tk_opt_paths)
  if !st && TkLib_Config['enable-shared'] == nil
    TkLib_Config['enable-shared'] = false
    st,path,lib,libs,*inc = find_tk(tklib, stubs, tkversion, *tk_opt_paths)
  end
  unless st
    puts("\n""Warning:: cannot find Tk library. tcltklib will not be compiled (tcltklib is disabled on your Ruby. That is, Ruby/Tk will not work). Please check configure options.")
    return false
  else
    ($LIBPATH ||= []; $LIBPATH |= [path]) if path
    $libs = append_library($libs, lib) if lib && !lib.empty?
    ($libs ||= "") << " " << libs if libs
    $INCFLAGS ||= ""
    inc.each{|f| $INCFLAGS << " -I" << f}
  end

  true
end

def find_tcltk_header(tclver, tkver)
  base_dir = []

  base_dir.concat [
    File.join(RbConfig::CONFIG['prefix'], 'include'),
    "/usr/local/include", "/usr/pkg/include", "/usr/contrib/include",
    "/usr/include"
  ].find_all{|dir| File.directory?(dir)}.map{|dir| File.expand_path(dir)}

  if !CROSS_COMPILING && is_win32?
    base_dir.concat [
      "c:/Tcl/include","c:/Program Files/Tcl/include",
      "c:/Program Files (x86)/Tcl/include",
      "/Tcl/include","/Program Files/Tcl/include",
      "/Program Files (x86)/Tcl/include"
    ].find_all{|dir| File.directory?(dir)}.map{|dir| File.expand_path(dir)}

    if ENV['CPATH']
      base_dir |= ENV['CPATH'].split(';').find_all{|dir| File.directory?(dir)}.map{|dir| File.expand_path(dir)}
    end
  end

  base_dir |= TkLib_Config["checked_shlib_dirs"]

  unless TkLib_Config["space-on-tk-libpath"]
    base_dir.delete_if{|path| path =~ / /}
  end

  # tcl.h
  if TclConfig_Info['MKMF_PARAMS']
    # already checked existence of tcl headers based on tclConfig.sh
    have_tcl_h = true
  else
    print "Search tcl.h"
    newline
    if enable_config("tcl-h-ver-check", true) &&
        tclver && tclver =~ /^\D*(\d)\.?(\d)/
      major = $1; minor = $2
    else
      major = minor = nil
    end
    progress(".")
    if major && minor
      # version check on tcl.h
      version_check = proc {|code|
        code << ("#if TCL_MAJOR_VERSION != #{major} || TCL_MINOR_VERSION != #{minor}\n" \
                 "#error VERSION does not match\n" \
                 "#endif")
      }
    else
      version_check = nil
    end
    have_tcl_h = have_header('tcl.h', &version_check)
    unless have_tcl_h
      if tclver && ! tclver.empty?
        versions = [tclver]
      else
        versions = TkLib_Config['search_versions']
      end
      paths = base_dir.dup
      (versions + [""]).each{|ver|
        paths.concat(base_dir.map{|dir|
                       [
                        dir + '/tcl' + ver,
                        dir + '/tcl' + ver + '/include',
                        dir + '/tcl' + ver.delete('.'),
                        dir + '/tcl' + ver.delete('.') + '/include'
                       ]
                     }.flatten)
      }
      paths = paths.map{|dir|
        (File.directory?(dir))? File.expand_path(dir): nil
      }.compact.uniq

      if major || minor
        version_check = proc {|code|
          code << "#if TCL_MAJOR_VERSION != #{major}\n#error MAJOR_VERSION does not match\n#endif\n" if major
          code << "#if TCL_MINOR_VERSION != #{minor}\n#error MINOR_VERSION does not match\n#endif\n" if minor
          code
        }
      else
        version_check = nil
      end
      have_tcl_h = paths.find{|path|
        progress(".")
        inc_opt = " -I#{path.quote}"
        if try_header("tcl", inc_opt, &version_check)
          ($INCFLAGS ||= "") << inc_opt
          true
        else
          false
        end
      }
    end
    progress("\n")
  end

  # tk.h
  if TkConfig_Info['MKMF_PARAMS']
    # already checked existence of tk headers based on tkConfig.sh
    have_tk_h = true
  else
    print "Search tk.h"
    newline
    if enable_config("tk-h-ver-check", true) &&
        tkver && tkver =~ /^\D*(\d)\.?(\d)/
      major = $1; minor = $2
    else
      major = minor = nil
    end
    progress(".")
    if major && minor
      # version check on tk.h
      version_check = proc {|code|
        code << ("#if TK_MAJOR_VERSION != #{major} || TK_MINOR_VERSION != #{minor}\n" \
                 "#error VERSION does not match\n" \
                 "#endif")
      }
    else
      version_check = nil
    end
    have_tk_h = have_header('tk.h')
    unless have_tk_h
      if tkver && ! tkver.empty?
        versions = [tkver]
      else
        versions = TkLib_Config['search_versions']
      end
      paths = base_dir.dup
      (versions + [""]).each{|ver|
        paths.concat(base_dir.map{|dir|
                       [
                        dir + '/tk' + ver,
                        dir + '/tk' + ver + '/include',
                        dir + '/tk' + ver.delete('.'),
                        dir + '/tk' + ver.delete('.') + '/include'
                       ]
                     }.flatten)
      }
      paths = paths.map{|dir|
        (File.directory?(dir))? File.expand_path(dir): nil
      }.compact.uniq

      if major || minor
        version_check = proc {|code|
          code << "#if TK_MAJOR_VERSION != #{major}\n#error MAJOR_VERSION does not match\n#endif\n" if major
          code << "#if TK_MINOR_VERSION != #{minor}\n#error MINOR_VERSION does not match\n#endif\n" if minor
          code
        }
      else
        version_check = nil
      end
      have_tk_h = paths.find{|path|
        progress(".")
        inc_opt = " -I#{path.quote}"
        if try_header(%w'tcl.h tk.h', inc_opt, &version_check)
          ($INCFLAGS ||= "") << inc_opt
          true
        else
          false
        end
      }
    end
    progress("\n")
  end

  puts "Can't find \"tcl.h\"." unless have_tcl_h
  puts "Can't find \"tk.h\"."  unless have_tk_h
  have_tcl_h && have_tk_h
end

def setup_for_macosx_framework(tclver, tkver)
  # use framework, but no tclConfig.sh
  unless $LIBS && $LIBS.include?('-framework')
    ($LIBS ||= "") << ' -framework Tk -framework Tcl'
  end

  if TkLib_Config["tcl-framework-header"]
    TclConfig_Info['TCL_INCLUDE_SPEC'][0,0] =
      " -I#{TkLib_Config["tcl-framework-header"].quote} "
  else
    tcl_base = File.join(TkLib_Config["tcltk-framework"], 'Tcl.framework')
    if tclver
      TclConfig_Info['TCL_INCLUDE_SPEC'] <<
        " -I#{File.join(tcl_base, 'Versions', tclver, 'Headers').quote} "
    end

    TclConfig_Info['TCL_INCLUDE_SPEC'] << File.join(tcl_base, 'Headers')

    unless tclver
      dir = Dir.glob(File.join(tcl_base, 'Versions', '*', 'Headers'),
                     File::FNM_CASEFOLD).sort.reverse[0]
      TclConfig_Info['TCL_INCLUDE_SPEC'] << "-I#{dir.quote} " if dir
    end
  end

  if TkLib_Config["tk-framework-header"]
    TkConfig_Info['TK_INCLUDE_SPEC'][0,0] =
      " -I#{TkLib_Config["tk-framework-header"].quote} "
  else
    tk_base  = File.join(TkLib_Config["tcltk-framework"], 'Tk.framework')
    if tkver
      TkConfig_Info['TK_INCLUDE_SPEC'] <<
        " -I#{File.join(tk_base, 'Versions', tkver, 'Headers').quote} "
    end

    TkConfig_Info['TK_INCLUDE_SPEC'] << File.join(tk_base, 'Headers')

    unless tkver
      dir = Dir.glob(File.join(tk_base, 'Versions', '*', 'Headers'),
                     File::FNM_CASEFOLD).sort.reverse[0]
      TkConfig_Info['TK_INCLUDE_SPEC'] << "-I#{dir.quote} " if dir
    end
  end
end

def find_X11(*opt_paths)
  defaults =
    [ "/usr/X11*/lib", "/usr/lib/X11*", "/usr/local/X11*", "/usr/openwin/lib" ]
  paths = []
  opt_paths.compact.each{|path| paths.concat(Dir.glob(path.strip.chomp('/'), File::FNM_CASEFOLD))}
  defaults.compact.each{|path| paths.concat(Dir.glob(path.strip.chomp('/'), File::FNM_CASEFOLD))}
  st = find_library("X11", "XOpenDisplay", *paths)
  unless st
    puts("\n""Warning:: cannot find X11 library. tcltklib will not be compiled (tcltklib is disabled on your Ruby. That is, Ruby/Tk will not work). Please check configure options. If your Tcl/Tk don't require X11, please try --without-X11.")
  end
  st
end

def search_X_libraries
  use_tkConfig = false
  if TkConfig_Info['config_file_path']
    # use definitions on tkConfig.sh
    if (/\S/ =~ TkConfig_Info['TK_XINCLUDES'] ||
        /\S/ =~ TkConfig_Info['TK_XLIBSW'])
      use_tkConfig = true
      #use_X = true && with_config("X11", ! is_win32?)
      use_X = with_config("X11", true)
    else
      #use_X = false || with_config("X11", false)
      use_X = with_config("X11", false)
    end
  else
    # depend on configure options
    use_X = with_config("X11", !(is_win32? || TkLib_Config["tcltk-framework"]))
  end

  if /\S/ =~ TkConfig_Info['TK_XINCLUDES']
    ($INCFLAGS ||= "") << " " << TkConfig_Info['TK_XINCLUDES'].strip
  end

  if use_X
    puts("Use X11 libraries (or use TK_XINCLUDES/TK_XLIBSW information on tkConfig.sh).")
    x11_idir, x11_ldir = dir_config("X11")
    x11_ldir2 = with_config("X11-lib")
    unless find_X11(x11_ldir2, x11_ldir)
      puts("Can't find X11 libraries. ")
      if use_tkConfig &&
          /\S/ =~ TkConfig_Info['TK_XLIBSW']
        puts("But, try to use TK_XLIBSW information (believe tkConfig.sh).")
        ($libs ||= "") << " " << TkConfig_Info['TK_XLIBSW'] << " "
      else
        puts("So, can't make tcltklib.so which is required by Ruby/Tk.")
        exit
      end
    end
  end

  use_X
end

def pthread_check()
  tcl_major_ver = nil
  tcl_minor_ver = nil

  # Is tcl-thread given by user ?
  case enable_config("tcl-thread")
  when true
    tcl_enable_thread = true
  when false
    tcl_enable_thread = false
  else
    tcl_enable_thread = nil
  end

  if TclConfig_Info['config_file_path']
    if tcl_enable_thread == true
      puts("\n""Warning: definition of tclConfig.sh is ignored, because --enable-tcl-thread option is given.")
    elsif tcl_enable_thread == false
      puts("\n""Warning: definition of tclConfig.sh is ignored, because --disable-tcl-thread option is given.")
    else
      # tcl-thread is unknown and tclConfig.sh is given
      if TclConfig_Info['TCL_THREADS']
        tcl_enable_thread = (TclConfig_Info['TCL_THREADS'] == "1")
      else
        tcl_major_ver = TclConfig_Info['TCL_MAJOR_VERSION'].to_i
        tcl_minor_ver = TclConfig_Info['TCL_MINOR_VERSION'].to_i
        if tcl_major_ver < 8 || (tcl_major_ver == 8 && tcl_minor_ver == 0)
          tcl_enable_thread = false
        end
      end

      if tcl_enable_thread == nil
        # cannot find definition
        if tcl_major_ver
          puts("\n""Warning: '#{TclConfig_Info['config_file_path']}' doesn't include TCL_THREADS definition.")
        else
          puts("\n""Warning: '#{TclConfig_Info['config_file_path']}' may not be a tclConfig file.")
        end
        #tclConfig = false
      end
    end
  end

  if tcl_enable_thread == nil && !TclConfig_Info['config_file_path']
    # tcl-thread is unknown and tclConfig is unavailable
    begin
      try_run("int main() { exit(0); }")
    rescue Exception
      # cannot try_run. Is CROSS-COMPILE environment?
      puts(%Q'\
*****************************************************************************
**
** NATIVETHREAD SUPPORT CHECK WARNING:
**
**   We cannot check the consistency of nativethread support between
**   Ruby and the Tcl/Tk library in your environment (are you perhaps
**   cross-compiling?). If nativethread support for these 2 packages
**   is inconsistent you may find you get errors when running Ruby/Tk
**   (e.g. hangs or segmentation faults).  We strongly recommend
**   you to check the consistency manually.
**
*****************************************************************************
')
      return true
    end
  end

  if tcl_enable_thread == nil
    # tcl-thread is unknown
    if try_run(<<EOF)
#include <tcl.h>
int main() {
   Tcl_Interp *ip;
   ip = Tcl_CreateInterp();
   exit((Tcl_Eval(ip, "set tcl_platform(threaded)") == TCL_OK)? 0: 1);
}
EOF
      tcl_enable_thread = true
    elsif try_run(<<EOF)
#include <tcl.h>
static Tcl_ThreadDataKey dataKey;
int main() { exit((Tcl_GetThreadData(&dataKey, 1) == dataKey)? 1: 0); }
EOF
      tcl_enable_thread = true
    else
      tcl_enable_thread = false
    end
  end

  # check pthread mode
  if (TkLib_Config["ruby_with_thread"])
    $CPPFLAGS ||= ""

    # ruby -> enable
    unless tcl_enable_thread
      # ruby -> enable && tcl -> disable
      puts(%Q'\
*****************************************************************************
**
** NATIVETHREAD SUPPORT MODE WARNING:
**
**   Ruby is compiled with --enable-pthread, but your Tcl/Tk library
**   seems to be compiled without nativethread support. Although you can
**   create the tcltklib library, this combination may cause errors (e.g.
**   hangs or segmentation faults). If you have no reason to keep the
**   current nativethread support status, we recommend you reconfigure and
**   recompile the libraries so that both or neither support nativethreads.
**
**   If you want change the status of nativethread support, please recompile
**   Ruby without "--enable-pthread" configure option (If you use Ruby 1.9.x
**   or later, you cannot remove this option, because it requires native-
**   thread support.) or recompile Tcl/Tk with "--enable-threads" configure
**   option (if your Tcl/Tk is later than or equal to Tcl/Tk 8.1).
**
*****************************************************************************
')
    end

    # ruby -> enable && tcl -> enable/disable
    if tcl_enable_thread
      $CPPFLAGS += ' -DWITH_TCL_ENABLE_THREAD=1'
    else
      $CPPFLAGS += ' -DWITH_TCL_ENABLE_THREAD=0'
    end

    return true

  else
    # ruby -> disable
    if tcl_enable_thread
      # ruby -> disable && tcl -> enable
      puts(%Q'\
*****************************************************************************
**
** NATIVETHREAD SUPPORT MODE ERROR:
**
**   Ruby is not compiled with --enable-pthread, but your Tcl/Tk
**   library seems to be compiled with nativethread support. This
**   combination may cause frequent hang or segmentation fault
**   errors when Ruby/Tk is working. We recommend that you NEVER
**   create the library with such a combination of nativethread support.
**
**   Please recompile Ruby with the "--enable-pthread" configure option
**   or recompile Tcl/Tk with the "--disable-threads" configure option.
**
*****************************************************************************
')
      $CPPFLAGS += ' -DWITH_TCL_ENABLE_THREAD=1'
      return false
    else
      # ruby -> disable && tcl -> disable
      $CPPFLAGS += ' -DWITH_TCL_ENABLE_THREAD=0'
      return true
    end
  end
end

##############################################################
# main
##############################################################
# check header file
print("check functions.")

%w"ruby_native_thread_p rb_errinfo rb_hash_lookup
 rb_proc_new 
 rb_sourcefile rb_thread_alive_p rb_thread_check_trap_pending
 ruby_enc_find_basename
".each do |func|
  have_func(func, "ruby.h")
  progress(".")
end
progress("\n")

# check libraries
unless is_win32?
  print("check libraries.")
  have_library("nsl", "t_open")
  progress(".")
  have_library("socket", "socket")
  progress(".")
  have_library("dl", "dlopen")
  progress(".")
  have_library("m", "log", "math.h")
  progress("\n")
end
$CPPFLAGS ||= ""
$CPPFLAGS += ' -D_WIN32' if /cygwin/ =~ RUBY_PLATFORM

# Does ruby have nativethread ?
TkLib_Config["ruby_with_thread"] =
  macro_defined?('HAVE_NATIVETHREAD', '#include "ruby.h"')


#---------------------------------------------------
TclConfig_Info = {}
TkConfig_Info  = {}

# use Tcl/Tk build dir?  (has highest priority)
TkLib_Config["tcl-build-dir"] = with_config("tcl-build-dir")
TkLib_Config["tk-build-dir"]  = with_config("tk-build-dir")
if TkLib_Config["tcl-build-dir"]
  puts("use Tcl build (pre-install) dir \"#{TkLib_Config["tcl-build-dir"]}\"")
  TkLib_Config["tcl-build-dir"] = File.expand_path(TkLib_Config["tcl-build-dir"])
  base = File.dirname(TkLib_Config["tcl-build-dir"])
  ($INCFLAGS ||= "") << " -I#{File.join(base, "generic").quote} -I#{TkLib_Config["tcl-build-dir"].quote}"
  $LIBPATH ||= []; $LIBPATH |= [TkLib_Config["tcl-build-dir"]]
end
if TkLib_Config["tk-build-dir"]
  puts("use Tk build (pre-install) dir \"#{TkLib_Config["tk-build-dir"]}\"")
  TkLib_Config["tk-build-dir"] = File.expand_path(TkLib_Config["tk-build-dir"])
  base = File.dirname(TkLib_Config["tk-build-dir"])
  ($INCFLAGS ||= "") << " -I#{File.join(base, "generic").quote} -I#{TkLib_Config["tk-build-dir"].quote}"
  $LIBPATH ||= []; $LIBPATH |= [TkLib_Config["tk-build-dir"]]
end

# check requirement of Tcl/tk version
tcltk_version = with_config("tcltkversion")
TkLib_Config["tcltkversion"] = check_tcltk_version(tcltk_version)

if TkLib_Config["tcl-build-dir"]
  if (cfgfile = with_config("tclConfig-file", Dir.glob(File.join(TkLib_Config["tcl-build-dir"], "tclConfig*.sh"), File::FNM_CASEFOLD)[0]))
    TclConfig_Info['config_file_path'] = cfgfile
    TkLib_Config["tclConfig_info"] = cfginfo = parse_tclConfig(cfgfile)
    if tclver = TkLib_Config["tcltkversion"][0]
      TkLib_Config["tcltkversion"][0].sub!(/\d(\.?)\d/, "#{cfginfo['TCL_MAJOR_VERSION']}\\1#{cfginfo['TCL_MINOR_VERSION']}")
    else
      TkLib_Config["tcltkversion"][0] = "#{cfginfo['TCL_MAJOR_VERSION']}.#{cfginfo['TCL_MINOR_VERSION']}"
    end
  end
end
if TkLib_Config["tk-build-dir"]
  if (cfgfile = with_config("tkConfig-file", Dir.glob(File.join(TkLib_Config["tk-build-dir"], "tkConfig*.sh"), File::FNM_CASEFOLD)[0]))
    TkConfig_Info['config_file_path'] = cfgfile
    TkLib_Config["tkConfig_info"] = cfginfo = parse_tclConfig(cfgfile)
    if TkLib_Config["tcltkversion"][1]
      TkLib_Config["tcltkversion"][1].sub!(/\d(\.?)\d/, "#{cfginfo['TK_MAJOR_VERSION']}\\1#{cfginfo['TK_MINOR_VERSION']}")
    else
      TkLib_Config["tcltkversion"][1] = "#{cfginfo['TK_MAJOR_VERSION']}.#{cfginfo['TK_MINOR_VERSION']}"
    end
  end
end

tclver, tkver = TkLib_Config["tcltkversion"]
puts("Specified Tcl/Tk version is #{[tclver, tkver].inspect}") if tclver||tkver

# use ActiveTcl ?
#if activeTcl = with_config("ActiveTcl")
#if activeTcl = with_config("ActiveTcl", true)
if activeTcl = with_config("ActiveTcl", !(TkLib_Config["tcl-build-dir"] && TkLib_Config["tk-build-dir"]))
  puts("Use ActiveTcl libraries (if available).")
  unless activeTcl.kind_of? String
    # set default ActiveTcl path
    if CROSS_COMPILING
    elsif is_win32?
      activeTcl = 'c:/Tcl*'
    elsif is_macosx?
      activeTcl = '/Library/Frameworks'
    else
      activeTcl = '/opt/ActiveTcl*'
    end
  end
end
TkLib_Config["ActiveTcl"] = activeTcl

# allow space chars on a libpath
TkLib_Config["space-on-tk-libpath"] =
  enable_config("space-on-tk-libpath", ! is_win32?)

# enable Tcl/Tk stubs?
=begin
if /\S/ =~ TclConfig_Info['TCL_STUB_LIB_SPEC'] &&
   /\S/ =~ TkConfig_Info['TK_STUB_LIB_SPEC']
  stubs = true
  unless (st = enable_config("tcltk-stubs")).nil?
    stubs &&= st
  end
  unless (st = with_config("tcltk-stubs")).nil?
    stubs &&= st
  end
else
  stubs = enable_config("tcltk-stubs") || with_config("tcltk-stubs")
end
=end
stubs = enable_config("tcltk-stubs") || with_config("tcltk-stubs")
if (TkLib_Config["tcltk-stubs"] = stubs)
  puts("Compile with Tcl/Tk stubs.")
  $CPPFLAGS ||= ""; $CPPFLAGS += ' -DUSE_TCL_STUBS -DUSE_TK_STUBS'
end

# directory configuration of Tcl/Tk libraries
if TkLib_Config["tcl-build-dir"]
  tcl_idir = File.join(File.dirname(TkLib_Config["tcl-build-dir"]),"generic")
  tcl_ldir = TkLib_Config["tcl-build-dir"]
else
  tcl_idir, tcl_ldir = dir_config("tcl")
end
if TkLib_Config["tk-build-dir"]
  tk_idir = File.join(File.dirname(TkLib_Config["tk-build-dir"]),"generic")
  tk_ldir = TkLib_Config["tk-build-dir"]
else
  tk_idir, tk_ldir = dir_config("tk")
end

tcl_idir = tk_idir unless tcl_idir
tcl_ldir = tk_ldir unless tcl_ldir
tk_idir = tcl_idir unless tk_idir
tk_ldir = tcl_ldir unless tk_ldir

TclConfig_Info['TCL_INCLUDE_SPEC'] ||= ""
TkConfig_Info['TK_INCLUDE_SPEC']   ||= ""
TclConfig_Info['TCL_INCLUDE_SPEC'][0,0] = "-I#{tcl_idir.quote} " if tcl_idir
TkConfig_Info['TK_INCLUDE_SPEC'][0,0]   = "-I#{tk_idir.quote} "  if tk_idir

# get tclConfig.sh/tkConfig.sh
TkLib_Config["tcl-NG-path"] = []
TkLib_Config["tk-NG-path"] = []
tclcfg, tkcfg =
  get_tclConfig(
    TclConfig_Info['config_file_path'] || with_config("tclConfig-file", true),
    TkConfig_Info['config_file_path']  || with_config("tkConfig-file", true),
    (TclConfig_Info['config_file_path'])?
                File.dirname(TclConfig_Info['config_file_path']) :
                with_config("tclConfig-dir", tcl_ldir || true),
    (TkConfig_Info['config_file_path'])?
                File.dirname(TkConfig_Info['config_file_path']) :
                with_config("tkConfig-dir", tk_ldir || true)
  )
TclConfig_Info.merge!(TkLib_Config["tclConfig_info"]) if TkLib_Config["tclConfig_info"]
TkConfig_Info.merge!(TkLib_Config["tkConfig_info"]) if TkLib_Config["tkConfig_info"]
TclConfig_Info['config_file_path'] ||= tclcfg
TkConfig_Info['config_file_path'] ||= tkcfg

tk_cfg_dir  = File.dirname(TkConfig_Info['config_file_path'])  rescue nil
tcl_cfg_dir = File.dirname(TclConfig_Info['config_file_path']) rescue nil

tk_ldir_list  = [tk_ldir,  tk_cfg_dir].uniq
tcl_ldir_list = [tcl_ldir, tcl_cfg_dir].uniq

if TkConfig_Info['config_file_path']
  if TkLib_Config["tk-build-dir"]
    spec_dir = get_libpath(TkConfig_Info['TK_LIB_FLAG'], TkConfig_Info['TK_BUILD_LIB_SPEC'])
  else
    spec_dir = get_libpath(TkConfig_Info['TK_LIB_FLAG'], TkConfig_Info['TK_LIB_SPEC'])
  end
  tk_ldir_list << spec_dir if File.directory?(spec_dir)
end
if TclConfig_Info['config_file_path']
  if TkLib_Config["tcl-build-dir"]
    spec_dir = get_libpath(TclConfig_Info['TCL_LIB_FLAG'], TclConfig_Info['TCL_BUILD_LIB_SPEC'])
  else
    spec_dir = get_libpath(TclConfig_Info['TCL_LIB_FLAG'], TclConfig_Info['TCL_LIB_SPEC'])
  end
  tcl_ldir_list << spec_dir if File.directory?(spec_dir)
end

# check tk_shlib_search_path
TkLib_Config["checked_shlib_dirs"] =
  check_shlib_search_path(with_config('tk-shlib-search-path'))

# set TCL_DEFS and TK_DEFS
$CPPFLAGS ||= ""
# $CPPFLAGS += " #{TclConfig_Info['TCL_DEFS']}"
# $CPPFLAGS += " #{TkConfig_Info['TK_DEFS']}"
$defs += collect_tcltk_defs(TclConfig_Info['TCL_DEFS'], TkConfig_Info['TK_DEFS'])

# MacOS X Frameworks?
if TkLib_Config["tcltk-framework"]
  puts("Use MacOS X Frameworks.")
  ($LDFLAGS ||= "") << " " << libpathflag([TkLib_Config["tcl-build-dir"]]) if TkLib_Config["tcl-build-dir"]

  libs = ''
  if tcl_cfg_dir
    TclConfig_Info['TCL_LIBS'] ||= ""
    ($INCFLAGS ||= "") << ' ' << TclConfig_Info['TCL_INCLUDE_SPEC']
    libs << ' ' << TclConfig_Info['TCL_LIBS']
    if stubs
      if TkLib_Config["tcl-build-dir"] &&
          /\S/ =~ TclConfig_Info['TCL_BUILD_STUB_LIB_SPEC']
        libs << ' ' << TclConfig_Info['TCL_BUILD_STUB_LIB_SPEC']
      else
        libs << ' ' << TclConfig_Info['TCL_STUB_LIB_SPEC']
      end
    else
      if TkLib_Config["tcl-build-dir"] &&
          /\S/ =~ TclConfig_Info['TCL_BUILD_LIB_SPEC']
        libs << ' ' << TclConfig_Info['TCL_BUILD_LIB_SPEC']
      else
        libs << ' ' << TclConfig_Info['TCL_LIB_SPEC']
      end
    end
  end

  libs << " " << libpathflag([TkLib_Config["tk-build-dir"]]) if TkLib_Config["tk-build-dir"]

  if tk_cfg_dir
    TkConfig_Info['TK_LIBS'] ||= ""
    ($INCFLAGS ||= "") << ' ' << TkConfig_Info['TK_INCLUDE_SPEC']
    libs << ' ' << TkConfig_Info['TK_LIBS']
    if stubs
      if TkLib_Config["tk-build-dir"] &&
          /\S/ =~ TclConfig_Info['TK_BUILD_STUB_LIB_SPEC']
        libs << ' ' << TkConfig_Info['TK_BUILD_STUB_LIB_SPEC']
      else
        libs << ' ' << TkConfig_Info['TK_STUB_LIB_SPEC']
      end
    else
      if TkLib_Config["tk-build-dir"] &&
          /\S/ =~ TclConfig_Info['TK_BUILD_LIB_SPEC']
        libs << ' ' << TkConfig_Info['TK_BUILD_LIB_SPEC']
      else
        libs << ' ' << TkConfig_Info['TK_LIB_SPEC']
      end
    end
  end
  $LDFLAGS << ' ' << libs
  setup_for_macosx_framework(tclver, tkver) if tcl_cfg_dir && tk_cfg_dir
end

# name of  Tcl/Tk libraries
tklib = with_config("tklib")
tcllib = with_config("tcllib")

# search X libraries
use_X = search_X_libraries


#---------------------------------------------------
if (TkLib_Config["tcltk-framework"] ||
      ( find_tcltk_header(tclver, tkver) &&
          find_tcltk_library(tcllib, tklib, stubs, tclver, tkver,
                             tcl_ldir_list, tk_ldir_list) ) ) &&
    (stubs || pthread_check())
  # create Makefile

  # for SUPPORT_STATUS
  $INSTALLFILES ||= []
  $INSTALLFILES << ["lib/tkextlib/SUPPORT_STATUS", "$(RUBYLIBDIR)", "lib"]

  # remove harmful definitions.
  $defs.delete_if{|x|/^-Du?intptr_t=/ =~ x}

  create_makefile("tcltklib")

  puts "\nFind Tcl/Tk libraries. Make tcltklib.so which is required by Ruby/Tk."
else
  puts "\nCan't find proper Tcl/Tk libraries. So, can't make tcltklib.so which is required by Ruby/Tk."
  puts "If you have Tcl/Tk libraries on your environment, you may be able to use them with configure options (see ext/tk/README.tcltklib)."
end
