Kludge for bareword handles
[p5sagit/p5-mst-13.2.git] / ext / FileHandle / FileHandle.pm
CommitLineData
c07a80fd 1package FileHandle;
2
3=head1 NAME
4
5FileHandle - supply object methods for filehandles
6
7=head1 SYNOPSIS
8
9 use FileHandle;
10
11 $fh = new FileHandle;
12 if ($fh->open "< file") {
13 print <$fh>;
14 $fh->close;
15 }
16
17 $fh = new FileHandle "> FOO";
18 if (defined $fh) {
19 print $fh "bar\n";
20 $fh->close;
21 }
22
23 $fh = new FileHandle "file", "r";
24 if (defined $fh) {
25 print <$fh>;
26 undef $fh; # automatically closes the file
27 }
28
29 $fh = new FileHandle "file", O_WRONLY|O_APPEND;
30 if (defined $fh) {
31 print $fh "corge\n";
32 undef $fh; # automatically closes the file
33 }
34
a5f75d66 35 $pos = $fh->getpos;
36 $fh->setpos $pos;
37
38 $fh->setvbuf($buffer_var, _IOLBF, 1024);
39
c07a80fd 40 ($readfh, $writefh) = FileHandle::pipe;
41
42 autoflush STDOUT 1;
dd7f5759 43
c07a80fd 44=head1 DESCRIPTION
45
46C<FileHandle::new> creates a C<FileHandle>, which is a reference to a
47newly created symbol (see the C<Symbol> package). If it receives any
48parameters, they are passed to C<FileHandle::open>; if the open fails,
49the C<FileHandle> object is destroyed. Otherwise, it is returned to
50the caller.
51
52C<FileHandle::new_from_fd> creates a C<FileHandle> like C<new> does.
53It requires two parameters, which are passed to C<FileHandle::fdopen>;
54if the fdopen fails, the C<FileHandle> object is destroyed.
55Otherwise, it is returned to the caller.
56
57C<FileHandle::open> accepts one parameter or two. With one parameter,
58it is just a front end for the built-in C<open> function. With two
59parameters, the first parameter is a filename that may include
60whitespace or other special characters, and the second parameter is
0cbad286 61the open mode, optionally followed by a file permission value.
62
1fef88e7 63If C<FileHandle::open> receives a Perl mode string ("E<gt>", "+E<lt>", etc.)
0cbad286 64or a POSIX fopen() mode string ("w", "r+", etc.), it uses the basic
65Perl C<open> operator.
66
67If C<FileHandle::open> is given a numeric mode, it passes that mode
68and the optional permissions value to the Perl C<sysopen> operator.
69For convenience, C<FileHandle::import> tries to import the O_XXX
70constants from the Fcntl module. If dynamic loading is not available,
71this may fail, but the rest of FileHandle will still work.
c07a80fd 72
73C<FileHandle::fdopen> is like C<open> except that its first parameter
74is not a filename but rather a file handle name, a FileHandle object,
75or a file descriptor number.
76
a5f75d66 77If the C functions fgetpos() and fsetpos() are available, then
78C<FileHandle::getpos> returns an opaque value that represents the
79current position of the FileHandle, and C<FileHandle::setpos> uses
80that value to return to a previously visited position.
81
82If the C function setvbuf() is available, then C<FileHandle::setvbuf>
83sets the buffering policy for the FileHandle. The calling sequence
84for the Perl function is the same as its C counterpart, including the
85macros C<_IOFBF>, C<_IOLBF>, and C<_IONBF>, except that the buffer
86parameter specifies a scalar variable to use as a buffer. WARNING: A
87variable used as a buffer by C<FileHandle::setvbuf> must not be
88modified in any way until the FileHandle is closed or until
89C<FileHandle::setvbuf> is called again, or memory corruption may
90result!
91
c07a80fd 92See L<perlfunc> for complete descriptions of each of the following
93supported C<FileHandle> methods, which are just front ends for the
94corresponding built-in functions:
95
96 close
97 fileno
98 getc
99 gets
100 eof
101 clearerr
102 seek
103 tell
104
105See L<perlvar> for complete descriptions of each of the following
106supported C<FileHandle> methods:
107
108 autoflush
109 output_field_separator
110 output_record_separator
111 input_record_separator
112 input_line_number
113 format_page_number
114 format_lines_per_page
115 format_lines_left
116 format_name
117 format_top_name
118 format_line_break_characters
119 format_formfeed
120
121Furthermore, for doing normal I/O you might need these:
122
123=over
124
1fef88e7 125=item $fh-E<gt>print
c07a80fd 126
127See L<perlfunc/print>.
128
1fef88e7 129=item $fh-E<gt>printf
c07a80fd 130
131See L<perlfunc/printf>.
132
1fef88e7 133=item $fh-E<gt>getline
c07a80fd 134
1fef88e7 135This works like E<lt>$fhE<gt> described in L<perlop/"I/O Operators">
c07a80fd 136except that it's more readable and can be safely called in an
137array context but still returns just one line.
138
1fef88e7 139=item $fh-E<gt>getlines
c07a80fd 140
1fef88e7 141This works like E<lt>$fhE<gt> when called in an array context to
c07a80fd 142read all the remaining lines in a file, except that it's more readable.
143It will also croak() if accidentally called in a scalar context.
144
145=back
146
147=head1 SEE ALSO
148
149L<perlfunc>,
66b5b9b7 150L<perlop/"I/O Operators">.
c07a80fd 151
152=head1 BUGS
153
154Due to backwards compatibility, all filehandles resemble objects
155of class C<FileHandle>, or actually classes derived from that class.
156They actually aren't. Which means you can't derive your own
157class from C<FileHandle> and inherit those methods.
158
159=cut
160
161require 5.000;
dd7f5759 162use vars qw($VERSION @EXPORT @EXPORT_OK $AUTOLOAD);
c07a80fd 163use Carp;
c07a80fd 164use Symbol;
c07a80fd 165use SelectSaver;
166
167require Exporter;
168require DynaLoader;
169@ISA = qw(Exporter DynaLoader);
170
66b5b9b7 171require IO::Handle; # Kludge for bareword handles
172
dd7f5759 173$VERSION = "1.00" ;
174
175@EXPORT = qw(_IOFBF _IOLBF _IONBF);
c07a80fd 176
177@EXPORT_OK = qw(
178 autoflush
179 output_field_separator
180 output_record_separator
181 input_record_separator
182 input_line_number
183 format_page_number
184 format_lines_per_page
185 format_lines_left
186 format_name
187 format_top_name
188 format_line_break_characters
189 format_formfeed
190
191 print
192 printf
193 getline
194 getlines
195);
196
197
198################################################
dd7f5759 199## If the Fcntl extension is available,
200## export its constants.
201##
202
203sub import {
204 my $pkg = shift;
205 my $callpkg = caller;
206 Exporter::export $pkg, $callpkg;
207 eval {
208 require Fcntl;
209 Exporter::export 'Fcntl', $callpkg;
210 };
211};
212
213
214################################################
c07a80fd 215## Interaction with the XS.
216##
217
dd7f5759 218eval {
219 bootstrap FileHandle;
220};
221if ($@) {
222 *constant = sub { undef };
223}
c07a80fd 224
225sub AUTOLOAD {
226 if ($AUTOLOAD =~ /::(_?[a-z])/) {
227 $AutoLoader::AUTOLOAD = $AUTOLOAD;
228 goto &AutoLoader::AUTOLOAD
229 }
230 my $constname = $AUTOLOAD;
231 $constname =~ s/.*:://;
232 my $val = constant($constname);
233 defined $val or croak "$constname is not a valid FileHandle macro";
234 *$AUTOLOAD = sub { $val };
235 goto &$AUTOLOAD;
236}
237
238
239################################################
240## Constructors, destructors.
241##
242
243sub new {
0cbad286 244 @_ >= 1 && @_ <= 4
245 or croak 'usage: new FileHandle [FILENAME [,MODE [,PERMS]]]';
c07a80fd 246 my $class = shift;
247 my $fh = gensym;
248 if (@_) {
249 FileHandle::open($fh, @_)
250 or return undef;
251 }
252 bless $fh, $class;
253}
254
255sub new_from_fd {
256 @_ == 3 or croak 'usage: new_from_fd FileHandle FD, MODE';
257 my $class = shift;
258 my $fh = gensym;
259 FileHandle::fdopen($fh, @_)
260 or return undef;
261 bless $fh, $class;
262}
263
264sub DESTROY {
265 my ($fh) = @_;
f75e77c7 266
267 # During global object destruction, this function may be called
268 # on FILEHANDLEs as well as on the GLOBs that contains them.
269 # Thus the following trickery. If only the CORE file operators
270 # could deal with FILEHANDLEs, it wouldn't be necessary...
271
272 if ($fh =~ /=FILEHANDLE\(/) {
273 local *TMP = $fh;
2c891ab9 274 close(TMP) if defined fileno(TMP);
f75e77c7 275 }
276 else {
2c891ab9 277 close($fh) if defined fileno($fh);
f75e77c7 278 }
c07a80fd 279}
280
281################################################
282## Open and close.
283##
284
285sub pipe {
286 @_ and croak 'usage: FileHandle::pipe()';
287 my $readfh = new FileHandle;
288 my $writefh = new FileHandle;
289 pipe($readfh, $writefh)
290 or return undef;
291 ($readfh, $writefh);
292}
293
294sub _open_mode_string {
295 my ($mode) = @_;
296 $mode =~ /^\+?(<|>>?)$/
297 or $mode =~ s/^r(\+?)$/$1</
298 or $mode =~ s/^w(\+?)$/$1>/
299 or $mode =~ s/^a(\+?)$/$1>>/
300 or croak "FileHandle: bad open mode: $mode";
301 $mode;
302}
303
304sub open {
305 @_ >= 2 && @_ <= 4 or croak 'usage: $fh->open(FILENAME [,MODE [,PERMS]])';
306 my ($fh, $file) = @_;
307 if (@_ > 2) {
308 my ($mode, $perms) = @_[2, 3];
309 if ($mode =~ /^\d+$/) {
310 defined $perms or $perms = 0666;
311 return sysopen($fh, $file, $mode, $perms);
312 }
313 $file = "./" . $file unless $file =~ m#^/#;
314 $file = _open_mode_string($mode) . " $file\0";
315 }
316 open($fh, $file);
317}
318
319sub fdopen {
320 @_ == 3 or croak 'usage: $fh->fdopen(FD, MODE)';
321 my ($fh, $fd, $mode) = @_;
322 if (ref($fd) =~ /GLOB\(/) {
323 # It's a glob reference; remove the star from its name.
324 ($fd = "".$$fd) =~ s/^\*//;
325 } elsif ($fd =~ m#^\d+$#) {
326 # It's an FD number; prefix with "=".
327 $fd = "=$fd";
328 }
329 open($fh, _open_mode_string($mode) . '&' . $fd);
330}
331
332sub close {
333 @_ == 1 or croak 'usage: $fh->close()';
334 close($_[0]);
335}
336
337################################################
338## Normal I/O functions.
339##
340
341sub fileno {
342 @_ == 1 or croak 'usage: $fh->fileno()';
343 fileno($_[0]);
344}
345
346sub getc {
347 @_ == 1 or croak 'usage: $fh->getc()';
348 getc($_[0]);
349}
350
351sub gets {
352 @_ == 1 or croak 'usage: $fh->gets()';
353 my ($handle) = @_;
354 scalar <$handle>;
355}
356
357sub eof {
358 @_ == 1 or croak 'usage: $fh->eof()';
359 eof($_[0]);
360}
361
362sub clearerr {
363 @_ == 1 or croak 'usage: $fh->clearerr()';
364 seek($_[0], 0, 1);
365}
366
367sub seek {
368 @_ == 3 or croak 'usage: $fh->seek(POS, WHENCE)';
369 seek($_[0], $_[1], $_[2]);
370}
371
372sub tell {
373 @_ == 1 or croak 'usage: $fh->tell()';
374 tell($_[0]);
375}
376
377sub print {
378 @_ or croak 'usage: $fh->print([ARGS])';
379 my $this = shift;
380 print $this @_;
381}
382
383sub printf {
384 @_ or croak 'usage: $fh->printf([ARGS])';
385 my $this = shift;
386 printf $this @_;
387}
388
389sub getline {
390 @_ == 1 or croak 'usage: $fh->getline';
391 my $this = shift;
392 return scalar <$this>;
393}
394
395sub getlines {
396 @_ == 1 or croak 'usage: $fh->getline()';
397 my $this = shift;
398 wantarray or croak "Can't call FileHandle::getlines in a scalar context";
399 return <$this>;
400}
401
402################################################
403## State modification functions.
404##
405
406sub autoflush {
407 my $old = new SelectSaver qualify($_[0], caller);
eb542a37 408 my $prev = $|;
409 $| = @_ > 1 ? $_[1] : 1;
c07a80fd 410 $prev;
411}
412
413sub output_field_separator {
414 my $old = new SelectSaver qualify($_[0], caller);
eb542a37 415 my $prev = $,;
416 $, = $_[1] if @_ > 1;
c07a80fd 417 $prev;
418}
419
420sub output_record_separator {
421 my $old = new SelectSaver qualify($_[0], caller);
eb542a37 422 my $prev = $\;
423 $\ = $_[1] if @_ > 1;
c07a80fd 424 $prev;
425}
426
427sub input_record_separator {
428 my $old = new SelectSaver qualify($_[0], caller);
eb542a37 429 my $prev = $/;
430 $/ = $_[1] if @_ > 1;
c07a80fd 431 $prev;
432}
433
434sub input_line_number {
435 my $old = new SelectSaver qualify($_[0], caller);
eb542a37 436 my $prev = $.;
437 $. = $_[1] if @_ > 1;
c07a80fd 438 $prev;
439}
440
441sub format_page_number {
442 my $old = new SelectSaver qualify($_[0], caller);
eb542a37 443 my $prev = $%;
444 $% = $_[1] if @_ > 1;
c07a80fd 445 $prev;
446}
447
448sub format_lines_per_page {
449 my $old = new SelectSaver qualify($_[0], caller);
eb542a37 450 my $prev = $=;
451 $= = $_[1] if @_ > 1;
c07a80fd 452 $prev;
453}
454
455sub format_lines_left {
456 my $old = new SelectSaver qualify($_[0], caller);
eb542a37 457 my $prev = $-;
458 $- = $_[1] if @_ > 1;
c07a80fd 459 $prev;
460}
461
462sub format_name {
463 my $old = new SelectSaver qualify($_[0], caller);
eb542a37 464 my $prev = $~;
465 $~ = qualify($_[1], caller) if @_ > 1;
c07a80fd 466 $prev;
467}
468
469sub format_top_name {
470 my $old = new SelectSaver qualify($_[0], caller);
eb542a37 471 my $prev = $^;
472 $^ = qualify($_[1], caller) if @_ > 1;
c07a80fd 473 $prev;
474}
475
476sub format_line_break_characters {
477 my $old = new SelectSaver qualify($_[0], caller);
eb542a37 478 my $prev = $:;
479 $: = $_[1] if @_ > 1;
c07a80fd 480 $prev;
481}
482
483sub format_formfeed {
484 my $old = new SelectSaver qualify($_[0], caller);
eb542a37 485 my $prev = $^L;
486 $^L = $_[1] if @_ > 1;
c07a80fd 487 $prev;
488}
489
4901;