[DOC PATCH] pod syntax fixups for File::Spec::* modules
[p5sagit/p5-mst-13.2.git] / lib / File / Spec / Epoc.pm
CommitLineData
fa6a1c44 1package File::Spec::Epoc;
2
3use strict;
4use Cwd;
5use vars qw(@ISA);
6require File::Spec::Unix;
7@ISA = qw(File::Spec::Unix);
8
9=head1 NAME
10
11File::Spec::Epoc - methods for Epoc file specs
12
13=head1 SYNOPSIS
14
15 require File::Spec::Epoc; # Done internally by File::Spec if needed
16
17=head1 DESCRIPTION
18
19See File::Spec::Unix for a documentation of the methods provided
20there. This package overrides the implementation of these methods, not
21the semantics.
22
23This package is still work in progress ;-)
24o.flebbe@gmx.de
25
26
4ac9195f 27=over 4
fa6a1c44 28
29=item devnull
30
31Returns a string representation of the null device.
32
33=cut
34
35sub devnull {
36 return "nul:";
37}
38
39=item tmpdir
40
41Returns a string representation of a temporay directory:
42
43=cut
44
45my $tmpdir;
46sub tmpdir {
47 return "C:/System/temp";
48}
49
50sub case_tolerant {
51 return 1;
52}
53
54sub file_name_is_absolute {
55 my ($self,$file) = @_;
56 return scalar($file =~ m{^([a-z?]:)?[\\/]}is);
57}
58
59=item path
60
61Takes no argument, returns the environment variable PATH as an array. Since
62there is no search path supported, it returns undef, sorry.
63
64=cut
4ac9195f 65
fa6a1c44 66sub path {
67 return undef;
68}
69
59605c55 70=item canonpath()
fa6a1c44 71
72No physical check on the filesystem, but a logical cleanup of a
73path. On UNIX eliminated successive slashes and successive "/.".
74
75=cut
76
77sub canonpath {
78 my ($self,$path) = @_;
79 $path =~ s/^([a-z]:)/\u$1/s;
80
81 $path =~ s|/+|/|g unless($^O eq 'cygwin'); # xx////xx -> xx/xx
82 $path =~ s|(/\.)+/|/|g; # xx/././xx -> xx/xx
83 $path =~ s|^(\./)+||s unless $path eq "./"; # ./xx -> xx
84 $path =~ s|^/(\.\./)+|/|s; # /../../xx -> xx
85 $path =~ s|/\z|| unless $path eq "/"; # xx/ -> xx
86 return $path;
87}
88
89=item splitpath
90
91 ($volume,$directories,$file) = File::Spec->splitpath( $path );
92 ($volume,$directories,$file) = File::Spec->splitpath( $path, $no_file );
93
94Splits a path in to volume, directory, and filename portions. Assumes that
95the last file is a path unless the path ends in '\\', '\\.', '\\..'
96or $no_file is true. On Win32 this means that $no_file true makes this return
97( $volume, $path, undef ).
98
99Separators accepted are \ and /.
100
101The results can be passed to L</catpath> to get back a path equivalent to
102(usually identical to) the original path.
103
104=cut
105
106sub splitpath {
107 my ($self,$path, $nofile) = @_;
108 my ($volume,$directory,$file) = ('','','');
109 if ( $nofile ) {
110 $path =~
111 m{^( (?:[a-zA-Z?]:|(?:\\\\|//)[^\\/]+[\\/][^\\/]+)? )
112 (.*)
113 }xs;
114 $volume = $1;
115 $directory = $2;
116 }
117 else {
118 $path =~
119 m{^ ( (?: [a-zA-Z?]: |
120 (?:\\\\|//)[^\\/]+[\\/][^\\/]+
121 )?
122 )
123 ( (?:.*[\\\\/](?:\.\.?\z)?)? )
124 (.*)
125 }xs;
126 $volume = $1;
127 $directory = $2;
128 $file = $3;
129 }
130
131 return ($volume,$directory,$file);
132}
133
134
135=item splitdir
136
59605c55 137The opposite of L<catdir()|File::Spec/catdir()>.
fa6a1c44 138
139 @dirs = File::Spec->splitdir( $directories );
140
141$directories must be only the directory portion of the path on systems
142that have the concept of a volume or that have path syntax that differentiates
143files from directories.
144
145Unlike just splitting the directories on the separator, leading empty and
146trailing directory entries can be returned, because these are significant
147on some OSs. So,
148
149 File::Spec->splitdir( "/a/b/c" );
150
151Yields:
152
153 ( '', 'a', 'b', '', 'c', '' )
154
155=cut
156
157sub splitdir {
158 my ($self,$directories) = @_ ;
159 #
160 # split() likes to forget about trailing null fields, so here we
161 # check to be sure that there will not be any before handling the
162 # simple case.
163 #
164 if ( $directories !~ m|[\\/]\z| ) {
165 return split( m|[\\/]|, $directories );
166 }
167 else {
168 #
169 # since there was a trailing separator, add a file name to the end,
170 # then do the split, then replace it with ''.
171 #
172 my( @directories )= split( m|[\\/]|, "${directories}dummy" ) ;
173 $directories[ $#directories ]= '' ;
174 return @directories ;
175 }
176}
177
178
179=item catpath
180
181Takes volume, directory and file portions and returns an entire path. Under
182Unix, $volume is ignored, and this is just like catfile(). On other OSs,
183the $volume become significant.
184
185=cut
186
187sub catpath {
188 my ($self,$volume,$directory,$file) = @_;
189
190 # If it's UNC, make sure the glue separator is there, reusing
191 # whatever separator is first in the $volume
192 $volume .= $1
193 if ( $volume =~ m@^([\\/])[\\/][^\\/]+[\\/][^\\/]+\z@s &&
194 $directory =~ m@^[^\\/]@s
195 ) ;
196
197 $volume .= $directory ;
198
199 # If the volume is not just A:, make sure the glue separator is
200 # there, reusing whatever separator is first in the $volume if possible.
201 if ( $volume !~ m@^[a-zA-Z]:\z@s &&
202 $volume =~ m@[^\\/]\z@ &&
203 $file =~ m@[^\\/]@
204 ) {
205 $volume =~ m@([\\/])@ ;
206 my $sep = $1 ? $1 : '\\' ;
207 $volume .= $sep ;
208 }
209
210 $volume .= $file ;
211
212 return $volume ;
213}
214
215
216=item abs2rel
217
218Takes a destination path and an optional base path returns a relative path
219from the base path to the destination path:
220
221 $rel_path = File::Spec->abs2rel( $destination ) ;
222 $rel_path = File::Spec->abs2rel( $destination, $base ) ;
223
59605c55 224If $base is not present or '', then L<cwd()|Cwd> is used. If $base is relative,
fa6a1c44 225then it is converted to absolute form using L</rel2abs()>. This means that it
59605c55 226is taken to be relative to L<cwd()|Cwd>.
fa6a1c44 227
228On systems with the concept of a volume, this assumes that both paths
229are on the $destination volume, and ignores the $base volume.
230
231On systems that have a grammar that indicates filenames, this ignores the
232$base filename as well. Otherwise all path components are assumed to be
233directories.
234
235If $path is relative, it is converted to absolute form using L</rel2abs()>.
59605c55 236This means that it is taken to be relative to L<cwd()|Cwd>.
fa6a1c44 237
238Based on code written by Shigio Yamaguchi.
239
240No checks against the filesystem are made.
241
242=cut
243
244sub abs2rel {
245 my($self,$path,$base) = @_;
246
247 # Clean up $path
248 if ( ! $self->file_name_is_absolute( $path ) ) {
249 $path = $self->rel2abs( $path ) ;
250 }
251 else {
252 $path = $self->canonpath( $path ) ;
253 }
254
255 # Figure out the effective $base and clean it up.
256 if ( ! $self->file_name_is_absolute( $base ) ) {
257 $base = $self->rel2abs( $base ) ;
258 }
259 elsif ( !defined( $base ) || $base eq '' ) {
260 $base = cwd() ;
261 }
262 else {
263 $base = $self->canonpath( $base ) ;
264 }
265
266 # Split up paths
267 my ( $path_volume, $path_directories, $path_file ) =
268 $self->splitpath( $path, 1 ) ;
269
270 my ( undef, $base_directories, undef ) =
271 $self->splitpath( $base, 1 ) ;
272
273 # Now, remove all leading components that are the same
274 my @pathchunks = $self->splitdir( $path_directories );
275 my @basechunks = $self->splitdir( $base_directories );
276
277 while ( @pathchunks &&
278 @basechunks &&
279 lc( $pathchunks[0] ) eq lc( $basechunks[0] )
280 ) {
281 shift @pathchunks ;
282 shift @basechunks ;
283 }
284
285 # No need to catdir, we know these are well formed.
286 $path_directories = CORE::join( '\\', @pathchunks );
287 $base_directories = CORE::join( '\\', @basechunks );
288
289 # $base_directories now contains the directories the resulting relative
290 # path must ascend out of before it can descend to $path_directory. So,
291 # replace all names with $parentDir
292
293 #FA Need to replace between backslashes...
294 $base_directories =~ s|[^\\]+|..|g ;
295
296 # Glue the two together, using a separator if necessary, and preventing an
297 # empty result.
298
299 #FA Must check that new directories are not empty.
300 if ( $path_directories ne '' && $base_directories ne '' ) {
301 $path_directories = "$base_directories\\$path_directories" ;
302 } else {
303 $path_directories = "$base_directories$path_directories" ;
304 }
305
306 # It makes no sense to add a relative path to a UNC volume
307 $path_volume = '' unless $path_volume =~ m{^[A-Z]:}is ;
308
309 return $self->canonpath(
310 $self->catpath($path_volume, $path_directories, $path_file )
311 ) ;
312}
313
59605c55 314=item rel2abs()
fa6a1c44 315
316Converts a relative path to an absolute path.
317
318 $abs_path = File::Spec->rel2abs( $destination ) ;
319 $abs_path = File::Spec->rel2abs( $destination, $base ) ;
320
59605c55 321If $base is not present or '', then L<cwd()|Cwd> is used. If $base is relative,
fa6a1c44 322then it is converted to absolute form using L</rel2abs()>. This means that it
59605c55 323is taken to be relative to L<cwd()|Cwd>.
fa6a1c44 324
325Assumes that both paths are on the $base volume, and ignores the
326$destination volume.
327
328On systems that have a grammar that indicates filenames, this ignores the
329$base filename as well. Otherwise all path components are assumed to be
330directories.
331
332If $path is absolute, it is cleaned up and returned using L</canonpath()>.
333
334Based on code written by Shigio Yamaguchi.
335
336No checks against the filesystem are made.
337
338=cut
339
340sub rel2abs($;$;) {
341 my ($self,$path,$base ) = @_;
342
343 if ( ! $self->file_name_is_absolute( $path ) ) {
344
345 if ( !defined( $base ) || $base eq '' ) {
346 $base = cwd() ;
347 }
348 elsif ( ! $self->file_name_is_absolute( $base ) ) {
349 $base = $self->rel2abs( $base ) ;
350 }
351 else {
352 $base = $self->canonpath( $base ) ;
353 }
354
355 my ( undef, $path_directories, $path_file ) =
356 $self->splitpath( $path, 1 ) ;
357
358 my ( $base_volume, $base_directories, undef ) =
359 $self->splitpath( $base, 1 ) ;
360
361 $path = $self->catpath(
362 $base_volume,
363 $self->catdir( $base_directories, $path_directories ),
364 $path_file
365 ) ;
366 }
367
368 return $self->canonpath( $path ) ;
369}
370
371=back
372
373=head1 SEE ALSO
374
375L<File::Spec>
376
377=cut
378
3791;