summaryrefslogtreecommitdiff
path: root/cpan/lib/File/Spec/VMS.pm
diff options
context:
space:
mode:
Diffstat (limited to 'cpan/lib/File/Spec/VMS.pm')
-rw-r--r--cpan/lib/File/Spec/VMS.pm441
1 files changed, 255 insertions, 186 deletions
diff --git a/cpan/lib/File/Spec/VMS.pm b/cpan/lib/File/Spec/VMS.pm
index 362cdaa2..600c49fa 100644
--- a/cpan/lib/File/Spec/VMS.pm
+++ b/cpan/lib/File/Spec/VMS.pm
@@ -4,7 +4,8 @@ use strict;
use vars qw(@ISA $VERSION);
require File::Spec::Unix;
-$VERSION = '1.4';
+$VERSION = '3.62';
+$VERSION =~ tr/_//d;
@ISA = qw(File::Spec::Unix);
@@ -25,239 +26,238 @@ See File::Spec::Unix for a documentation of the methods provided
there. This package overrides the implementation of these methods, not
the semantics.
-=over 4
-
-=item eliminate_macros
+The default behavior is to allow either VMS or Unix syntax on input and to
+return VMS syntax on output unless Unix syntax has been explicitly requested
+via the C<DECC$FILENAME_UNIX_REPORT> CRTL feature.
-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.
+=over 4
=cut
-sub eliminate_macros {
- my($self,$path) = @_;
- return '' unless $path;
- $self = {} unless ref $self;
+# Need to look up the feature settings. The preferred way is to use the
+# VMS::Feature module, but that may not be available to dual life modules.
- if ($path =~ /\s/) {
- return join ' ', map { $self->eliminate_macros($_) } split /\s+/, $path;
+my $use_feature;
+BEGIN {
+ if (eval { local $SIG{__DIE__}; require VMS::Feature; }) {
+ $use_feature = 1;
}
-
- 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;
+# Need to look up the UNIX report mode. This may become a dynamic mode
+# in the future.
+sub _unix_rpt {
+ my $unix_rpt;
+ if ($use_feature) {
+ $unix_rpt = VMS::Feature::current("filename_unix_report");
+ } else {
+ my $env_unix_rpt = $ENV{'DECC$FILENAME_UNIX_REPORT'} || '';
+ $unix_rpt = $env_unix_rpt =~ /^[ET1]/i;
}
-
- # 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;
+ return $unix_rpt;
}
-=back
-
-=head2 Methods always loaded
-
-=over 4
-
=item canonpath (override)
-Removes redundant portions of file specifications according to VMS syntax.
+Removes redundant portions of file specifications and returns results
+in native syntax unless Unix filename reporting has been enabled.
=cut
+
sub canonpath {
my($self,$path) = @_;
- if ($path =~ m|/|) { # Fake Unix
+ return undef unless defined $path;
+
+ my $unix_rpt = $self->_unix_rpt;
+
+ if ($path =~ m|/|) {
my $pathify = $path =~ m|/\Z(?!\n)|;
$path = $self->SUPER::canonpath($path);
- if ($pathify) { return vmspath($path); }
- else { return vmsify($path); }
- }
- else {
- $path =~ s/([\[<])000000\./$1/g; # [000000.foo ==> [foo
- $path =~ s/([^-]+)\.(\]\[|><)?000000([\]\>])/$1$3/g; # foo.000000] ==> foo]
- $path =~ s-\]\[--g; $path =~ s/><//g; # foo.][bar ==> foo.bar
- 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
- $path =~ s/^[\[<\]>]{2}//; # []foo ==> foo
- return $path;
+
+ return $path if $unix_rpt;
+ $path = $pathify ? vmspath($path) : vmsify($path);
}
+
+ $path =~ s/(?<!\^)</[/; # < and > ==> [ and ]
+ $path =~ s/(?<!\^)>/]/;
+ $path =~ s/(?<!\^)\]\[\./\.\]\[/g; # ][. ==> .][
+ $path =~ s/(?<!\^)\[000000\.\]\[/\[/g; # [000000.][ ==> [
+ $path =~ s/(?<!\^)\[000000\./\[/g; # [000000. ==> [
+ $path =~ s/(?<!\^)\.\]\[000000\]/\]/g; # .][000000] ==> ]
+ $path =~ s/(?<!\^)\.\]\[/\./g; # foo.][bar ==> foo.bar
+ 1 while ($path =~ s/(?<!\^)([\[\.])(-+)\.(-+)([\.\]])/$1$2$3$4/);
+ # That loop does the following
+ # with any amount of dashes:
+ # .-.-. ==> .--.
+ # [-.-. ==> [--.
+ # .-.-] ==> .--]
+ # [-.-] ==> [--]
+ 1 while ($path =~ s/(?<!\^)([\[\.])[^\]\.]+\.-(-+)([\]\.])/$1$2$3/);
+ # That loop does the following
+ # with any amount (minimum 2)
+ # of dashes:
+ # .foo.--. ==> .-.
+ # .foo.--] ==> .-]
+ # [foo.--. ==> [-.
+ # [foo.--] ==> [-]
+ #
+ # And then, the remaining cases
+ $path =~ s/(?<!\^)\[\.-/[-/; # [.- ==> [-
+ $path =~ s/(?<!\^)\.[^\]\.]+\.-\./\./g; # .foo.-. ==> .
+ $path =~ s/(?<!\^)\[[^\]\.]+\.-\./\[/g; # [foo.-. ==> [
+ $path =~ s/(?<!\^)\.[^\]\.]+\.-\]/\]/g; # .foo.-] ==> ]
+ # [foo.-] ==> [000000]
+ $path =~ s/(?<!\^)\[[^\]\.]+\.-\]/\[000000\]/g;
+ # [] ==>
+ $path =~ s/(?<!\^)\[\]// unless $path eq '[]';
+ return $unix_rpt ? unixify($path) : $path;
}
-=item catdir
+=item catdir (override)
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).
+native directory specification unless the Unix filename reporting feature
+has been enabled. 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 $self = shift;
+ my $dir = pop;
+
+ my $unix_rpt = $self->_unix_rpt;
+
+ my @dirs = grep {defined() && length()} @_;
+
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".
+ $spath =~ s/\.dir\Z(?!\n)//i; $sdir =~ s/\.dir\Z(?!\n)//i;
+
+ if ($unix_rpt) {
+ $spath = unixify($spath) unless $spath =~ m#/#;
+ $sdir= unixify($sdir) unless $sdir =~ m#/#;
+ return $self->SUPER::catdir($spath, $sdir)
+ }
+
+ $rslt = vmspath( unixify($spath) . '/' . unixify($sdir));
+
+ # 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); }
+
+ } else {
+ # Single directory. Return an empty string on null input; otherwise
+ # just return a canonical path.
+
+ if (not defined $dir or not length $dir) {
+ $rslt = '';
+ } else {
+ $rslt = $unix_rpt ? $dir : vmspath($dir);
+ }
}
return $self->canonpath($rslt);
}
-=item catfile
+=item catfile (override)
-Concatenates a list of file specifications, and returns the result as a
-VMS-syntax file specification.
+Concatenates a list of directory specifications with a filename specification
+to build a path.
=cut
sub catfile {
- my ($self,@files) = @_;
- my $file = $self->canonpath(pop @files);
- @files = grep($_,@files);
+ my $self = shift;
+ my $tfile = pop();
+ my $file = $self->canonpath($tfile);
+ my @files = grep {defined() && length()} @_;
+
+ my $unix_rpt = $self->_unix_rpt;
+
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) {
+
+ # Something building a VMS path in pieces may try to pass a
+ # directory name in filename format, so normalize it.
+ $spath =~ s/\.dir\Z(?!\n)//i;
+
+ # If the spath ends with a directory delimiter and the file is bare,
+ # then just concatenate them.
+ 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 = unixify($spath);
+ $rslt .= (defined($rslt) && length($rslt) ? '/' : '') . unixify($file);
+ $rslt = vmsify($rslt) unless $unix_rpt;
}
}
- else { $rslt = (defined($file) && length($file)) ? vmsify($file) : ''; }
- return $self->canonpath($rslt);
+ else {
+ # Only passed a single file?
+ my $xfile = (defined($file) && length($file)) ? $file : '';
+
+ $rslt = $unix_rpt ? $xfile : vmsify($xfile);
+ }
+ return $self->canonpath($rslt) unless $unix_rpt;
+
+ # In Unix report mode, do not strip off redundant path information.
+ return $rslt;
}
=item curdir (override)
-Returns a string representation of the current directory: '[]'
+Returns a string representation of the current directory: '[]' or '.'
=cut
sub curdir {
+ my $self = shift @_;
+ return '.' if ($self->_unix_rpt);
return '[]';
}
=item devnull (override)
-Returns a string representation of the null device: '_NLA0:'
+Returns a string representation of the null device: '_NLA0:' or '/dev/null'
=cut
sub devnull {
+ my $self = shift @_;
+ return '/dev/null' if ($self->_unix_rpt);
return "_NLA0:";
}
=item rootdir (override)
Returns a string representation of the root directory: 'SYS$DISK:[000000]'
+or '/'
=cut
sub rootdir {
+ my $self = shift @_;
+ if ($self->_unix_rpt) {
+ # Root may exist, try it first.
+ my $try = '/';
+ my ($dev1, $ino1) = stat('/');
+ my ($dev2, $ino2) = stat('.');
+
+ # Perl falls back to '.' if it can not determine '/'
+ if (($dev1 != $dev2) || ($ino1 != $ino2)) {
+ return $try;
+ }
+ # Fall back to UNIX format sys$disk.
+ return '/sys$disk/';
+ }
return 'SYS$DISK:[000000]';
}
@@ -266,28 +266,37 @@ sub rootdir {
Returns a string representation of the first writable directory
from the following list or '' if none are writable:
+ /tmp if C<DECC$FILENAME_UNIX_REPORT> is enabled.
sys$scratch:
$ENV{TMPDIR}
-Since perl 5.8.0, if running under taint mode, and if $ENV{TMPDIR}
+If running under taint mode, and if $ENV{TMPDIR}
is tainted, it is not used.
=cut
-my $tmpdir;
sub tmpdir {
+ my $self = shift @_;
+ my $tmpdir = $self->_cached_tmpdir('TMPDIR');
return $tmpdir if defined $tmpdir;
- my $self = shift;
- $tmpdir = $self->_tmpdir( 'sys$scratch:', $ENV{TMPDIR} );
+ if ($self->_unix_rpt) {
+ $tmpdir = $self->_tmpdir('/tmp', '/sys$scratch', $ENV{TMPDIR});
+ }
+ else {
+ $tmpdir = $self->_tmpdir( 'sys$scratch:', $ENV{TMPDIR} );
+ }
+ $self->_cache_tmpdir($tmpdir, 'TMPDIR');
}
=item updir (override)
-Returns a string representation of the parent directory: '[-]'
+Returns a string representation of the parent directory: '[-]' or '..'
=cut
sub updir {
+ my $self = shift @_;
+ return '..' if ($self->_unix_rpt);
return '[-]';
}
@@ -326,34 +335,71 @@ sub file_name_is_absolute {
$file = $ENV{$file} while $file =~ /^[\w\$\-]+\Z(?!\n)/s && $ENV{$file};
return scalar($file =~ m!^/!s ||
$file =~ m![<\[][^.\-\]>]! ||
- $file =~ /:[^<\[]/);
+ $file =~ /^[A-Za-z0-9_\$\-\~]+(?<!\^):/);
}
=item splitpath (override)
-Splits using VMS syntax.
+ ($volume,$directories,$file) = File::Spec->splitpath( $path );
+ ($volume,$directories,$file) = File::Spec->splitpath( $path,
+ $no_file );
+
+Passing a true value for C<$no_file> indicates that the path being
+split only contains directory components, even on systems where you
+can usually (when not supporting a foreign syntax) tell the difference
+between directories and files at a glance.
=cut
sub splitpath {
- my($self,$path) = @_;
- my($dev,$dir,$file) = ('','','');
-
- vmsify($path) =~ /(.+:)?([\[<].*[\]>])?(.*)/s;
- return ($1 || '',$2 || '',$3);
+ my($self,$path, $nofile) = @_;
+ my($dev,$dir,$file) = ('','','');
+ my $vmsify_path = vmsify($path);
+
+ if ( $nofile ) {
+ #vmsify('d1/d2/d3') returns '[.d1.d2]d3'
+ #vmsify('/d1/d2/d3') returns 'd1:[d2]d3'
+ if( $vmsify_path =~ /(.*)\](.+)/ ){
+ $vmsify_path = $1.'.'.$2.']';
+ }
+ $vmsify_path =~ /(.+:)?(.*)/s;
+ $dir = defined $2 ? $2 : ''; # dir can be '0'
+ return ($1 || '',$dir,$file);
+ }
+ else {
+ $vmsify_path =~ /(.+:)?([\[<].*[\]>])?(.*)/s;
+ return ($1 || '',$2 || '',$3);
+ }
}
=item splitdir (override)
-Split dirspec using VMS syntax.
+Split a directory specification into the components.
=cut
sub splitdir {
my($self,$dirspec) = @_;
- $dirspec =~ s/\]\[//g; $dirspec =~ s/\-\-/-.-/g;
- $dirspec = "[$dirspec]" unless $dirspec =~ /[\[<]/; # make legal
- my(@dirs) = split('\.', vmspath($dirspec));
+ my @dirs = ();
+ return @dirs if ( (!defined $dirspec) || ('' eq $dirspec) );
+
+ $dirspec =~ s/(?<!\^)</[/; # < and > ==> [ and ]
+ $dirspec =~ s/(?<!\^)>/]/;
+ $dirspec =~ s/(?<!\^)\]\[\./\.\]\[/g; # ][. ==> .][
+ $dirspec =~ s/(?<!\^)\[000000\.\]\[/\[/g; # [000000.][ ==> [
+ $dirspec =~ s/(?<!\^)\[000000\./\[/g; # [000000. ==> [
+ $dirspec =~ s/(?<!\^)\.\]\[000000\]/\]/g; # .][000000] ==> ]
+ $dirspec =~ s/(?<!\^)\.\]\[/\./g; # foo.][bar ==> foo.bar
+ while ($dirspec =~ s/(^|[\[\<\.])\-(\-+)($|[\]\>\.])/$1-.$2$3/g) {}
+ # That loop does the following
+ # with any amount of dashes:
+ # .--. ==> .-.-.
+ # [--. ==> [-.-.
+ # .--] ==> .-.-]
+ # [--] ==> [-.-]
+ $dirspec = "[$dirspec]" unless $dirspec =~ /(?<!\^)[\[<]/; # make legal
+ $dirspec =~ s/^(\[|<)\./$1/;
+ @dirs = split /(?<!\^)\./, vmspath($dirspec);
$dirs[0] =~ s/^[\[<]//s; $dirs[-1] =~ s/[\]>]\Z(?!\n)//s;
@dirs;
}
@@ -361,7 +407,7 @@ sub splitdir {
=item catpath (override)
-Construct a complete filespec using VMS syntax
+Construct a complete filespec.
=cut
@@ -373,30 +419,35 @@ sub catpath {
$dev = $dir_volume unless length $dev;
$dir = length $dir_file ? $self->catfile($dir_dir, $dir_file) : $dir_dir;
- if ($dev =~ m|^/+([^/]+)|) { $dev = "$1:"; }
+ 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);
+ $dir = "[$dir]" unless $dir =~ /(?<!\^)[\[<\/]/;
+ $dir = vmspath($dir);
}
+ $dir = '' if length($dev) && ($dir eq '[]' || $dir eq '<>');
"$dev$dir$file";
}
=item abs2rel (override)
-Use VMS syntax when converting filespecs.
+Attempt to convert an absolute file specification to a relative specification.
=cut
sub abs2rel {
my $self = shift;
return vmspath(File::Spec::Unix::abs2rel( $self, @_ ))
- if grep m{/}, @_;
+ if ((grep m{/}, @_) && !(grep m{(?<!\^)[\[<:]}, @_));
my($path,$base) = @_;
$base = $self->_cwd() unless defined $base and length $base;
- for ($path, $base) { $_ = $self->canonpath($_) }
+ # If there is no device or directory syntax on $base, make sure it
+ # is treated as a directory.
+ $base = VMS::Filespec::vmspath($base) unless $base =~ m{(?<!\^)[\[<:]};
+
+ for ($path, $base) { $_ = $self->rel2abs($_) }
# Are we even starting $path on the same (node::)device as $base? Note that
# logical paths or nodename differences may be on the "same device"
@@ -412,12 +463,12 @@ sub abs2rel {
my ($base_volume, $base_directories, $base_file) = $self->splitpath($base);
return $path unless lc($path_volume) eq lc($base_volume);
- for ($path, $base) { $_ = $self->rel2abs($_) }
-
# Now, remove all leading components that are the same
my @pathchunks = $self->splitdir( $path_directories );
+ my $pathchunks = @pathchunks;
unshift(@pathchunks,'000000') unless $pathchunks[0] eq '000000';
my @basechunks = $self->splitdir( $base_directories );
+ my $basechunks = @basechunks;
unshift(@basechunks,'000000') unless $basechunks[0] eq '000000';
while ( @pathchunks &&
@@ -430,23 +481,34 @@ sub abs2rel {
# @basechunks now contains the directories to climb out of,
# @pathchunks now has the directories to descend in to.
- $path_directories = join '.', ('-' x @basechunks, @pathchunks) ;
+ if ((@basechunks > 0) || ($basechunks != $pathchunks)) {
+ $path_directories = join '.', ('-' x @basechunks, @pathchunks) ;
+ }
+ else {
+ $path_directories = join '.', @pathchunks;
+ }
+ $path_directories = '['.$path_directories.']';
return $self->canonpath( $self->catpath( '', $path_directories, $path_file ) ) ;
}
=item rel2abs (override)
-Use VMS syntax when converting filespecs.
+Return an absolute file specification from a relative one.
=cut
sub rel2abs {
my $self = shift ;
- return vmspath(File::Spec::Unix::rel2abs( $self, @_ ))
- if ( join( '', @_ ) =~ m{/} ) ;
-
my ($path,$base ) = @_;
+ return undef unless defined $path;
+ if ($path =~ m/\//) {
+ $path = ( -d $path || $path =~ m/\/\z/ # educated guessing about
+ ? vmspath($path) # whether it's a directory
+ : vmsify($path) );
+ }
+ $base = vmspath($base) if defined $base && $base =~ m/\//;
+
# Clean up and split up $path
if ( ! $self->file_name_is_absolute( $path ) ) {
# Figure out the effective $base and clean it up.
@@ -486,13 +548,20 @@ sub rel2abs {
=back
+=head1 COPYRIGHT
+
+Copyright (c) 2004-14 by the Perl 5 Porters. All rights reserved.
+
+This program is free software; you can redistribute it and/or modify
+it under the same terms as Perl itself.
+
=head1 SEE ALSO
See L<File::Spec> and L<File::Spec::Unix>. This package overrides the
implementation of these methods, not the semantics.
An explanation of VMS file specs can be found at
-L<"http://h71000.www7.hp.com/doc/731FINAL/4506/4506pro_014.html#apps_locating_naming_files">.
+L<http://h71000.www7.hp.com/doc/731FINAL/4506/4506pro_014.html#apps_locating_naming_files>.
=cut