#!@PERL@

# this may be run either directly as a script or use'd as a module

use strict;
use warnings;

package SysPathSubst;

use autouse Cwd => qw( realpath );
use autouse 'File::Spec::Functions' => qw(catdir);

my $VERSION = '@VERSION@';

my $prog;


run() unless caller();

use vars qw( @ISA @EXPORT_OK );

require Exporter;
@ISA = qw( Exporter );
@EXPORT_OK = qw( syspathsubst compact_paths );

sub prog
{
    require File::Basename;
    $prog ||= File::Basename::basename( $0 );
}

sub run
{
    my $ok = eval { main() };

    if ( $@ )
    {
	my $error = $@;

	my $prog = prog();
	print STDERR "$prog: $_\n" foreach split /\n/, $error;
	exit 1;
    }

    exit ! $ok;
}


sub main
{
    my %opt = opts();

    help(0)   if $opt{help};
    help(2)   if $opt{usage};
    version() if $opt{version};


    my $paths = syspathsubst( $opt{delimiter},
			      $opt{components},
			      @{$opt{templates}} );

    print $paths, "\n" if $paths;
}

sub syspathsubst
{
    my ( $delimiter, $components, @templates ) = @_;

    return compact_paths( $delimiter,
			  map { pathsubst( $components, $_ ) } @templates
			);
}

sub compact_paths
{
    my $delimiter = shift;

    my %in;

    my @paths = 
      grep { $_ && ! $in{$_}++ } 
      map { 'ARRAY' eq ref($_) ? catdir( @$_ ) : $_ } @_;

    return wantarray()
      ? @paths
      : defined $delimiter ? join( $delimiter, @paths )
      :                      $paths[0];

}


sub pathsubst
{
    my ( $components, $tpl ) = @_;

    $tpl = catdir( @$tpl )
      if 'ARRAY' eq ref $tpl;

    my $resolvelinks = $tpl =~ /%[lL]/;
    my $firstvalid   = $tpl =~ /%[LP]/;
    $tpl =~ s/%[pl]/%s/i;

    my @paths;

    # do minimum if nothing to fill
    if ( $tpl !~ /%s/ )
    {
	push @paths, $tpl
	  if -e $tpl
    }

    # templates to fill
    else
    {
	for my $cmp ( @$components )
	{
	    (my $tpath = $tpl) =~ s/%s/$cmp/;

	    $tpath = realpath( $tpath ) || $tpath
	      if $resolvelinks;

	    next unless -e $tpath;
	    push @paths, $tpath;
	    last if $firstvalid;
	}
    }
    return @paths;
}


sub opts
{
    require Getopt::Long;
    my %opt = ( delimiter => ' ' );

    eval {
        local $SIG{ __WARN__ } = sub { die $_[0] };

	Getopt::Long::GetOptions ( \%opt,
		     qw/
			components=s
			delimiter=s
			help
			usage
			version
			/,
		   );
    };

    die $@ if $@;

    return %opt if grep { $opt{$_} } qw/ help usage version /;

    die "missing path templates\n" unless @ARGV;

    $opt{templates} = [ map { split(':', $_ ) } @ARGV ];

    if ( ! defined $opt{components} )
    {
	chomp ($opt{components} = qx( @bindir_EVAL@/sysarch platforms ));
	die 'error running sysarch' if $?;
    }

    $opt{components} = [ split(':', $opt{components} ) ];

    $opt{delimiter} = "\n" if $opt{delimiter} eq '\n';

    return %opt;
}


sub version
{
    print prog(), " ", $VERSION, "\n";
    exit 0;
}

sub help
{
  my ( $verbose ) = @_;

  require Pod::Usage;
  Pod::Usage::pod2usage ( { -exitval => 0, -verbose => $verbose } );
}

1;

__END__

=pod

