File Coverage

bin/cat
Criterion Covered Total %
statement 53 80 66.2
branch 16 32 50.0
condition 4 18 22.2
subroutine 7 9 77.7
pod n/a
total 80 139 57.5


line stmt bran cond sub pod time code
1             #!/usr/bin/perl
2              
3             =begin metadata
4              
5             Name: cat
6             Description: concatenate and print files
7             Author: Abigail, perlpowertools@abigail.be
8             License: perl
9              
10             =end metadata
11              
12             =cut
13              
14 1     1   5338 use strict;
  1         2  
  1         51  
15              
16 1     1   7 use File::Basename qw(basename);
  1         2  
  1         116  
17 1     1   730 use Getopt::Std qw(getopts);
  1         2659  
  1         81  
18              
19 1     1   7 use constant EX_SUCCESS => 0;
  1         2  
  1         104  
20 1     1   6 use constant EX_FAILURE => 1;
  1         4  
  1         2540  
21              
22 1         192114 our $VERSION = '1.3';
23 1         88 my $Program = basename($0);
24              
25 1         3 my %opt;
26 1 50       9 getopts('benstuv', \%opt) or do {
27 0         0 warn "usage: $Program [-benstuv] [file ...]\n";
28 0         0 exit EX_FAILURE;
29             };
30              
31 1         63 my $ends = $opt{'e'};
32 1         4 my $tabs = $opt{'t'};
33 1   33     20 my $nonprinting = $opt{'v'} || $ends || $tabs;
34 1         3 my $squeeze_empty = $opt{'s'};
35 1   33     8 my $number_lines = $opt{'n'} && !$opt{'b'};
36 1         2 my $number_non_blanks = $opt{'b'};
37              
38 1 100       8 my $cook = grep {$_ || ()} @opt{'b', 'e', 'n', 's', 't', 'v'};
  6         20  
39 1 50       5 my $cat = $cook ? \&cook_file : \&raw_file;
40              
41             # Unbuffer output for -u.
42 1 50       3 $| = 1 if $opt{'u'};
43              
44 1         2 my $was_empty = 0;
45 1         2 my $count = 0;
46              
47 1 50       4 if (scalar(@ARGV) == 0) {
48 0         0 push @ARGV, '-';
49             }
50 1         3 my $err = 0;
51 1         3 foreach my $f (@ARGV) {
52 1         4 $err |= do_file($f);
53             }
54 1 50       0 exit ($err ? EX_FAILURE : EX_SUCCESS);
55              
56             sub VERSION_MESSAGE {
57 0     0   0 print "$Program version $VERSION\n";
58 0         0 exit EX_SUCCESS;
59             }
60              
61             sub do_file {
62 1     1   3 my $name = shift;
63              
64 1         2 my $fh;
65 1 50       4 if ($name eq '-') {
66 0         0 $fh = *STDIN;
67             } else {
68 1 50       99 if (-d $name) {
69 0         0 warn "$Program: $name: is a directory\n";
70 0         0 return 1;
71             }
72 1 50       62 if (!open($fh, '<', $name)) {
73 0         0 warn "$Program: $name: $!\n";
74 0         0 return 1;
75             }
76             }
77 1         15 $cat->($fh);
78              
79 1 50 33     17 if ($name ne '-' && !close($fh)) {
80 0         0 warn "$Program: failed to close '$name': $!\n";
81 0         0 return 1;
82             }
83 1         6 return 0;
84             }
85              
86             sub raw_file {
87 0     0   0 my $fh = shift;
88 0         0 my $BUFSZ = 8192;
89 0         0 my $buf;
90 0         0 while (read $fh, $buf, $BUFSZ) {
91 0         0 print $buf;
92             }
93             }
94              
95             sub cook_file {
96 1     1   3 my $fh = shift;
97              
98 1         56 while (<$fh>) {
99 1 50       5 if ($squeeze_empty) {
100 0         0 my $is_empty = /^$/;
101 0 0 0     0 if ($is_empty && $was_empty) {
102 0         0 next;
103             }
104 0         0 $was_empty = $is_empty;
105             }
106              
107 1 50       4 s/$/\$/ if $ends;
108 1 50       18 if ($nonprinting) {
109 0         0 s/([\x80-\xFF])/"M-" . ("\x7F" & $1)/ge;
  0         0  
110 0         0 s/([\x00-\x08\x0B-\x1F])/"^" . chr (0100 + ord $1)/ge;
  0         0  
111 0         0 s/\x7F/^?/g;
112             }
113 1 50       4 if ($tabs) {
114 0         0 s/\x09/^I/g;
115             }
116              
117 1 50 0     5 if ($number_lines || ($number_non_blanks && /\S/)) {
      33        
118 1         22 printf "%6d\t", ++$count;
119             }
120 1         12 print;
121             }
122             }
123              
124             __END__