summaryrefslogtreecommitdiff
path: root/cpan/dist/File-Spec
diff options
context:
space:
mode:
authorfukachan <fukachan>2001-03-09 14:30:08 +0000
committerfukachan <fukachan>2001-03-09 14:30:08 +0000
commit5def37416636f5f6aeccf2f1e80b789fdb35ae47 (patch)
tree7fbab5719b67716195cedcba1311a5b892c86dea /cpan/dist/File-Spec
parent7a9ad82897f5210cf71f067e02679df7948fa1f1 (diff)
downloadfml8-5def37416636f5f6aeccf2f1e80b789fdb35ae47.tar.gz
fml8-5def37416636f5f6aeccf2f1e80b789fdb35ae47.tar.bz2
fml8-5def37416636f5f6aeccf2f1e80b789fdb35ae47.zip
Initial revision
Diffstat (limited to 'cpan/dist/File-Spec')
-rw-r--r--cpan/dist/File-Spec/CHANGES13
-rw-r--r--cpan/dist/File-Spec/MANIFEST14
-rw-r--r--cpan/dist/File-Spec/MANIFEST.SKIP8
-rw-r--r--cpan/dist/File-Spec/Makefile.PL17
-rw-r--r--cpan/dist/File-Spec/README28
-rw-r--r--cpan/dist/File-Spec/Spec.pm92
-rw-r--r--cpan/dist/File-Spec/Spec/Functions.pm97
-rw-r--r--cpan/dist/File-Spec/Spec/Mac.pm394
-rw-r--r--cpan/dist/File-Spec/Spec/OS2.pm62
-rw-r--r--cpan/dist/File-Spec/Spec/Unix.pm458
-rw-r--r--cpan/dist/File-Spec/Spec/VMS.pm505
-rw-r--r--cpan/dist/File-Spec/Spec/Win32.pm354
-rwxr-xr-xcpan/dist/File-Spec/t/filefunc.t17
-rwxr-xr-xcpan/dist/File-Spec/t/filespec.t379
14 files changed, 2438 insertions, 0 deletions
diff --git a/cpan/dist/File-Spec/CHANGES b/cpan/dist/File-Spec/CHANGES
new file mode 100644
index 00000000..f326e0b7
--- /dev/null
+++ b/cpan/dist/File-Spec/CHANGES
@@ -0,0 +1,13 @@
+CHANGES for File::Spec
+
+
+0.82 Wed Jun 28 11:24:05 EDT 2000
+ - Mac.pm: file_name_is_absolute( '' ) now returns TRUE on all platforms
+ - Spec.pm: unbreak C<$VERSION = '0.xx'> to be C<$VERSION = 0.xx>, so
+ underscores can be used when I want to update CPAN without anyone
+ needing to update the perl repository.
+ - abs2rel, rel2abs doc tweaks
+ - VMS.pm: get $path =~ /\s/ checks from perl repository.
+ - Makefile.PL: added INSTALLDIRS => 'perl', since these are std. modules.
+ - Remove vestigial context prototypes from &rel2abs until some future
+ arrives where method prototypes are honored.
diff --git a/cpan/dist/File-Spec/MANIFEST b/cpan/dist/File-Spec/MANIFEST
new file mode 100644
index 00000000..dd4890ae
--- /dev/null
+++ b/cpan/dist/File-Spec/MANIFEST
@@ -0,0 +1,14 @@
+MANIFEST
+MANIFEST.SKIP
+CHANGES
+Makefile.PL
+README
+Spec.pm
+Spec/Functions.pm
+Spec/Mac.pm
+Spec/OS2.pm
+Spec/Unix.pm
+Spec/VMS.pm
+Spec/Win32.pm
+t/filespec.t
+t/filefunc.t
diff --git a/cpan/dist/File-Spec/MANIFEST.SKIP b/cpan/dist/File-Spec/MANIFEST.SKIP
new file mode 100644
index 00000000..390d5a54
--- /dev/null
+++ b/cpan/dist/File-Spec/MANIFEST.SKIP
@@ -0,0 +1,8 @@
+bak$
+^blib
+Makefile
+^pm_to_blib$
+import_.*
+export_.*
+.*\.sw[a-z]$
+\.tar\.gz$
diff --git a/cpan/dist/File-Spec/Makefile.PL b/cpan/dist/File-Spec/Makefile.PL
new file mode 100644
index 00000000..823ec2cf
--- /dev/null
+++ b/cpan/dist/File-Spec/Makefile.PL
@@ -0,0 +1,17 @@
+use ExtUtils::MakeMaker;
+# See lib/ExtUtils/MakeMaker.pm for details of how to influence
+# the contents of the Makefile that is written.
+WriteMakefile(
+ 'NAME' => 'File::Spec',
+ 'VERSION_FROM' => 'Spec.pm',
+ 'LIBS' => [''], # e.g., '-lm'
+ 'DEFINE' => '', # e.g., '-DHAVE_SOMETHING'
+ 'INC' => '', # e.g., '-I/usr/include/other'
+ 'INSTALLDIRS' => 'perl', # 'perl' makes it replace std modules
+# 'PM' => {'Spec.pm' => '$(INST_LIBDIR)/File/Spec.pm',
+# 'OS2.pm' => '$(INST_LIBDIR)/File/Spec/OS2.pm',
+# 'Win32.pm' => '$(INST_LIBDIR)/File/Spec/Win32.pm',
+# 'VMS.pm' => '$(INST_LIBDIR)/File/Spec/VMS.pm',
+# 'Unix.pm' => '$(INST_LIBDIR)/File/Spec/Unix.pm',
+# }
+);
diff --git a/cpan/dist/File-Spec/README b/cpan/dist/File-Spec/README
new file mode 100644
index 00000000..f4afcff5
--- /dev/null
+++ b/cpan/dist/File-Spec/README
@@ -0,0 +1,28 @@
+File::Spec 0.81 -- a module for portably manipulating file specifications
+
+ Copyright (c) 1998 Kenneth Albanowski. All rights reserved.
+ This program is free software; you can redistribute it and/or
+ modify it under the same terms as Perl itself.
+
+ Copyright (c) 1999, 2000 Barrie Slaymaker. All rights reserved.
+ This program is free software; you can redistribute it and/or
+ modify it under the same terms as Perl itself.
+
+This module should work with Perl 5.004 and earlier (Perl 5.005 and later
+include a version of File::Spec with the distribution, though this version
+could be more recent). If it doesn't, bug reports and patches are welcome.
+
+To install this module, please run:
+
+ perl Makefile.PL
+ make
+ make test
+ make install
+
+For more information on the module, please see the POD documentation
+inside Spec.pm. ("perldoc File::Spec", once it is installed.)
+
+A note on copyrights: a lot of people have contributed a lot of work
+to these modules, with credits given in the POD for the various modules.
+If you are one of them and would like to hold copyright on your work,
+please send me an appropriate patch for this README file.
diff --git a/cpan/dist/File-Spec/Spec.pm b/cpan/dist/File-Spec/Spec.pm
new file mode 100644
index 00000000..40503c46
--- /dev/null
+++ b/cpan/dist/File-Spec/Spec.pm
@@ -0,0 +1,92 @@
+package File::Spec;
+
+use strict;
+use vars qw(@ISA $VERSION);
+
+$VERSION = 0.82 ;
+
+my %module = (MacOS => 'Mac',
+ MSWin32 => 'Win32',
+ os2 => 'OS2',
+ VMS => 'VMS');
+
+my $module = $module{$^O} || 'Unix';
+require "File/Spec/$module.pm";
+@ISA = ("File::Spec::$module");
+
+1;
+__END__
+
+=head1 NAME
+
+File::Spec - portably perform operations on file names
+
+=head1 SYNOPSIS
+
+ use File::Spec;
+
+ $x=File::Spec->catfile('a', 'b', 'c');
+
+which returns 'a/b/c' under Unix. Or:
+
+ use File::Spec::Functions;
+
+ $x = catfile('a', 'b', 'c');
+
+=head1 DESCRIPTION
+
+This module is designed to support operations commonly performed on file
+specifications (usually called "file names", but not to be confused with the
+contents of a file, or Perl's file handles), such as concatenating several
+directory and file names into a single path, or determining whether a path
+is rooted. It is based on code directly taken from MakeMaker 5.17, code
+written by Andreas KE<ouml>nig, Andy Dougherty, Charles Bailey, Ilya
+Zakharevich, Paul Schinder, and others.
+
+Since these functions are different for most operating systems, each set of
+OS specific routines is available in a separate module, including:
+
+ File::Spec::Unix
+ File::Spec::Mac
+ File::Spec::OS2
+ File::Spec::Win32
+ File::Spec::VMS
+
+The module appropriate for the current OS is automatically loaded by
+File::Spec. Since some modules (like VMS) make use of facilities available
+only under that OS, it may not be possible to load all modules under all
+operating systems.
+
+Since File::Spec is object oriented, subroutines should not called directly,
+as in:
+
+ File::Spec::catfile('a','b');
+
+but rather as class methods:
+
+ File::Spec->catfile('a','b');
+
+For simple uses, L<File::Spec::Functions> provides convenient functional
+forms of these methods.
+
+For a list of available methods, please consult L<File::Spec::Unix>,
+which contains the entire set, and which is inherited by the modules for
+other platforms. For further information, please see L<File::Spec::Mac>,
+L<File::Spec::OS2>, L<File::Spec::Win32>, or L<File::Spec::VMS>.
+
+=head1 SEE ALSO
+
+File::Spec::Unix, File::Spec::Mac, File::Spec::OS2, File::Spec::Win32,
+File::Spec::VMS, File::Spec::Functions, ExtUtils::MakeMaker
+
+=head1 AUTHORS
+
+Kenneth Albanowski <F<kjahds@kjahds.com>>, Andy Dougherty
+<F<doughera@lafcol.lafayette.edu>>, Andreas KE<ouml>nig
+<F<A.Koenig@franz.ww.TU-Berlin.DE>>, Tim Bunce <F<Tim.Bunce@ig.co.uk>>. VMS
+support by Charles Bailey <F<bailey@newman.upenn.edu>>. OS/2 support by
+Ilya Zakharevich <F<ilya@math.ohio-state.edu>>. Mac support by Paul Schinder
+<F<schinder@pobox.com>>. abs2rel() and rel2abs() written by
+Shigio Yamaguchi <F<shigio@tamacom.com>>, modified by Barrie Slaymaker
+<F<barries@slaysys.com>>. splitpath(), splitdir(), catpath() and catdir()
+by Barrie Slaymaker.
diff --git a/cpan/dist/File-Spec/Spec/Functions.pm b/cpan/dist/File-Spec/Spec/Functions.pm
new file mode 100644
index 00000000..0036ac1d
--- /dev/null
+++ b/cpan/dist/File-Spec/Spec/Functions.pm
@@ -0,0 +1,97 @@
+package File::Spec::Functions;
+
+use File::Spec;
+use strict;
+
+use vars qw(@ISA @EXPORT @EXPORT_OK %EXPORT_TAGS $VERSION);
+
+$VERSION = '1.1';
+
+require Exporter;
+
+@ISA = qw(Exporter);
+
+@EXPORT = qw(
+ canonpath
+ catdir
+ catfile
+ curdir
+ rootdir
+ updir
+ no_upwards
+ file_name_is_absolute
+ path
+);
+
+@EXPORT_OK = qw(
+ devnull
+ tmpdir
+ splitpath
+ splitdir
+ catpath
+ abs2rel
+ rel2abs
+);
+
+%EXPORT_TAGS = ( ALL => [ @EXPORT_OK, @EXPORT ] );
+
+foreach my $meth (@EXPORT, @EXPORT_OK) {
+ my $sub = File::Spec->can($meth);
+ no strict 'refs';
+ *{$meth} = sub {&$sub('File::Spec', @_)};
+}
+
+
+1;
+__END__
+
+=head1 NAME
+
+File::Spec::Functions - portably perform operations on file names
+
+=head1 SYNOPSIS
+
+ use File::Spec::Functions;
+ $x = catfile('a','b');
+
+=head1 DESCRIPTION
+
+This module exports convenience functions for all of the class methods
+provided by File::Spec.
+
+For a reference of available functions, please consult L<File::Spec::Unix>,
+which contains the entire set, and which is inherited by the modules for
+other platforms. For further information, please see L<File::Spec::Mac>,
+L<File::Spec::OS2>, L<File::Spec::Win32>, or L<File::Spec::VMS>.
+
+=head2 Exports
+
+The following functions are exported by default.
+
+ canonpath
+ catdir
+ catfile
+ curdir
+ rootdir
+ updir
+ no_upwards
+ file_name_is_absolute
+ path
+
+
+The following functions are exported only by request.
+
+ devnull
+ tmpdir
+ splitpath
+ splitdir
+ catpath
+ abs2rel
+ rel2abs
+
+All the functions may be imported using the C<:ALL> tag.
+
+=head1 SEE ALSO
+
+File::Spec, File::Spec::Unix, File::Spec::Mac, File::Spec::OS2,
+File::Spec::Win32, File::Spec::VMS, ExtUtils::MakeMaker
diff --git a/cpan/dist/File-Spec/Spec/Mac.pm b/cpan/dist/File-Spec/Spec/Mac.pm
new file mode 100644
index 00000000..9ef55ec8
--- /dev/null
+++ b/cpan/dist/File-Spec/Spec/Mac.pm
@@ -0,0 +1,394 @@
+package File::Spec::Mac;
+
+use strict;
+use vars qw(@ISA $VERSION);
+require File::Spec::Unix;
+
+$VERSION = '1.2';
+
+@ISA = qw(File::Spec::Unix);
+
+=head1 NAME
+
+File::Spec::Mac - File::Spec for MacOS
+
+=head1 SYNOPSIS
+
+ require File::Spec::Mac; # Done internally by File::Spec if needed
+
+=head1 DESCRIPTION
+
+Methods for manipulating file specifications.
+
+=head1 METHODS
+
+=over 2
+
+=item canonpath
+
+On MacOS, there's nothing to be done. Returns what it's given.
+
+=cut
+
+sub canonpath {
+ my ($self,$path) = @_;
+ return $path;
+}
+
+=item catdir
+
+Concatenate two or more directory names to form a complete path ending with
+a directory. Put a trailing : on the end of the complete path if there
+isn't one, because that's what's done in MacPerl's environment.
+
+The fundamental requirement of this routine is that
+
+ File::Spec->catdir(split(":",$path)) eq $path
+
+But because of the nature of Macintosh paths, some additional
+possibilities are allowed to make using this routine give reasonable results
+for some common situations. Here are the rules that are used. Each
+argument has its trailing ":" removed. Each argument, except the first,
+has its leading ":" removed. They are then joined together by a ":".
+
+So
+
+ File::Spec->catdir("a","b") = "a:b:"
+ File::Spec->catdir("a:",":b") = "a:b:"
+ File::Spec->catdir("a:","b") = "a:b:"
+ File::Spec->catdir("a",":b") = "a:b"
+ File::Spec->catdir("a","","b") = "a::b"
+
+etc.
+
+To get a relative path (one beginning with :), begin the first argument with :
+or put a "" as the first argument.
+
+If you don't want to worry about these rules, never allow a ":" on the ends
+of any of the arguments except at the beginning of the first.
+
+Under MacPerl, there is an additional ambiguity. Does the user intend that
+
+ File::Spec->catfile("LWP","Protocol","http.pm")
+
+be relative or absolute? There's no way of telling except by checking for the
+existence of LWP: or :LWP, and even there he may mean a dismounted volume or
+a relative path in a different directory (like in @INC). So those checks
+aren't done here. This routine will treat this as absolute.
+
+=cut
+
+sub catdir {
+ shift;
+ my @args = @_;
+ my $result = shift @args;
+ $result =~ s/:\Z(?!\n)//;
+ foreach (@args) {
+ s/:\Z(?!\n)//;
+ s/^://s;
+ $result .= ":$_";
+ }
+ return "$result:";
+}
+
+=item catfile
+
+Concatenate one or more directory names and a filename to form a
+complete path ending with a filename. Since this uses catdir, the
+same caveats apply. Note that the leading : is removed from the filename,
+so that
+
+ File::Spec->catfile($ENV{HOME},"file");
+
+and
+
+ File::Spec->catfile($ENV{HOME},":file");
+
+give the same answer, as one might expect.
+
+=cut
+
+sub catfile {
+ my $self = shift;
+ my $file = pop @_;
+ return $file unless @_;
+ my $dir = $self->catdir(@_);
+ $file =~ s/^://s;
+ return $dir.$file;
+}
+
+=item curdir
+
+Returns a string representing the current directory.
+
+=cut
+
+sub curdir {
+ return ":";
+}
+
+=item devnull
+
+Returns a string representing the null device.
+
+=cut
+
+sub devnull {
+ return "Dev:Null";
+}
+
+=item rootdir
+
+Returns a string representing the root directory. Under MacPerl,
+returns the name of the startup volume, since that's the closest in
+concept, although other volumes aren't rooted there.
+
+=cut
+
+sub rootdir {
+#
+# There's no real root directory on MacOS. The name of the startup
+# volume is returned, since that's the closest in concept.
+#
+ require Mac::Files;
+ my $system = Mac::Files::FindFolder(&Mac::Files::kOnSystemDisk,
+ &Mac::Files::kSystemFolderType);
+ $system =~ s/:.*\Z(?!\n)/:/s;
+ return $system;
+}
+
+=item tmpdir
+
+Returns a string representation of the first existing directory
+from the following list or '' if none exist:
+
+ $ENV{TMPDIR}
+
+=cut
+
+my $tmpdir;
+sub tmpdir {
+ return $tmpdir if defined $tmpdir;
+ $tmpdir = $ENV{TMPDIR} if -d $ENV{TMPDIR};
+ $tmpdir = '' unless defined $tmpdir;
+ return $tmpdir;
+}
+
+=item updir
+
+Returns a string representing the parent directory.
+
+=cut
+
+sub updir {
+ return "::";
+}
+
+=item file_name_is_absolute
+
+Takes as argument a path and returns true, if it is an absolute path. In
+the case where a name can be either relative or absolute (for example, a
+folder named "HD" in the current working directory on a drive named "HD"),
+relative wins. Use ":" in the appropriate place in the path if you want to
+distinguish unambiguously.
+
+As a special case, the file name '' is always considered to be absolute.
+
+=cut
+
+sub file_name_is_absolute {
+ my ($self,$file) = @_;
+ if ($file =~ /:/) {
+ return ($file !~ m/^:/s);
+ } elsif ( $file eq '' ) {
+ return 1 ;
+ } else {
+ return (! -e ":$file");
+ }
+}
+
+=item path
+
+Returns the null list for the MacPerl application, since the concept is
+usually meaningless under MacOS. But if you're using the MacPerl tool under
+MPW, it gives back $ENV{Commands} suitably split, as is done in
+:lib:ExtUtils:MM_Mac.pm.
+
+=cut
+
+sub path {
+#
+# The concept is meaningless under the MacPerl application.
+# Under MPW, it has a meaning.
+#
+ return unless exists $ENV{Commands};
+ return split(/,/, $ENV{Commands});
+}
+
+=item splitpath
+
+=cut
+
+sub splitpath {
+ my ($self,$path, $nofile) = @_;
+
+ my ($volume,$directory,$file) = ('','','');
+
+ if ( $nofile ) {
+ ( $volume, $directory ) = $path =~ m@((?:[^:]+(?::|\Z(?!\n)))?)(.*)@s;
+ }
+ else {
+ $path =~
+ m@^( (?: [^:]+: )? )
+ ( (?: .*: )? )
+ ( .* )
+ @xs;
+ $volume = $1;
+ $directory = $2;
+ $file = $3;
+ }
+
+ # Make sure non-empty volumes and directories end in ':'
+ $volume .= ':' if $volume =~ m@[^:]\Z(?!\n)@ ;
+ $directory .= ':' if $directory =~ m@[^:]\Z(?!\n)@ ;
+ return ($volume,$directory,$file);
+}
+
+
+=item splitdir
+
+=cut
+
+sub splitdir {
+ my ($self,$directories) = @_ ;
+ #
+ # split() likes to forget about trailing null fields, so here we
+ # check to be sure that there will not be any before handling the
+ # simple case.
+ #
+ if ( $directories !~ m@:\Z(?!\n)@ ) {
+ return split( m@:@, $directories );
+ }
+ else {
+ #
+ # since there was a trailing separator, add a file name to the end,
+ # then do the split, then replace it with ''.
+ #
+ my( @directories )= split( m@:@, "${directories}dummy" ) ;
+ $directories[ $#directories ]= '' ;
+ return @directories ;
+ }
+}
+
+
+=item catpath
+
+=cut
+
+sub catpath {
+ my $self = shift ;
+
+ my $result = shift ;
+ $result =~ s@^([^/])@/$1@s ;
+
+ my $segment ;
+ for $segment ( @_ ) {
+ if ( $result =~ m@[^/]\Z(?!\n)@ && $segment =~ m@^[^/]@s ) {
+ $result .= "/$segment" ;
+ }
+ elsif ( $result =~ m@/\Z(?!\n)@ && $segment =~ m@^/@s ) {
+ $result =~ s@/+\Z(?!\n)@/@;
+ $segment =~ s@^/+@@s;
+ $result .= "$segment" ;
+ }
+ else {
+ $result .= $segment ;
+ }
+ }
+
+ return $result ;
+}
+
+=item abs2rel
+
+See L<File::Spec::Unix/abs2rel> for general documentation.
+
+Unlike C<File::Spec::Unix->abs2rel()>, this function will make
+checks against the local filesystem if necessary. See
+L</file_name_is_absolute> for details.
+
+=cut
+
+sub abs2rel {
+ my($self,$path,$base) = @_;
+
+ # Clean up $path
+ if ( ! $self->file_name_is_absolute( $path ) ) {
+ $path = $self->rel2abs( $path ) ;
+ }
+
+ # Figure out the effective $base and clean it up.
+ if ( !defined( $base ) || $base eq '' ) {
+ $base = cwd() ;
+ }
+ elsif ( ! $self->file_name_is_absolute( $base ) ) {
+ $base = $self->rel2abs( $base ) ;
+ }
+
+ # Now, remove all leading components that are the same
+ my @pathchunks = $self->splitdir( $path );
+ my @basechunks = $self->splitdir( $base );
+
+ while (@pathchunks && @basechunks && $pathchunks[0] eq $basechunks[0]) {
+ shift @pathchunks ;
+ shift @basechunks ;
+ }
+
+ $path = join( ':', @pathchunks );
+
+ # @basechunks now contains the number of directories to climb out of.
+ $base = ':' x @basechunks ;
+
+ return "$base:$path" ;
+}
+
+=item rel2abs
+
+See L<File::Spec::Unix/rel2abs> for general documentation.
+
+Unlike C<File::Spec::Unix->rel2abs()>, this function will make
+checks against the local filesystem if necessary. See
+L</file_name_is_absolute> for details.
+
+=cut
+
+sub rel2abs {
+ my ($self,$path,$base ) = @_;
+
+ if ( ! $self->file_name_is_absolute( $path ) ) {
+ if ( !defined( $base ) || $base eq '' ) {
+ $base = cwd() ;
+ }
+ elsif ( ! $self->file_name_is_absolute( $base ) ) {
+ $base = $self->rel2abs( $base ) ;
+ }
+ else {
+ $base = $self->canonpath( $base ) ;
+ }
+
+ $path = $self->canonpath("$base$path") ;
+ }
+
+ return $path ;
+}
+
+
+=back
+
+=head1 SEE ALSO
+
+L<File::Spec>
+
+=cut
+
+1;
diff --git a/cpan/dist/File-Spec/Spec/OS2.pm b/cpan/dist/File-Spec/Spec/OS2.pm
new file mode 100644
index 00000000..20bf8c9d
--- /dev/null
+++ b/cpan/dist/File-Spec/Spec/OS2.pm
@@ -0,0 +1,62 @@
+package File::Spec::OS2;
+
+use strict;
+use vars qw(@ISA $VERSION);
+require File::Spec::Unix;
+
+$VERSION = '1.1';
+
+@ISA = qw(File::Spec::Unix);
+
+sub devnull {
+ return "/dev/nul";
+}
+
+sub case_tolerant {
+ return 1;
+}
+
+sub file_name_is_absolute {
+ my ($self,$file) = @_;
+ return scalar($file =~ m{^([a-z]:)?[\\/]}is);
+}
+
+sub path {
+ my $path = $ENV{PATH};
+ $path =~ s:\\:/:g;
+ my @path = split(';',$path);
+ foreach (@path) { $_ = '.' if $_ eq '' }
+ return @path;
+}
+
+my $tmpdir;
+sub tmpdir {
+ return $tmpdir if defined $tmpdir;
+ my $self = shift;
+ foreach (@ENV{qw(TMPDIR TEMP TMP)}, qw(/tmp /)) {
+ next unless defined && -d;
+ $tmpdir = $_;
+ last;
+ }
+ $tmpdir = '' unless defined $tmpdir;
+ $tmpdir =~ s:\\:/:g;
+ $tmpdir = $self->canonpath($tmpdir);
+ return $tmpdir;
+}
+
+1;
+__END__
+
+=head1 NAME
+
+File::Spec::OS2 - methods for OS/2 file specs
+
+=head1 SYNOPSIS
+
+ require File::Spec::OS2; # Done internally by File::Spec if needed
+
+=head1 DESCRIPTION
+
+See File::Spec::Unix for a documentation of the methods provided
+there. This package overrides the implementation of these methods, not
+the semantics.
diff --git a/cpan/dist/File-Spec/Spec/Unix.pm b/cpan/dist/File-Spec/Spec/Unix.pm
new file mode 100644
index 00000000..a81c5332
--- /dev/null
+++ b/cpan/dist/File-Spec/Spec/Unix.pm
@@ -0,0 +1,458 @@
+package File::Spec::Unix;
+
+use strict;
+use vars qw($VERSION);
+
+$VERSION = '1.2';
+
+use Cwd;
+
+=head1 NAME
+
+File::Spec::Unix - methods used by File::Spec
+
+=head1 SYNOPSIS
+
+ require File::Spec::Unix; # Done automatically by File::Spec
+
+=head1 DESCRIPTION
+
+Methods for manipulating file specifications.
+
+=head1 METHODS
+
+=over 2
+
+=item canonpath
+
+No physical check on the filesystem, but a logical cleanup of a
+path. On UNIX eliminated successive slashes and successive "/.".
+
+ $cpath = File::Spec->canonpath( $path ) ;
+
+=cut
+
+sub canonpath {
+ my ($self,$path) = @_;
+ $path =~ s|/+|/|g unless($^O eq 'cygwin'); # xx////xx -> xx/xx
+ $path =~ s|(/\.)+/|/|g; # xx/././xx -> xx/xx
+ $path =~ s|^(\./)+||s unless $path eq "./"; # ./xx -> xx
+ $path =~ s|^/(\.\./)+|/|s; # /../../xx -> xx
+ $path =~ s|/\Z(?!\n)|| unless $path eq "/"; # xx/ -> xx
+ return $path;
+}
+
+=item catdir
+
+Concatenate two or more directory names to form a complete path ending
+with a directory. But remove the trailing slash from the resulting
+string, because it doesn't look good, isn't necessary and confuses
+OS2. Of course, if this is the root directory, don't cut off the
+trailing slash :-)
+
+=cut
+
+sub catdir {
+ my $self = shift;
+ my @args = @_;
+ foreach (@args) {
+ # append a slash to each argument unless it has one there
+ $_ .= "/" if $_ eq '' || substr($_,-1) ne "/";
+ }
+ return $self->canonpath(join('', @args));
+}
+
+=item catfile
+
+Concatenate one or more directory names and a filename to form a
+complete path ending with a filename
+
+=cut
+
+sub catfile {
+ my $self = shift;
+ my $file = pop @_;
+ return $file unless @_;
+ my $dir = $self->catdir(@_);
+ $dir .= "/" unless substr($dir,-1) eq "/";
+ return $dir.$file;
+}
+
+=item curdir
+
+Returns a string representation of the current directory. "." on UNIX.
+
+=cut
+
+sub curdir {
+ return ".";
+}
+
+=item devnull
+
+Returns a string representation of the null device. "/dev/null" on UNIX.
+
+=cut
+
+sub devnull {
+ return "/dev/null";
+}
+
+=item rootdir
+
+Returns a string representation of the root directory. "/" on UNIX.
+
+=cut
+
+sub rootdir {
+ return "/";
+}
+
+=item tmpdir
+
+Returns a string representation of the first writable directory
+from the following list or "" if none are writable:
+
+ $ENV{TMPDIR}
+ /tmp
+
+=cut
+
+my $tmpdir;
+sub tmpdir {
+ return $tmpdir if defined $tmpdir;
+ foreach ($ENV{TMPDIR}, "/tmp") {
+ next unless defined && -d && -w _;
+ $tmpdir = $_;
+ last;
+ }
+ $tmpdir = '' unless defined $tmpdir;
+ return $tmpdir;
+}
+
+=item updir
+
+Returns a string representation of the parent directory. ".." on UNIX.
+
+=cut
+
+sub updir {
+ return "..";
+}
+
+=item no_upwards
+
+Given a list of file names, strip out those that refer to a parent
+directory. (Does not strip symlinks, only '.', '..', and equivalents.)
+
+=cut
+
+sub no_upwards {
+ my $self = shift;
+ return grep(!/^\.{1,2}\Z(?!\n)/s, @_);
+}
+
+=item case_tolerant
+
+Returns a true or false value indicating, respectively, that alphabetic
+is not or is significant when comparing file specifications.
+
+=cut
+
+sub case_tolerant {
+ return 0;
+}
+
+=item file_name_is_absolute
+
+Takes as argument a path and returns true if it is an absolute path.
+
+This does not consult the local filesystem on Unix, Win32, or OS/2. It
+does sometimes on MacOS (see L<File::Spec::MacOS/file_name_is_absolute>).
+It does consult the working environment for VMS (see
+L<File::Spec::VMS/file_name_is_absolute>).
+
+=cut
+
+sub file_name_is_absolute {
+ my ($self,$file) = @_;
+ return scalar($file =~ m:^/:s);
+}
+
+=item path
+
+Takes no argument, returns the environment variable PATH as an array.
+
+=cut
+
+sub path {
+ my @path = split(':', $ENV{PATH});
+ foreach (@path) { $_ = '.' if $_ eq '' }
+ return @path;
+}
+
+=item join
+
+join is the same as catfile.
+
+=cut
+
+sub join {
+ my $self = shift;
+ return $self->catfile(@_);
+}
+
+=item splitpath
+
+ ($volume,$directories,$file) = File::Spec->splitpath( $path );
+ ($volume,$directories,$file) = File::Spec->splitpath( $path, $no_file );
+
+Splits a path in to volume, directory, and filename portions. On systems
+with no concept of volume, returns undef for volume.
+
+For systems with no syntax differentiating filenames from directories,
+assumes that the last file is a path unless $no_file is true or a
+trailing separator or /. or /.. is present. On Unix this means that $no_file
+true makes this return ( '', $path, '' ).
+
+The directory portion may or may not be returned with a trailing '/'.
+
+The results can be passed to L</catpath()> to get back a path equivalent to
+(usually identical to) the original path.
+
+=cut
+
+sub splitpath {
+ my ($self,$path, $nofile) = @_;
+
+ my ($volume,$directory,$file) = ('','','');
+
+ if ( $nofile ) {
+ $directory = $path;
+ }
+ else {
+ $path =~ m|^ ( (?: .* / (?: \.\.?\Z(?!\n) )? )? ) ([^/]*) |xs;
+ $directory = $1;
+ $file = $2;
+ }
+
+ return ($volume,$directory,$file);
+}
+
+
+=item splitdir
+
+The opposite of L</catdir()>.
+
+ @dirs = File::Spec->splitdir( $directories );
+
+$directories must be only the directory portion of the path on systems
+that have the concept of a volume or that have path syntax that differentiates
+files from directories.
+
+Unlike just splitting the directories on the separator, empty
+directory names (C<''>) can be returned, because these are significant
+on some OSs (e.g. MacOS).
+
+On Unix,
+
+ File::Spec->splitdir( "/a/b//c/" );
+
+Yields:
+
+ ( '', 'a', 'b', '', 'c', '' )
+
+=cut
+
+sub splitdir {
+ my ($self,$directories) = @_ ;
+ #
+ # split() likes to forget about trailing null fields, so here we
+ # check to be sure that there will not be any before handling the
+ # simple case.
+ #
+ if ( $directories !~ m|/\Z(?!\n)| ) {
+ return split( m|/|, $directories );
+ }
+ else {
+ #
+ # since there was a trailing separator, add a file name to the end,
+ # then do the split, then replace it with ''.
+ #
+ my( @directories )= split( m|/|, "${directories}dummy" ) ;
+ $directories[ $#directories ]= '' ;
+ return @directories ;
+ }
+}
+
+
+=item catpath
+
+Takes volume, directory and file portions and returns an entire path. Under
+Unix, $volume is ignored, and directory and file are catenated. A '/' is
+inserted if need be. On other OSs, $volume is significant.
+
+=cut
+
+sub catpath {
+ my ($self,$volume,$directory,$file) = @_;
+
+ if ( $directory ne '' &&
+ $file ne '' &&
+ substr( $directory, -1 ) ne '/' &&
+ substr( $file, 0, 1 ) ne '/'
+ ) {
+ $directory .= "/$file" ;
+ }
+ else {
+ $directory .= $file ;
+ }
+
+ return $directory ;
+}
+
+=item abs2rel
+
+Takes a destination path and an optional base path returns a relative path
+from the base path to the destination path:
+
+ $rel_path = File::Spec->abs2rel( $path ) ;
+ $rel_path = File::Spec->abs2rel( $path, $base ) ;
+
+If $base is not present or '', then L<cwd()> is used. If $base is relative,
+then it is converted to absolute form using L</rel2abs()>. This means that it
+is taken to be relative to L<cwd()>.
+
+On systems with the concept of a volume, this assumes that both paths
+are on the $destination volume, and ignores the $base volume.
+
+On systems that have a grammar that indicates filenames, this ignores the
+$base filename as well. Otherwise all path components are assumed to be
+directories.
+
+If $path is relative, it is converted to absolute form using L</rel2abs()>.
+This means that it is taken to be relative to L<cwd()>.
+
+No checks against the filesystem are made on most systems. On MacOS,
+the filesystem may be consulted (see
+L<File::Spec::MacOS/file_name_is_absolute>). On VMS, there is
+interaction with the working environment, as logicals and
+macros are expanded.
+
+Based on code written by Shigio Yamaguchi.
+
+=cut
+
+sub abs2rel {
+ my($self,$path,$base) = @_;
+
+ # Clean up $path
+ if ( ! $self->file_name_is_absolute( $path ) ) {
+ $path = $self->rel2abs( $path ) ;
+ }
+ else {
+ $path = $self->canonpath( $path ) ;
+ }
+
+ # Figure out the effective $base and clean it up.
+ if ( !defined( $base ) || $base eq '' ) {
+ $base = cwd() ;
+ }
+ elsif ( ! $self->file_name_is_absolute( $base ) ) {
+ $base = $self->rel2abs( $base ) ;
+ }
+ else {
+ $base = $self->canonpath( $base ) ;
+ }
+
+ # Now, remove all leading components that are the same
+ my @pathchunks = $self->splitdir( $path);
+ my @basechunks = $self->splitdir( $base);
+
+ while (@pathchunks && @basechunks && $pathchunks[0] eq $basechunks[0]) {
+ shift @pathchunks ;
+ shift @basechunks ;
+ }
+
+ $path = CORE::join( '/', @pathchunks );
+ $base = CORE::join( '/', @basechunks );
+
+ # $base now contains the directories the resulting relative path
+ # must ascend out of before it can descend to $path_directory. So,
+ # replace all names with $parentDir
+ $base =~ s|[^/]+|..|g ;
+
+ # Glue the two together, using a separator if necessary, and preventing an
+ # empty result.
+ if ( $path ne '' && $base ne '' ) {
+ $path = "$base/$path" ;
+ } else {
+ $path = "$base$path" ;
+ }
+
+ return $self->canonpath( $path ) ;
+}
+
+=item rel2abs
+
+Converts a relative path to an absolute path.
+
+ $abs_path = File::Spec->rel2abs( $path ) ;
+ $abs_path = File::Spec->rel2abs( $path, $base ) ;
+
+If $base is not present or '', then L<cwd()> is used. If $base is relative,
+then it is converted to absolute form using L</rel2abs()>. This means that it
+is taken to be relative to L<cwd()>.
+
+On systems with the concept of a volume, this assumes that both paths
+are on the $base volume, and ignores the $path volume.
+
+On systems that have a grammar that indicates filenames, this ignores the
+$base filename as well. Otherwise all path components are assumed to be
+directories.
+
+If $path is absolute, it is cleaned up and returned using L</canonpath()>.
+
+No checks against the filesystem are made on most systems. On MacOS,
+the filesystem may be consulted (see
+L<File::Spec::MacOS/file_name_is_absolute>). On VMS, there is
+interaction with the working environment, as logicals and
+macros are expanded.
+
+Based on code written by Shigio Yamaguchi.
+
+=cut
+
+sub rel2abs {
+ my ($self,$path,$base ) = @_;
+
+ # Clean up $path
+ if ( ! $self->file_name_is_absolute( $path ) ) {
+ # Figure out the effective $base and clean it up.
+ if ( !defined( $base ) || $base eq '' ) {
+ $base = cwd() ;
+ }
+ elsif ( ! $self->file_name_is_absolute( $base ) ) {
+ $base = $self->rel2abs( $base ) ;
+ }
+ else {
+ $base = $self->canonpath( $base ) ;
+ }
+
+ # Glom them together
+ $path = $self->catdir( $base, $path ) ;
+ }
+
+ return $self->canonpath( $path ) ;
+}
+
+
+=back
+
+=head1 SEE ALSO
+
+L<File::Spec>
+
+=cut
+
+1;
diff --git a/cpan/dist/File-Spec/Spec/VMS.pm b/cpan/dist/File-Spec/Spec/VMS.pm
new file mode 100644
index 00000000..c19695d7
--- /dev/null
+++ b/cpan/dist/File-Spec/Spec/VMS.pm
@@ -0,0 +1,505 @@
+package File::Spec::VMS;
+
+use strict;
+use vars qw(@ISA $VERSION);
+require File::Spec::Unix;
+
+$VERSION = '1.1';
+
+@ISA = qw(File::Spec::Unix);
+
+use Cwd;
+use File::Basename;
+use VMS::Filespec;
+
+=head1 NAME
+
+File::Spec::VMS - methods for VMS file specs
+
+=head1 SYNOPSIS
+
+ require File::Spec::VMS; # Done internally by File::Spec if needed
+
+=head1 DESCRIPTION
+
+See File::Spec::Unix for a documentation of the methods provided
+there. This package overrides the implementation of these methods, not
+the semantics.
+
+=over
+
+=item eliminate_macros
+
+Expands MM[KS]/Make macros in a text string, using the contents of
+identically named elements of C<%$self>, and returns the result
+as a file specification in Unix syntax.
+
+=cut
+
+sub eliminate_macros {
+ my($self,$path) = @_;
+ return '' unless $path;
+ $self = {} unless ref $self;
+
+ if ($path =~ /\s/) {
+ return join ' ', map { $self->eliminate_macros($_) } split /\s+/, $path;
+ }
+
+ my($npath) = unixify($path);
+ my($complex) = 0;
+ my($head,$macro,$tail);
+
+ # perform m##g in scalar context so it acts as an iterator
+ while ($npath =~ m#(.*?)\$\((\S+?)\)(.*)#gs) {
+ if ($self->{$2}) {
+ ($head,$macro,$tail) = ($1,$2,$3);
+ if (ref $self->{$macro}) {
+ if (ref $self->{$macro} eq 'ARRAY') {
+ $macro = join ' ', @{$self->{$macro}};
+ }
+ else {
+ print "Note: can't expand macro \$($macro) containing ",ref($self->{$macro}),
+ "\n\t(using MMK-specific deferred substitutuon; MMS will break)\n";
+ $macro = "\cB$macro\cB";
+ $complex = 1;
+ }
+ }
+ else { ($macro = unixify($self->{$macro})) =~ s#/\Z(?!\n)##; }
+ $npath = "$head$macro$tail";
+ }
+ }
+ if ($complex) { $npath =~ s#\cB(.*?)\cB#\${$1}#gs; }
+ $npath;
+}
+
+=item fixpath
+
+Catchall routine to clean up problem MM[SK]/Make macros. Expands macros
+in any directory specification, in order to avoid juxtaposing two
+VMS-syntax directories when MM[SK] is run. Also expands expressions which
+are all macro, so that we can tell how long the expansion is, and avoid
+overrunning DCL's command buffer when MM[KS] is running.
+
+If optional second argument has a TRUE value, then the return string is
+a VMS-syntax directory specification, if it is FALSE, the return string
+is a VMS-syntax file specification, and if it is not specified, fixpath()
+checks to see whether it matches the name of a directory in the current
+default directory, and returns a directory or file specification accordingly.
+
+=cut
+
+sub fixpath {
+ my($self,$path,$force_path) = @_;
+ return '' unless $path;
+ $self = bless {} unless ref $self;
+ my($fixedpath,$prefix,$name);
+
+ if ($path =~ /\s/) {
+ return join ' ',
+ map { $self->fixpath($_,$force_path) }
+ split /\s+/, $path;
+ }
+
+ if ($path =~ m#^\$\([^\)]+\)\Z(?!\n)#s || $path =~ m#[/:>\]]#) {
+ if ($force_path or $path =~ /(?:DIR\)|\])\Z(?!\n)/) {
+ $fixedpath = vmspath($self->eliminate_macros($path));
+ }
+ else {
+ $fixedpath = vmsify($self->eliminate_macros($path));
+ }
+ }
+ elsif ((($prefix,$name) = ($path =~ m#^\$\(([^\)]+)\)(.+)#s)) && $self->{$prefix}) {
+ my($vmspre) = $self->eliminate_macros("\$($prefix)");
+ # is it a dir or just a name?
+ $vmspre = ($vmspre =~ m|/| or $prefix =~ /DIR\Z(?!\n)/) ? vmspath($vmspre) : '';
+ $fixedpath = ($vmspre ? $vmspre : $self->{$prefix}) . $name;
+ $fixedpath = vmspath($fixedpath) if $force_path;
+ }
+ else {
+ $fixedpath = $path;
+ $fixedpath = vmspath($fixedpath) if $force_path;
+ }
+ # No hints, so we try to guess
+ if (!defined($force_path) and $fixedpath !~ /[:>(.\]]/) {
+ $fixedpath = vmspath($fixedpath) if -d $fixedpath;
+ }
+
+ # Trim off root dirname if it's had other dirs inserted in front of it.
+ $fixedpath =~ s/\.000000([\]>])/$1/;
+ # Special case for VMS absolute directory specs: these will have had device
+ # prepended during trip through Unix syntax in eliminate_macros(), since
+ # Unix syntax has no way to express "absolute from the top of this device's
+ # directory tree".
+ if ($path =~ /^[\[>][^.\-]/) { $fixedpath =~ s/^[^\[<]+//; }
+ $fixedpath;
+}
+
+=back
+
+=head2 Methods always loaded
+
+=over
+
+=item canonpath (override)
+
+Removes redundant portions of file specifications according to VMS syntax.
+
+=cut
+
+sub canonpath {
+ my($self,$path) = @_;
+
+ if ($path =~ m|/|) { # Fake Unix
+ my $pathify = $path =~ m|/\Z(?!\n)|;
+ $path = $self->SUPER::canonpath($path);
+ if ($pathify) { return vmspath($path); }
+ else { return vmsify($path); }
+ }
+ else {
+ $path =~ s-\]\[--g; $path =~ s/><//g; # foo.][bar ==> foo.bar
+ $path =~ s/([\[<])000000\./$1/; # [000000.foo ==> foo
+ 1 while $path =~ s{([\[<-])\.-}{$1-}; # [.-.- ==> [--
+ $path =~ s/\.[^\[<\.]+\.-([\]\>])/$1/; # bar.foo.-] ==> bar]
+ $path =~ s/([\[<])(-+)/$1 . "\cx" x length($2)/e; # encode leading '-'s
+ $path =~ s/([\[<\.])([^\[<\.\cx]+)\.-\.?/$1/g; # bar.-.foo ==> foo
+ $path =~ s/([\[<])(\cx+)/$1 . '-' x length($2)/e; # then decode
+ return $path;
+ }
+}
+
+=item catdir
+
+Concatenates a list of file specifications, and returns the result as a
+VMS-syntax directory specification. No check is made for "impossible"
+cases (e.g. elements other than the first being absolute filespecs).
+
+=cut
+
+sub catdir {
+ my ($self,@dirs) = @_;
+ my $dir = pop @dirs;
+ @dirs = grep($_,@dirs);
+ my $rslt;
+ if (@dirs) {
+ my $path = (@dirs == 1 ? $dirs[0] : $self->catdir(@dirs));
+ my ($spath,$sdir) = ($path,$dir);
+ $spath =~ s/\.dir\Z(?!\n)//; $sdir =~ s/\.dir\Z(?!\n)//;
+ $sdir = $self->eliminate_macros($sdir) unless $sdir =~ /^[\w\-]+\Z(?!\n)/s;
+ $rslt = $self->fixpath($self->eliminate_macros($spath)."/$sdir",1);
+
+ # Special case for VMS absolute directory specs: these will have had device
+ # prepended during trip through Unix syntax in eliminate_macros(), since
+ # Unix syntax has no way to express "absolute from the top of this device's
+ # directory tree".
+ if ($spath =~ /^[\[<][^.\-]/s) { $rslt =~ s/^[^\[<]+//s; }
+ }
+ else {
+ if (not defined $dir or not length $dir) { $rslt = ''; }
+ elsif ($dir =~ /^\$\([^\)]+\)\Z(?!\n)/s) { $rslt = $dir; }
+ else { $rslt = vmspath($dir); }
+ }
+ return $self->canonpath($rslt);
+}
+
+=item catfile
+
+Concatenates a list of file specifications, and returns the result as a
+VMS-syntax file specification.
+
+=cut
+
+sub catfile {
+ my ($self,@files) = @_;
+ my $file = pop @files;
+ @files = grep($_,@files);
+ my $rslt;
+ if (@files) {
+ my $path = (@files == 1 ? $files[0] : $self->catdir(@files));
+ my $spath = $path;
+ $spath =~ s/\.dir\Z(?!\n)//;
+ if ($spath =~ /^[^\)\]\/:>]+\)\Z(?!\n)/s && basename($file) eq $file) {
+ $rslt = "$spath$file";
+ }
+ else {
+ $rslt = $self->eliminate_macros($spath);
+ $rslt = vmsify($rslt.($rslt ? '/' : '').unixify($file));
+ }
+ }
+ else { $rslt = (defined($file) && length($file)) ? vmsify($file) : ''; }
+ return $self->canonpath($rslt);
+}
+
+
+=item curdir (override)
+
+Returns a string representation of the current directory: '[]'
+
+=cut
+
+sub curdir {
+ return '[]';
+}
+
+=item devnull (override)
+
+Returns a string representation of the null device: '_NLA0:'
+
+=cut
+
+sub devnull {
+ return "_NLA0:";
+}
+
+=item rootdir (override)
+
+Returns a string representation of the root directory: 'SYS$DISK:[000000]'
+
+=cut
+
+sub rootdir {
+ return 'SYS$DISK:[000000]';
+}
+
+=item tmpdir (override)
+
+Returns a string representation of the first writable directory
+from the following list or '' if none are writable:
+
+ sys$scratch
+ $ENV{TMPDIR}
+
+=cut
+
+my $tmpdir;
+sub tmpdir {
+ return $tmpdir if defined $tmpdir;
+ foreach ('sys$scratch', $ENV{TMPDIR}) {
+ next unless defined && -d && -w _;
+ $tmpdir = $_;
+ last;
+ }
+ $tmpdir = '' unless defined $tmpdir;
+ return $tmpdir;
+}
+
+=item updir (override)
+
+Returns a string representation of the parent directory: '[-]'
+
+=cut
+
+sub updir {
+ return '[-]';
+}
+
+=item case_tolerant (override)
+
+VMS file specification syntax is case-tolerant.
+
+=cut
+
+sub case_tolerant {
+ return 1;
+}
+
+=item path (override)
+
+Translate logical name DCL$PATH as a searchlist, rather than trying
+to C<split> string value of C<$ENV{'PATH'}>.
+
+=cut
+
+sub path {
+ my (@dirs,$dir,$i);
+ while ($dir = $ENV{'DCL$PATH;' . $i++}) { push(@dirs,$dir); }
+ return @dirs;
+}
+
+=item file_name_is_absolute (override)
+
+Checks for VMS directory spec as well as Unix separators.
+
+=cut
+
+sub file_name_is_absolute {
+ my ($self,$file) = @_;
+ # If it's a logical name, expand it.
+ $file = $ENV{$file} while $file =~ /^[\w\$\-]+\Z(?!\n)/s && $ENV{$file};
+ return scalar($file =~ m!^/!s ||
+ $file =~ m![<\[][^.\-\]>]! ||
+ $file =~ /:[^<\[]/);
+}
+
+=item splitpath (override)
+
+Splits using VMS syntax.
+
+=cut
+
+sub splitpath {
+ my($self,$path) = @_;
+ my($dev,$dir,$file) = ('','','');
+
+ vmsify($path) =~ /(.+:)?([\[<].*[\]>])?(.*)/s;
+ return ($1 || '',$2 || '',$3);
+}
+
+=item splitdir (override)
+
+Split dirspec using VMS syntax.
+
+=cut
+
+sub splitdir {
+ my($self,$dirspec) = @_;
+ $dirspec =~ s/\]\[//g; $dirspec =~ s/\-\-/-.-/g;
+ $dirspec = "[$dirspec]" unless $dirspec =~ /[\[<]/; # make legal
+ my(@dirs) = split('\.', vmspath($dirspec));
+ $dirs[0] =~ s/^[\[<]//s; $dirs[-1] =~ s/[\]>]\Z(?!\n)//s;
+ @dirs;
+}
+
+
+=item catpath (override)
+
+Construct a complete filespec using VMS syntax
+
+=cut
+
+sub catpath {
+ my($self,$dev,$dir,$file) = @_;
+ if ($dev =~ m|^/+([^/]+)|) { $dev = "$1:"; }
+ else { $dev .= ':' unless $dev eq '' or $dev =~ /:\Z(?!\n)/; }
+ if (length($dev) or length($dir)) {
+ $dir = "[$dir]" unless $dir =~ /[\[<\/]/;
+ $dir = vmspath($dir);
+ }
+ "$dev$dir$file";
+}
+
+=item abs2rel (override)
+
+Use VMS syntax when converting filespecs.
+
+=cut
+
+sub abs2rel {
+ my $self = shift;
+
+ return vmspath(File::Spec::Unix::abs2rel( $self, @_ ))
+ if ( join( '', @_ ) =~ m{/} ) ;
+
+ my($path,$base) = @_;
+
+ # Note: we use '/' to glue things together here, then let canonpath()
+ # clean them up at the end.
+
+ # Clean up $path
+ if ( ! $self->file_name_is_absolute( $path ) ) {
+ $path = $self->rel2abs( $path ) ;
+ }
+ else {
+ $path = $self->canonpath( $path ) ;
+ }
+
+ # Figure out the effective $base and clean it up.
+ if ( !defined( $base ) || $base eq '' ) {
+ $base = cwd() ;
+ }
+ elsif ( ! $self->file_name_is_absolute( $base ) ) {
+ $base = $self->rel2abs( $base ) ;
+ }
+ else {
+ $base = $self->canonpath( $base ) ;
+ }
+
+ # Split up paths
+ my ( $path_directories, $path_file ) =
+ ($self->splitpath( $path, 1 ))[1,2] ;
+
+ $path_directories = $1
+ if $path_directories =~ /^\[(.*)\]\Z(?!\n)/s ;
+
+ my $base_directories = ($self->splitpath( $base, 1 ))[1] ;
+
+ $base_directories = $1
+ if $base_directories =~ /^\[(.*)\]\Z(?!\n)/s ;
+
+ # Now, remove all leading components that are the same
+ my @pathchunks = $self->splitdir( $path_directories );
+ my @basechunks = $self->splitdir( $base_directories );
+
+ while ( @pathchunks &&
+ @basechunks &&
+ lc( $pathchunks[0] ) eq lc( $basechunks[0] )
+ ) {
+ shift @pathchunks ;
+ shift @basechunks ;
+ }
+
+ # @basechunks now contains the directories to climb out of,
+ # @pathchunks now has the directories to descend in to.
+ $path_directories = '-.' x @basechunks . join( '.', @pathchunks ) ;
+ $path_directories =~ s{\.\Z(?!\n)}{} ;
+ return $self->canonpath( $self->catpath( '', $path_directories, $path_file ) ) ;
+}
+
+
+=item rel2abs (override)
+
+Use VMS syntax when converting filespecs.
+
+=cut
+
+sub rel2abs {
+ my $self = shift ;
+ return vmspath(File::Spec::Unix::rel2abs( $self, @_ ))
+ if ( join( '', @_ ) =~ m{/} ) ;
+
+ my ($path,$base ) = @_;
+ # Clean up and split up $path
+ if ( ! $self->file_name_is_absolute( $path ) ) {
+ # Figure out the effective $base and clean it up.
+ if ( !defined( $base ) || $base eq '' ) {
+ $base = cwd() ;
+ }
+ elsif ( ! $self->file_name_is_absolute( $base ) ) {
+ $base = $self->rel2abs( $base ) ;
+ }
+ else {
+ $base = $self->canonpath( $base ) ;
+ }
+
+ # Split up paths
+ my ( $path_directories, $path_file ) =
+ ($self->splitpath( $path ))[1,2] ;
+
+ my ( $base_volume, $base_directories ) =
+ $self->splitpath( $base ) ;
+
+ $path_directories = '' if $path_directories eq '[]' ||
+ $path_directories eq '<>';
+ my $sep = '' ;
+ $sep = '.'
+ if ( $base_directories =~ m{[^.\]>]\Z(?!\n)} &&
+ $path_directories =~ m{^[^.\[<]}s
+ ) ;
+ $base_directories = "$base_directories$sep$path_directories";
+ $base_directories =~ s{\.?[\]>][\[<]\.?}{.};
+
+ $path = $self->catpath( $base_volume, $base_directories, $path_file );
+ }
+
+ return $self->canonpath( $path ) ;
+}
+
+
+=back
+
+=head1 SEE ALSO
+
+L<File::Spec>
+
+=cut
+
+1;
diff --git a/cpan/dist/File-Spec/Spec/Win32.pm b/cpan/dist/File-Spec/Spec/Win32.pm
new file mode 100644
index 00000000..f5d6cda2
--- /dev/null
+++ b/cpan/dist/File-Spec/Spec/Win32.pm
@@ -0,0 +1,354 @@
+package File::Spec::Win32;
+
+use strict;
+use Cwd;
+use vars qw(@ISA $VERSION);
+require File::Spec::Unix;
+
+$VERSION = '1.2';
+
+@ISA = qw(File::Spec::Unix);
+
+=head1 NAME
+
+File::Spec::Win32 - methods for Win32 file specs
+
+=head1 SYNOPSIS
+
+ require File::Spec::Win32; # Done internally by File::Spec if needed
+
+=head1 DESCRIPTION
+
+See File::Spec::Unix for a documentation of the methods provided
+there. This package overrides the implementation of these methods, not
+the semantics.
+
+=over
+
+=item devnull
+
+Returns a string representation of the null device.
+
+=cut
+
+sub devnull {
+ return "nul";
+}
+
+=item tmpdir
+
+Returns a string representation of the first existing directory
+from the following list:
+
+ $ENV{TMPDIR}
+ $ENV{TEMP}
+ $ENV{TMP}
+ /tmp
+ /
+
+=cut
+
+my $tmpdir;
+sub tmpdir {
+ return $tmpdir if defined $tmpdir;
+ my $self = shift;
+ foreach (@ENV{qw(TMPDIR TEMP TMP)}, qw(/tmp /)) {
+ next unless defined && -d;
+ $tmpdir = $_;
+ last;
+ }
+ $tmpdir = '' unless defined $tmpdir;
+ $tmpdir = $self->canonpath($tmpdir);
+ return $tmpdir;
+}
+
+sub case_tolerant {
+ return 1;
+}
+
+sub file_name_is_absolute {
+ my ($self,$file) = @_;
+ return scalar($file =~ m{^([a-z]:)?[\\/]}is);
+}
+
+=item catfile
+
+Concatenate one or more directory names and a filename to form a
+complete path ending with a filename
+
+=cut
+
+sub catfile {
+ my $self = shift;
+ my $file = pop @_;
+ return $file unless @_;
+ my $dir = $self->catdir(@_);
+ $dir .= "\\" unless substr($dir,-1) eq "\\";
+ return $dir.$file;
+}
+
+sub path {
+ my $path = $ENV{'PATH'} || $ENV{'Path'} || $ENV{'path'};
+ my @path = split(';',$path);
+ foreach (@path) { $_ = '.' if $_ eq '' }
+ return @path;
+}
+
+=item canonpath
+
+No physical check on the filesystem, but a logical cleanup of a
+path. On UNIX eliminated successive slashes and successive "/.".
+
+=cut
+
+sub canonpath {
+ my ($self,$path) = @_;
+ $path =~ s/^([a-z]:)/\u$1/s;
+ $path =~ s|/|\\|g;
+ $path =~ s|([^\\])\\+|$1\\|g; # xx////xx -> xx/xx
+ $path =~ s|(\\\.)+\\|\\|g; # xx/././xx -> xx/xx
+ $path =~ s|^(\.\\)+||s unless $path eq ".\\"; # ./xx -> xx
+ $path =~ s|\\\Z(?!\n)||
+ unless $path =~ m#^([A-Z]:)?\\\Z(?!\n)#s; # xx/ -> xx
+ return $path;
+}
+
+=item splitpath
+
+ ($volume,$directories,$file) = File::Spec->splitpath( $path );
+ ($volume,$directories,$file) = File::Spec->splitpath( $path, $no_file );
+
+Splits a path in to volume, directory, and filename portions. Assumes that
+the last file is a path unless the path ends in '\\', '\\.', '\\..'
+or $no_file is true. On Win32 this means that $no_file true makes this return
+( $volume, $path, undef ).
+
+Separators accepted are \ and /.
+
+Volumes can be drive letters or UNC sharenames (\\server\share).
+
+The results can be passed to L</catpath> to get back a path equivalent to
+(usually identical to) the original path.
+
+=cut
+
+sub splitpath {
+ my ($self,$path, $nofile) = @_;
+ my ($volume,$directory,$file) = ('','','');
+ if ( $nofile ) {
+ $path =~
+ m{^( (?:[a-zA-Z]:|(?:\\\\|//)[^\\/]+[\\/][^\\/]+)? )
+ (.*)
+ }xs;
+ $volume = $1;
+ $directory = $2;
+ }
+ else {
+ $path =~
+ m{^ ( (?: [a-zA-Z]: |
+ (?:\\\\|//)[^\\/]+[\\/][^\\/]+
+ )?
+ )
+ ( (?:.*[\\\\/](?:\.\.?\Z(?!\n))?)? )
+ (.*)
+ }xs;
+ $volume = $1;
+ $directory = $2;
+ $file = $3;
+ }
+
+ return ($volume,$directory,$file);
+}
+
+
+=item splitdir
+
+The opposite of L</catdir()>.
+
+ @dirs = File::Spec->splitdir( $directories );
+
+$directories must be only the directory portion of the path on systems
+that have the concept of a volume or that have path syntax that differentiates
+files from directories.
+
+Unlike just splitting the directories on the separator, leading empty and
+trailing directory entries can be returned, because these are significant
+on some OSs. So,
+
+ File::Spec->splitdir( "/a/b/c" );
+
+Yields:
+
+ ( '', 'a', 'b', '', 'c', '' )
+
+=cut
+
+sub splitdir {
+ my ($self,$directories) = @_ ;
+ #
+ # split() likes to forget about trailing null fields, so here we
+ # check to be sure that there will not be any before handling the
+ # simple case.
+ #
+ if ( $directories !~ m|[\\/]\Z(?!\n)| ) {
+ return split( m|[\\/]|, $directories );
+ }
+ else {
+ #
+ # since there was a trailing separator, add a file name to the end,
+ # then do the split, then replace it with ''.
+ #
+ my( @directories )= split( m|[\\/]|, "${directories}dummy" ) ;
+ $directories[ $#directories ]= '' ;
+ return @directories ;
+ }
+}
+
+
+=item catpath
+
+Takes volume, directory and file portions and returns an entire path. Under
+Unix, $volume is ignored, and this is just like catfile(). On other OSs,
+the $volume become significant.
+
+=cut
+
+sub catpath {
+ my ($self,$volume,$directory,$file) = @_;
+
+ # If it's UNC, make sure the glue separator is there, reusing
+ # whatever separator is first in the $volume
+ $volume .= $1
+ if ( $volume =~ m@^([\\/])[\\/][^\\/]+[\\/][^\\/]+\Z(?!\n)@s &&
+ $directory =~ m@^[^\\/]@s
+ ) ;
+
+ $volume .= $directory ;
+
+ # If the volume is not just A:, make sure the glue separator is
+ # there, reusing whatever separator is first in the $volume if possible.
+ if ( $volume !~ m@^[a-zA-Z]:\Z(?!\n)@s &&
+ $volume =~ m@[^\\/]\Z(?!\n)@ &&
+ $file =~ m@[^\\/]@
+ ) {
+ $volume =~ m@([\\/])@ ;
+ my $sep = $1 ? $1 : '\\' ;
+ $volume .= $sep ;
+ }
+
+ $volume .= $file ;
+
+ return $volume ;
+}
+
+
+sub abs2rel {
+ my($self,$path,$base) = @_;
+
+ # Clean up $path
+ if ( ! $self->file_name_is_absolute( $path ) ) {
+ $path = $self->rel2abs( $path ) ;
+ }
+ else {
+ $path = $self->canonpath( $path ) ;
+ }
+
+ # Figure out the effective $base and clean it up.
+ if ( ! $self->file_name_is_absolute( $base ) ) {
+ $base = $self->rel2abs( $base ) ;
+ }
+ elsif ( !defined( $base ) || $base eq '' ) {
+ $base = cwd() ;
+ }
+ else {
+ $base = $self->canonpath( $base ) ;
+ }
+
+ # Split up paths
+ my ( $path_volume, $path_directories, $path_file ) =
+ $self->splitpath( $path, 1 ) ;
+
+ my $base_directories = ($self->splitpath( $base, 1 ))[1] ;
+
+ # Now, remove all leading components that are the same
+ my @pathchunks = $self->splitdir( $path_directories );
+ my @basechunks = $self->splitdir( $base_directories );
+
+ while ( @pathchunks &&
+ @basechunks &&
+ lc( $pathchunks[0] ) eq lc( $basechunks[0] )
+ ) {
+ shift @pathchunks ;
+ shift @basechunks ;
+ }
+
+ # No need to catdir, we know these are well formed.
+ $path_directories = CORE::join( '\\', @pathchunks );
+ $base_directories = CORE::join( '\\', @basechunks );
+
+ # $base_directories now contains the directories the resulting relative
+ # path must ascend out of before it can descend to $path_directory. So,
+ # replace all names with $parentDir
+
+ #FA Need to replace between backslashes...
+ $base_directories =~ s|[^\\]+|..|g ;
+
+ # Glue the two together, using a separator if necessary, and preventing an
+ # empty result.
+
+ #FA Must check that new directories are not empty.
+ if ( $path_directories ne '' && $base_directories ne '' ) {
+ $path_directories = "$base_directories\\$path_directories" ;
+ } else {
+ $path_directories = "$base_directories$path_directories" ;
+ }
+
+ # It makes no sense to add a relative path to a UNC volume
+ $path_volume = '' unless $path_volume =~ m{^[A-Z]:}is ;
+
+ return $self->canonpath(
+ $self->catpath($path_volume, $path_directories, $path_file )
+ ) ;
+}
+
+
+sub rel2abs {
+ my ($self,$path,$base ) = @_;
+
+ if ( ! $self->file_name_is_absolute( $path ) ) {
+
+ if ( !defined( $base ) || $base eq '' ) {
+ $base = cwd() ;
+ }
+ elsif ( ! $self->file_name_is_absolute( $base ) ) {
+ $base = $self->rel2abs( $base ) ;
+ }
+ else {
+ $base = $self->canonpath( $base ) ;
+ }
+
+ my ( $path_directories, $path_file ) =
+ ($self->splitpath( $path, 1 ))[1,2] ;
+
+ my ( $base_volume, $base_directories ) =
+ $self->splitpath( $base, 1 ) ;
+
+ $path = $self->catpath(
+ $base_volume,
+ $self->catdir( $base_directories, $path_directories ),
+ $path_file
+ ) ;
+ }
+
+ return $self->canonpath( $path ) ;
+}
+
+=back
+
+=head1 SEE ALSO
+
+L<File::Spec>
+
+=cut
+
+1;
diff --git a/cpan/dist/File-Spec/t/filefunc.t b/cpan/dist/File-Spec/t/filefunc.t
new file mode 100755
index 00000000..6e70a497
--- /dev/null
+++ b/cpan/dist/File-Spec/t/filefunc.t
@@ -0,0 +1,17 @@
+#!./perl
+
+BEGIN {
+ $^O = '';
+#chdir 't' if -d 't';
+#unshift @INC, '../lib';
+}
+
+print "1..1\n";
+
+use File::Spec::Functions;
+
+if (catfile('a','b','c') eq 'a/b/c') {
+ print "ok 1\n";
+} else {
+ print "not ok 1\n";
+}
diff --git a/cpan/dist/File-Spec/t/filespec.t b/cpan/dist/File-Spec/t/filespec.t
new file mode 100755
index 00000000..da192901
--- /dev/null
+++ b/cpan/dist/File-Spec/t/filespec.t
@@ -0,0 +1,379 @@
+#!./perl
+
+BEGIN {
+ $^O = '';
+#chdir 't' if -d 't';
+#unshift @INC, '../lib';
+}
+
+# Each element in this array is a single test. Storing them this way makes
+# maintenance easy, and should be OK since perl should be pretty functional
+# before these tests are run.
+
+@tests = (
+# Function Expected
+[ "Unix->catfile('a','b','c')", 'a/b/c' ],
+
+[ "Unix->splitpath('file')", ',,file' ],
+[ "Unix->splitpath('/d1/d2/d3/')", ',/d1/d2/d3/,' ],
+[ "Unix->splitpath('d1/d2/d3/')", ',d1/d2/d3/,' ],
+[ "Unix->splitpath('/d1/d2/d3/.')", ',/d1/d2/d3/.,' ],
+[ "Unix->splitpath('/d1/d2/d3/..')", ',/d1/d2/d3/..,' ],
+[ "Unix->splitpath('/d1/d2/d3/.file')", ',/d1/d2/d3/,.file' ],
+[ "Unix->splitpath('d1/d2/d3/file')", ',d1/d2/d3/,file' ],
+[ "Unix->splitpath('/../../d1/')", ',/../../d1/,' ],
+[ "Unix->splitpath('/././d1/')", ',/././d1/,' ],
+
+[ "Unix->catpath('','','file')", 'file' ],
+[ "Unix->catpath('','/d1/d2/d3/','')", '/d1/d2/d3/' ],
+[ "Unix->catpath('','d1/d2/d3/','')", 'd1/d2/d3/' ],
+[ "Unix->catpath('','/d1/d2/d3/.','')", '/d1/d2/d3/.' ],
+[ "Unix->catpath('','/d1/d2/d3/..','')", '/d1/d2/d3/..' ],
+[ "Unix->catpath('','/d1/d2/d3/','.file')", '/d1/d2/d3/.file' ],
+[ "Unix->catpath('','d1/d2/d3/','file')", 'd1/d2/d3/file' ],
+[ "Unix->catpath('','/../../d1/','')", '/../../d1/' ],
+[ "Unix->catpath('','/././d1/','')", '/././d1/' ],
+[ "Unix->catpath('d1','d2/d3/','')", 'd2/d3/' ],
+[ "Unix->catpath('d1','d2','d3/')", 'd2/d3/' ],
+
+[ "Unix->splitdir('')", '' ],
+[ "Unix->splitdir('/d1/d2/d3/')", ',d1,d2,d3,' ],
+[ "Unix->splitdir('d1/d2/d3/')", 'd1,d2,d3,' ],
+[ "Unix->splitdir('/d1/d2/d3')", ',d1,d2,d3' ],
+[ "Unix->splitdir('d1/d2/d3')", 'd1,d2,d3' ],
+
+[ "Unix->catdir()", '' ],
+[ "Unix->catdir('/')", '/' ],
+[ "Unix->catdir('','d1','d2','d3','')", '/d1/d2/d3' ],
+[ "Unix->catdir('d1','d2','d3','')", 'd1/d2/d3' ],
+[ "Unix->catdir('','d1','d2','d3')", '/d1/d2/d3' ],
+[ "Unix->catdir('d1','d2','d3')", 'd1/d2/d3' ],
+
+[ "Unix->catfile('a','b','c')", 'a/b/c' ],
+
+[ "Unix->canonpath('')", '' ],
+[ "Unix->canonpath('///../../..//./././a//b/.././c/././')", '/a/b/../c' ],
+[ "Unix->canonpath('/.')", '/.' ],
+
+[ "Unix->abs2rel('/t1/t2/t3','/t1/t2/t3')", '' ],
+[ "Unix->abs2rel('/t1/t2/t4','/t1/t2/t3')", '../t4' ],
+[ "Unix->abs2rel('/t1/t2','/t1/t2/t3')", '..' ],
+[ "Unix->abs2rel('/t1/t2/t3/t4','/t1/t2/t3')", 't4' ],
+[ "Unix->abs2rel('/t4/t5/t6','/t1/t2/t3')", '../../../t4/t5/t6' ],
+#[ "Unix->abs2rel('../t4','/t1/t2/t3')", '../t4' ],
+[ "Unix->abs2rel('/','/t1/t2/t3')", '../../..' ],
+[ "Unix->abs2rel('///','/t1/t2/t3')", '../../..' ],
+[ "Unix->abs2rel('/.','/t1/t2/t3')", '../../../.' ],
+[ "Unix->abs2rel('/./','/t1/t2/t3')", '../../..' ],
+#[ "Unix->abs2rel('../t4','/t1/t2/t3')", '../t4' ],
+
+[ "Unix->rel2abs('t4','/t1/t2/t3')", '/t1/t2/t3/t4' ],
+[ "Unix->rel2abs('t4/t5','/t1/t2/t3')", '/t1/t2/t3/t4/t5' ],
+[ "Unix->rel2abs('.','/t1/t2/t3')", '/t1/t2/t3' ],
+[ "Unix->rel2abs('..','/t1/t2/t3')", '/t1/t2/t3/..' ],
+[ "Unix->rel2abs('../t4','/t1/t2/t3')", '/t1/t2/t3/../t4' ],
+[ "Unix->rel2abs('/t1','/t1/t2/t3')", '/t1' ],
+
+[ "Win32->splitpath('file')", ',,file' ],
+[ "Win32->splitpath('\\d1/d2\\d3/')", ',\\d1/d2\\d3/,' ],
+[ "Win32->splitpath('d1/d2\\d3/')", ',d1/d2\\d3/,' ],
+[ "Win32->splitpath('\\d1/d2\\d3/.')", ',\\d1/d2\\d3/.,' ],
+[ "Win32->splitpath('\\d1/d2\\d3/..')", ',\\d1/d2\\d3/..,' ],
+[ "Win32->splitpath('\\d1/d2\\d3/.file')", ',\\d1/d2\\d3/,.file' ],
+[ "Win32->splitpath('\\d1/d2\\d3/file')", ',\\d1/d2\\d3/,file' ],
+[ "Win32->splitpath('d1/d2\\d3/file')", ',d1/d2\\d3/,file' ],
+[ "Win32->splitpath('C:\\d1/d2\\d3/')", 'C:,\\d1/d2\\d3/,' ],
+[ "Win32->splitpath('C:d1/d2\\d3/')", 'C:,d1/d2\\d3/,' ],
+[ "Win32->splitpath('C:\\d1/d2\\d3/file')", 'C:,\\d1/d2\\d3/,file' ],
+[ "Win32->splitpath('C:d1/d2\\d3/file')", 'C:,d1/d2\\d3/,file' ],
+[ "Win32->splitpath('C:\\../d2\\d3/file')", 'C:,\\../d2\\d3/,file' ],
+[ "Win32->splitpath('C:../d2\\d3/file')", 'C:,../d2\\d3/,file' ],
+[ "Win32->splitpath('\\../..\\d1/')", ',\\../..\\d1/,' ],
+[ "Win32->splitpath('\\./.\\d1/')", ',\\./.\\d1/,' ],
+[ "Win32->splitpath('\\\\node\\share\\d1/d2\\d3/')", '\\\\node\\share,\\d1/d2\\d3/,' ],
+[ "Win32->splitpath('\\\\node\\share\\d1/d2\\d3/file')", '\\\\node\\share,\\d1/d2\\d3/,file' ],
+[ "Win32->splitpath('\\\\node\\share\\d1/d2\\file')", '\\\\node\\share,\\d1/d2\\,file' ],
+[ "Win32->splitpath('file',1)", ',file,' ],
+[ "Win32->splitpath('\\d1/d2\\d3/',1)", ',\\d1/d2\\d3/,' ],
+[ "Win32->splitpath('d1/d2\\d3/',1)", ',d1/d2\\d3/,' ],
+[ "Win32->splitpath('\\\\node\\share\\d1/d2\\d3/',1)", '\\\\node\\share,\\d1/d2\\d3/,' ],
+
+[ "Win32->catpath('','','file')", 'file' ],
+[ "Win32->catpath('','\\d1/d2\\d3/','')", '\\d1/d2\\d3/' ],
+[ "Win32->catpath('','d1/d2\\d3/','')", 'd1/d2\\d3/' ],
+[ "Win32->catpath('','\\d1/d2\\d3/.','')", '\\d1/d2\\d3/.' ],
+[ "Win32->catpath('','\\d1/d2\\d3/..','')", '\\d1/d2\\d3/..' ],
+[ "Win32->catpath('','\\d1/d2\\d3/','.file')", '\\d1/d2\\d3/.file' ],
+[ "Win32->catpath('','\\d1/d2\\d3/','file')", '\\d1/d2\\d3/file' ],
+[ "Win32->catpath('','d1/d2\\d3/','file')", 'd1/d2\\d3/file' ],
+[ "Win32->catpath('C:','\\d1/d2\\d3/','')", 'C:\\d1/d2\\d3/' ],
+[ "Win32->catpath('C:','d1/d2\\d3/','')", 'C:d1/d2\\d3/' ],
+[ "Win32->catpath('C:','\\d1/d2\\d3/','file')", 'C:\\d1/d2\\d3/file' ],
+[ "Win32->catpath('C:','d1/d2\\d3/','file')", 'C:d1/d2\\d3/file' ],
+[ "Win32->catpath('C:','\\../d2\\d3/','file')", 'C:\\../d2\\d3/file' ],
+[ "Win32->catpath('C:','../d2\\d3/','file')", 'C:../d2\\d3/file' ],
+[ "Win32->catpath('','\\../..\\d1/','')", '\\../..\\d1/' ],
+[ "Win32->catpath('','\\./.\\d1/','')", '\\./.\\d1/' ],
+[ "Win32->catpath('\\\\node\\share','\\d1/d2\\d3/','')", '\\\\node\\share\\d1/d2\\d3/' ],
+[ "Win32->catpath('\\\\node\\share','\\d1/d2\\d3/','file')", '\\\\node\\share\\d1/d2\\d3/file' ],
+[ "Win32->catpath('\\\\node\\share','\\d1/d2\\','file')", '\\\\node\\share\\d1/d2\\file' ],
+
+[ "Win32->splitdir('')", '' ],
+[ "Win32->splitdir('\\d1/d2\\d3/')", ',d1,d2,d3,' ],
+[ "Win32->splitdir('d1/d2\\d3/')", 'd1,d2,d3,' ],
+[ "Win32->splitdir('\\d1/d2\\d3')", ',d1,d2,d3' ],
+[ "Win32->splitdir('d1/d2\\d3')", 'd1,d2,d3' ],
+
+[ "Win32->catdir()", '' ],
+[ "Win32->catdir('')", '\\' ],
+[ "Win32->catdir('/')", '\\' ],
+[ "Win32->catdir('//d1','d2')", '\\\\d1\\d2' ],
+[ "Win32->catdir('','/d1','d2')", '\\\\d1\\d2' ],
+[ "Win32->catdir('','','/d1','d2')", '\\\\\\d1\\d2' ],
+[ "Win32->catdir('','//d1','d2')", '\\\\\\d1\\d2' ],
+[ "Win32->catdir('','','//d1','d2')", '\\\\\\\\d1\\d2' ],
+[ "Win32->catdir('','d1','','d2','')", '\\d1\\d2' ],
+[ "Win32->catdir('','d1','d2','d3','')", '\\d1\\d2\\d3' ],
+[ "Win32->catdir('d1','d2','d3','')", 'd1\\d2\\d3' ],
+[ "Win32->catdir('','d1','d2','d3')", '\\d1\\d2\\d3' ],
+[ "Win32->catdir('d1','d2','d3')", 'd1\\d2\\d3' ],
+[ "Win32->catdir('A:/d1','d2','d3')", 'A:\\d1\\d2\\d3' ],
+[ "Win32->catdir('A:/d1','d2','d3','')", 'A:\\d1\\d2\\d3' ],
+#[ "Win32->catdir('A:/d1','B:/d2','d3','')", 'A:\\d1\\d2\\d3' ],
+[ "Win32->catdir('A:/d1','B:/d2','d3','')", 'A:\\d1\\B:\\d2\\d3' ],
+[ "Win32->catdir('A:/')", 'A:\\' ],
+
+[ "Win32->catfile('a','b','c')", 'a\\b\\c' ],
+
+[ "Win32->canonpath('')", '' ],
+[ "Win32->canonpath('a:')", 'A:' ],
+[ "Win32->canonpath('A:f')", 'A:f' ],
+[ "Win32->canonpath('//a\\b//c')", '\\\\a\\b\\c' ],
+[ "Win32->canonpath('/a/..../c')", '\\a\\....\\c' ],
+[ "Win32->canonpath('//a/b\\c')", '\\\\a\\b\\c' ],
+[ "Win32->canonpath('////')", '\\\\\\' ],
+[ "Win32->canonpath('//')", '\\' ],
+[ "Win32->canonpath('/.')", '\\.' ],
+[ "Win32->canonpath('//a/b/../../c')", '\\\\a\\b\\..\\..\\c' ],
+[ "Win32->canonpath('//a/../../c')", '\\\\a\\..\\..\\c' ],
+
+[ "Win32->abs2rel('/t1/t2/t3','/t1/t2/t3')", '' ],
+[ "Win32->abs2rel('/t1/t2/t4','/t1/t2/t3')", '..\\t4' ],
+[ "Win32->abs2rel('/t1/t2','/t1/t2/t3')", '..' ],
+[ "Win32->abs2rel('/t1/t2/t3/t4','/t1/t2/t3')", 't4' ],
+[ "Win32->abs2rel('/t4/t5/t6','/t1/t2/t3')", '..\\..\\..\\t4\\t5\\t6' ],
+#[ "Win32->abs2rel('../t4','/t1/t2/t3')", '\\t1\\t2\\t3\\..\\t4' ],
+[ "Win32->abs2rel('/','/t1/t2/t3')", '..\\..\\..' ],
+[ "Win32->abs2rel('///','/t1/t2/t3')", '..\\..\\..' ],
+[ "Win32->abs2rel('/.','/t1/t2/t3')", '..\\..\\..\\.' ],
+[ "Win32->abs2rel('/./','/t1/t2/t3')", '..\\..\\..' ],
+[ "Win32->abs2rel('\\\\a/t1/t2/t4','/t2/t3')", '..\\t4' ],
+[ "Win32->abs2rel('//a/t1/t2/t4','/t2/t3')", '..\\t4' ],
+
+[ "Win32->rel2abs('temp','C:/')", 'C:\\temp' ],
+[ "Win32->rel2abs('temp','C:/a')", 'C:\\a\\temp' ],
+[ "Win32->rel2abs('temp','C:/a/')", 'C:\\a\\temp' ],
+[ "Win32->rel2abs('../','C:/')", 'C:\\..' ],
+[ "Win32->rel2abs('../','C:/a')", 'C:\\a\\..' ],
+[ "Win32->rel2abs('temp','//prague_main/work/')", '\\\\prague_main\\work\\temp' ],
+[ "Win32->rel2abs('../temp','//prague_main/work/')", '\\\\prague_main\\work\\..\\temp' ],
+[ "Win32->rel2abs('temp','//prague_main/work')", '\\\\prague_main\\work\\temp' ],
+[ "Win32->rel2abs('../','//prague_main/work')", '\\\\prague_main\\work\\..' ],
+
+[ "VMS->splitpath('file')", ',,file' ],
+[ "VMS->splitpath('[d1.d2.d3]')", ',[d1.d2.d3],' ],
+[ "VMS->splitpath('[.d1.d2.d3]')", ',[.d1.d2.d3],' ],
+[ "VMS->splitpath('[d1.d2.d3]file')", ',[d1.d2.d3],file' ],
+[ "VMS->splitpath('d1/d2/d3/file')", ',[.d1.d2.d3],file' ],
+[ "VMS->splitpath('/d1/d2/d3/file')", 'd1:,[d2.d3],file' ],
+[ "VMS->splitpath('[.d1.d2.d3]file')", ',[.d1.d2.d3],file' ],
+[ "VMS->splitpath('node::volume:[d1.d2.d3]')", 'node::volume:,[d1.d2.d3],' ],
+[ "VMS->splitpath('node::volume:[d1.d2.d3]file')", 'node::volume:,[d1.d2.d3],file' ],
+[ "VMS->splitpath('node\"access_spec\"::volume:[d1.d2.d3]')", 'node"access_spec"::volume:,[d1.d2.d3],' ],
+[ "VMS->splitpath('node\"access_spec\"::volume:[d1.d2.d3]file')", 'node"access_spec"::volume:,[d1.d2.d3],file' ],
+
+[ "VMS->catpath('','','file')", 'file' ],
+[ "VMS->catpath('','[d1.d2.d3]','')", '[d1.d2.d3]' ],
+[ "VMS->catpath('','[.d1.d2.d3]','')", '[.d1.d2.d3]' ],
+[ "VMS->catpath('','[d1.d2.d3]','file')", '[d1.d2.d3]file' ],
+[ "VMS->catpath('','[.d1.d2.d3]','file')", '[.d1.d2.d3]file' ],
+[ "VMS->catpath('','d1/d2/d3','file')", '[.d1.d2.d3]file' ],
+[ "VMS->catpath('v','d1/d2/d3','file')", 'v:[.d1.d2.d3]file' ],
+[ "VMS->catpath('node::volume:','[d1.d2.d3]','')", 'node::volume:[d1.d2.d3]' ],
+[ "VMS->catpath('node::volume:','[d1.d2.d3]','file')", 'node::volume:[d1.d2.d3]file' ],
+[ "VMS->catpath('node\"access_spec\"::volume:','[d1.d2.d3]','')", 'node"access_spec"::volume:[d1.d2.d3]' ],
+[ "VMS->catpath('node\"access_spec\"::volume:','[d1.d2.d3]','file')", 'node"access_spec"::volume:[d1.d2.d3]file' ],
+
+[ "VMS->canonpath('')", '' ],
+[ "VMS->canonpath('volume:[d1]file')", 'volume:[d1]file' ],
+[ "VMS->canonpath('volume:[d1.-.d2.][d3.d4.-]')", 'volume:[d2.d3]' ],
+[ "VMS->canonpath('volume:[000000.d1]d2.dir;1')", 'volume:[d1]d2.dir;1' ],
+
+[ "VMS->splitdir('')", '' ],
+[ "VMS->splitdir('[]')", '' ],
+[ "VMS->splitdir('d1.d2.d3')", 'd1,d2,d3' ],
+[ "VMS->splitdir('[d1.d2.d3]')", 'd1,d2,d3' ],
+[ "VMS->splitdir('.d1.d2.d3')", ',d1,d2,d3' ],
+[ "VMS->splitdir('[.d1.d2.d3]')", ',d1,d2,d3' ],
+[ "VMS->splitdir('.-.d2.d3')", ',-,d2,d3' ],
+[ "VMS->splitdir('[.-.d2.d3]')", ',-,d2,d3' ],
+
+[ "VMS->catdir('')", '' ],
+[ "VMS->catdir('d1','d2','d3')", '[.d1.d2.d3]' ],
+[ "VMS->catdir('d1','d2/','d3')", '[.d1.d2.d3]' ],
+[ "VMS->catdir('','d1','d2','d3')", '[.d1.d2.d3]' ],
+[ "VMS->catdir('','-','d2','d3')", '[-.d2.d3]' ],
+[ "VMS->catdir('','-','','d3')", '[-.d3]' ],
+[ "VMS->catdir('dir.dir','d2.dir','d3.dir')", '[.dir.d2.d3]' ],
+[ "VMS->catdir('[.name]')", '[.name]' ],
+[ "VMS->catdir('[.name]','[.name]')", '[.name.name]'],
+
+[ "VMS->abs2rel('node::volume:[t1.t2.t3]','[t1.t2.t3]')", '' ],
+[ "VMS->abs2rel('node::volume:[t1.t2.t4]','[t1.t2.t3]')", '[-.t4]' ],
+[ "VMS->abs2rel('[t1.t2.t3]','[t1.t2.t3]')", '' ],
+[ "VMS->abs2rel('[t1.t2.t3]file','[t1.t2.t3]')", 'file' ],
+[ "VMS->abs2rel('[t1.t2.t4]','[t1.t2.t3]')", '[-.t4]' ],
+[ "VMS->abs2rel('[t1.t2]file','[t1.t2.t3]')", '[-]file' ],
+[ "VMS->abs2rel('[t1.t2.t3.t4]','[t1.t2.t3]')", '[t4]' ],
+[ "VMS->abs2rel('[t4.t5.t6]','[t1.t2.t3]')", '[---.t4.t5.t6]' ],
+[ "VMS->abs2rel('[000000]','[t1.t2.t3]')", '[---.000000]' ],
+[ "VMS->abs2rel('a:[t1.t2.t4]','[t1.t2.t3]')", '[-.t4]' ],
+[ "VMS->abs2rel('[a.-.b.c.-]','[t1.t2.t3]')", '[---.b]' ],
+
+[ "VMS->rel2abs('[.t4]','[t1.t2.t3]')", '[t1.t2.t3.t4]' ],
+[ "VMS->rel2abs('[.t4.t5]','[t1.t2.t3]')", '[t1.t2.t3.t4.t5]' ],
+[ "VMS->rel2abs('[]','[t1.t2.t3]')", '[t1.t2.t3]' ],
+[ "VMS->rel2abs('[-]','[t1.t2.t3]')", '[t1.t2]' ],
+[ "VMS->rel2abs('[-.t4]','[t1.t2.t3]')", '[t1.t2.t4]' ],
+[ "VMS->rel2abs('[t1]','[t1.t2.t3]')", '[t1]' ],
+
+[ "OS2->catdir('A:/d1','B:/d2','d3','')", 'A:/d1/B:/d2/d3' ],
+[ "OS2->catfile('a','b','c')", 'a/b/c' ],
+
+[ "Mac->splitpath('file')", ',,file' ],
+[ "Mac->splitpath(':file')", ',:,file' ],
+[ "Mac->splitpath(':d1',1)", ',:d1:,' ],
+[ "Mac->splitpath('d1',1)", 'd1:,,' ],
+[ "Mac->splitpath('d1:d2:d3:')", 'd1:,d2:d3:,' ],
+[ "Mac->splitpath('d1:d2:d3',1)", 'd1:,d2:d3:,' ],
+[ "Mac->splitpath(':d1:d2:d3:')", ',:d1:d2:d3:,' ],
+[ "Mac->splitpath(':d1:d2:d3:',1)", ',:d1:d2:d3:,' ],
+[ "Mac->splitpath('d1:d2:d3:file')", 'd1:,d2:d3:,file' ],
+[ "Mac->splitpath('d1:d2:d3',1)", 'd1:,d2:d3:,' ],
+
+[ "Mac->catdir('')", ':' ],
+[ "Mac->catdir('d1','d2','d3')", 'd1:d2:d3:' ],
+[ "Mac->catdir('d1','d2/','d3')", 'd1:d2/:d3:' ],
+[ "Mac->catdir('','d1','d2','d3')", ':d1:d2:d3:' ],
+[ "Mac->catdir('','','d2','d3')", '::d2:d3:' ],
+[ "Mac->catdir('','','','d3')", ':::d3:' ],
+[ "Mac->catdir(':name')", ':name:' ],
+[ "Mac->catdir(':name',':name')", ':name:name:' ],
+
+[ "Mac->catfile('a','b','c')", 'a:b:c' ],
+
+[ "Mac->canonpath('')", '' ],
+[ "Mac->canonpath(':')", ':' ],
+[ "Mac->canonpath('::')", '::' ],
+[ "Mac->canonpath('a::')", 'a::' ],
+[ "Mac->canonpath(':a::')", ':a::' ],
+
+[ "Mac->abs2rel('t1:t2:t3','t1:t2:t3')", ':' ],
+[ "Mac->abs2rel('t1:t2','t1:t2:t3')", '::' ],
+[ "Mac->abs2rel('t1:t4','t1:t2:t3')", ':::t4' ],
+[ "Mac->abs2rel('t1:t2:t4','t1:t2:t3')", '::t4' ],
+[ "Mac->abs2rel('t1:t2:t3:t4','t1:t2:t3')", ':t4' ],
+[ "Mac->abs2rel('t4:t5:t6','t1:t2:t3')", '::::t4:t5:t6' ],
+[ "Mac->abs2rel('t1','t1:t2:t3')", ':::' ],
+
+[ "Mac->rel2abs(':t4','t1:t2:t3')", 't1:t2:t3:t4' ],
+[ "Mac->rel2abs(':t4:t5','t1:t2:t3')", 't1:t2:t3:t4:t5' ],
+[ "Mac->rel2abs('','t1:t2:t3')", '' ],
+[ "Mac->rel2abs('::','t1:t2:t3')", 't1:t2:t3::' ],
+[ "Mac->rel2abs('::t4','t1:t2:t3')", 't1:t2:t3::t4' ],
+[ "Mac->rel2abs('t1','t1:t2:t3')", 't1' ],
+) ;
+
+# Grab all of the plain routines from File::Spec
+use File::Spec @File::Spec::EXPORT_OK ;
+
+require File::Spec::Unix ;
+require File::Spec::Win32 ;
+
+eval {
+ require VMS::Filespec ;
+} ;
+
+my $skip_exception = "Install VMS::Filespec (from vms/ext)" ;
+
+if ( $@ ) {
+ # Not pretty, but it allows testing of things not implemented soley
+ # on VMS. It might be better to change File::Spec::VMS to do this,
+ # making it more usable when running on (say) Unix but working with
+ # VMS paths.
+ eval qq-
+ sub File::Spec::VMS::vmsify { die "$skip_exception" }
+ sub File::Spec::VMS::unixify { die "$skip_exception" }
+ sub File::Spec::VMS::vmspath { die "$skip_exception" }
+ - ;
+ $INC{"VMS/Filespec.pm"} = 1 ;
+}
+require File::Spec::VMS ;
+
+require File::Spec::OS2 ;
+require File::Spec::Mac ;
+
+print "1..", scalar( @tests ), "\n" ;
+
+my $current_test= 1 ;
+
+# Test out the class methods
+for ( @tests ) {
+ tryfunc( @$_ ) ;
+}
+
+
+
+#
+# Tries a named function with the given args and compares the result against
+# an expected result. Works with functions that return scalars or arrays.
+#
+sub tryfunc {
+ my $function = shift ;
+ my $expected = shift ;
+ my $platform = shift ;
+
+ if ($platform && $^O ne $platform) {
+ print "ok $current_test # skipped: $function\n" ;
+ ++$current_test ;
+ return;
+ }
+
+ $function =~ s#\\#\\\\#g ;
+
+ my $got ;
+ if ( $function =~ /^[^\$].*->/ ) {
+ $got = eval( "join( ',', File::Spec::$function )" ) ;
+ }
+ else {
+ $got = eval( "join( ',', $function )" ) ;
+ }
+
+ if ( $@ ) {
+ if ( substr( $@, 0, length $skip_exception ) eq $skip_exception ) {
+ chomp $@ ;
+ print "ok $current_test # skip $function: $@\n" ;
+ }
+ else {
+ chomp $@ ;
+ print "not ok $current_test # $function: $@\n" ;
+ }
+ }
+ elsif ( !defined( $got ) || $got ne $expected ) {
+ print "not ok $current_test # $function: got '$got', expected '$expected'\n" ;
+ }
+ else {
+ print "ok $current_test # $function\n" ;
+ }
+ ++$current_test ;
+}