File Coverage

blib/lib/IO/Default.pm
Criterion Covered Total %
statement 30 67 44.7
branch 0 30 0.0
condition 0 6 0.0
subroutine 11 18 61.1
pod n/a
total 41 121 33.8


line stmt bran cond sub pod time code
1              
2             # $Id: Default.pm,v 1.3 2000/09/13 21:57:07 nwiger Exp $
3             ####################################################################
4             #
5             # Copyright (c) 2000, Nathan Wiger
6             #
7             # IO::Default - Replace select() and default filehandle with $DEFOUT
8             # Also add $DEFIN and $DEFERR variables
9             #
10             ####################################################################
11              
12             require 5.005;
13             package IO::Default;
14              
15 1     1   652 use strict;
  1         1  
  1         32  
16 1     1   5 no strict 'refs';
  1         2  
  1         30  
17 1     1   4 use vars qw(@EXPORT @ISA $VERSION $DEFOUT $DEFERR $DEFIN);
  1         11  
  1         138  
18             $VERSION = do { my @r=(q$Revision: 1.3 $=~/\d+/g); sprintf "%d."."%02d"x$#r,@r };
19              
20 1     1   4 use Exporter;
  1         2  
  1         59  
21             @ISA = qw(Exporter);
22             @EXPORT = qw($DEFOUT $DEFERR $DEFIN);
23              
24 1     1   5 use Carp;
  1         1  
  1         324  
25              
26             # This works via tie(), "plain and simple", but with a couple special
27             # subclasses since each variable is tied differently. On assignment,
28             # basically we just do some select or open calls to twiddle what
29             # we're working with. The $DEFIN handle is more complicated because
30             # it tries to override what is done with <> and .
31              
32             tie $DEFOUT, 'IO::Default::DEFOUT';
33             tie $DEFERR, 'IO::Default::DEFERR';
34             tie $DEFIN, 'IO::Default::DEFIN';
35              
36             # Stolen from CGI.pm - thanks Lincoln!
37             # Man, will I be glad when these become scalars in Perl 6...
38              
39             sub _to_filehandle {
40 0     0   0 my $thingy = shift;
41 0 0       0 return undef unless $thingy;
42 0 0       0 return $thingy if UNIVERSAL::isa($thingy,'GLOB');
43 0 0       0 return $thingy if UNIVERSAL::isa($thingy,'FileHandle');
44 0 0       0 if (!ref($thingy)) {
45 0         0 my $caller = 1;
46 0         0 while (my $package = caller($caller++)) {
47 0 0       0 my($tmp) = $thingy =~ /[\':]/ ? $thingy : "$package\:\:$thingy";
48 0 0       0 return $tmp if defined(fileno($tmp));
49             }
50             }
51 0         0 return undef;
52             }
53              
54              
55             # For $DEFOUT, we just call select() on STORE/FETCH
56              
57             package IO::Default::DEFOUT;
58 1     1   5 use Carp;
  1         1  
  1         216  
59              
60             sub TIESCALAR {
61 1     1   3 my $c = shift;
62 1         8 bless { DEFOUT => (select) }, $c;
63             }
64              
65             sub STORE {
66 0     0   0 my $c = shift;
67 0         0 my $h = IO::Default::_to_filehandle(shift);
68 0 0 0     0 return $h if ($c->{DEFOUT} and $h eq $c->{DEFOUT}); # duplicate, skip
69 0 0       0 select $h or carp "Assignment to \$DEFOUT failed: $!";
70 0         0 return $c->{DEFOUT} = $h;
71             }
72              
73             sub FETCH {
74 0     0   0 my $c = shift;
75 0         0 return $c->{DEFOUT} = select;
76             }
77              
78              
79             # For $DEFERR, we just reopen STDERR
80              
81             package IO::Default::DEFERR;
82 1     1   5 use Carp;
  1         1  
  1         218  
83              
84             sub TIESCALAR {
85 1     1   2 my $c = shift;
86 1         4 bless { DEFERR => "STDERR" }, $c;
87             }
88              
89             sub STORE {
90 0     0   0 my $c = shift;
91 0         0 my $h = IO::Default::_to_filehandle(shift);
92 0 0       0 return $h if $h eq $c->{DEFERR}; # duplicate, skip
93 0 0       0 if ( ref $h ) {
94 0         0 *STDERR = *$h; # use typeglob aliases
95             } else {
96 0 0       0 open(STDERR, ">&$h") or carp "Assignment to \$DEFERR failed: $!";
97             }
98 0         0 $c->{DEFERR} = $h;
99             }
100              
101             sub FETCH {
102 0     0   0 shift->{DEFERR};
103             }
104              
105              
106             # For $DEFIN, we just copy whatever's been passed in
107              
108             package IO::Default::DEFIN;
109 1     1   5 use Carp;
  1         2  
  1         261  
110              
111             sub TIESCALAR {
112 1     1   2 my $c = shift;
113 1         3 bless { DEFIN => undef }, $c;
114             }
115              
116             sub STORE {
117 0     0     my $c = shift;
118 0           my $h = IO::Default::_to_filehandle(shift);
119 0 0 0       return $h if ($c->{DEFERR} and $h eq $c->{DEFERR}); # duplicate, skip
120              
121             # This may seem mean, but the whole purpose of this module
122             # is to change the meaning of <> to not iterate over
123             # command-line files. As such, we need to blow away any
124             # @ARGV that's hanging around still because of ARGV's
125             # inherent special-ness.
126 0           undef @ARGV;
127              
128 0 0         if ( ref $h ) {
129 0           *ARGV = *$h; # use typeglob aliases
130             } else {
131 0 0         open(ARGV, "<&$h") or carp "Assignment to \$DEFIN failed: $!";
132             }
133 0           $c->{DEFIN} = $h;
134             }
135              
136             sub FETCH {
137 0     0     my $c = shift;
138 0           my $h = IO::Default::_to_filehandle(shift);
139 0 0         return $h if $h eq $c->{DEFIN}; # duplicate, skip
140              
141             # If we haven't set $DEFIN yet, but we're trying to
142             # read from it explicitly, then basically do what STORE
143             # does and reopen ARGV "correctly".
144 0           $c->STORE($h);
145             }
146              
147              
148             1;
149              
150             __END__