# kpathsea.pl -- search a file as Karl Berry likes to do it.
#
# Copyright (C) 1994 Ralph Schleicher (rs@purple.in-ulm.de)
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Library General Public
# License as published by the Free Software Foundation; either
# version 2 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	See the GNU
# Library General Public License for more details.
#
# You should have received a copy of the GNU Library General Public
# License along with this library; if not, write to the Free
# Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#
# The comments are borrowed from `kpathsea.info'.  ;-)


package KPathSearch;

# Is `require' local to a package?  I don't know.
#
if (! $find_included)
{
  do 'find.pl' || die "$0:find.pl: $!\n";

  $find_included = 1;
}

sub main'kpathsearch
{
  local ($var, $def, $file) = @_;

  local (@path) = split (':', $ENV{$var} || $def, -1);
  local (@def) = split (':', $def, -1);
  local (@dir) = ();

  local ($[) = 0;

  while (@path)
    {
      $_ = shift @path;

      # Extra colons expand to the compilation default.
      #
      unshift (@path, @def), next if $_ eq '';

      # `~' and `~user' expand to home directories.
      #
      if (/^~/)
	{
	  local ($slash, $name, $n, $p, $u, $g, $q, $c, $o, $home, $s);

	  $slash = index ($_, '/');
	  $slash = length if $slash < 0;

	  $name = substr ($_, 1, $slash - 1);
	  if ($name ne '')
	    { ($n, $p, $u, $g, $q, $c, $o, $home, $s) = getpwnam ($name); }
	  else
	    { ($n, $p, $u, $g, $q, $c, $o, $home, $s) = getpwuid ($<); }

	  $home = '.' if $home eq '';

	  $_ =~ s/^~$name/$home/;
	}

      # `$foo' and `${foo}' expand to environment values.
      #
      while (/\$(\w*|\{.*\})/)
	{
	  $_ = join ('', $`, $ENV{$1} || '.', $');
	}

      # `a//' and `a//b' recursively expand to sub-directories.
      #
      if (/\/\//)
	{
	  local ($base, @sub) = split ('//', $_, -1);
	  local ($term) = pop (@sub);

	  undef @directories;
	  &find ($base);

	  foreach $sub (@sub)
	    {
	      @directories = grep (m|^$base/(.*/)?$sub|, @directories);
	    }
	  @directories = grep (m|$term$|, @directories) if $term ne '';

	  push (@dir, @directories);
	}
      else
	{
	  push (@dir, $_);
	}
    }

  # See what we have to return.
  #
  return @dir if $file eq '';

  if (wantarray)
    {
      return grep (-e ($_ = "$_/$file"), @dir);
    }

  foreach (@dir)
    {
      return $_ if -f ($_ = "$_/$file");
    }

  return undef;
}

sub wanted
{
  push (@directories, $name) if (lstat ($_)) && -d _;
}

1;
