line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
# $Id: File.pm,v 1.3 2006/11/03 20:59:19 mike Exp $ |
2
|
|
|
|
|
|
|
|
3
|
|
|
|
|
|
|
# File.pm - a cleverer IO::File-alike that does pushback |
4
|
|
|
|
|
|
|
|
5
|
|
|
|
|
|
|
package Games::ScottAdams::File; |
6
|
1
|
|
|
1
|
|
7
|
use strict; |
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
43
|
|
7
|
|
|
|
|
|
|
|
8
|
|
|
|
|
|
|
# This module simply implements a slightly cleverer IO::File-alike |
9
|
|
|
|
|
|
|
# that remembers the filename, maintains a notion of the current line |
10
|
|
|
|
|
|
|
# number (useful for diagnostics) and can maintain an arbitrary number |
11
|
|
|
|
|
|
|
# of pushback lines. It clearly has wider applicability outside of |
12
|
|
|
|
|
|
|
# the Scott Adams module and should probably not be a |
13
|
|
|
|
|
|
|
# Games::ScottAdams class. |
14
|
|
|
|
|
|
|
|
15
|
1
|
|
|
1
|
|
1204
|
use IO::File; |
|
1
|
|
|
|
|
15634
|
|
|
1
|
|
|
|
|
1065
|
|
16
|
|
|
|
|
|
|
|
17
|
|
|
|
|
|
|
|
18
|
|
|
|
|
|
|
sub new { |
19
|
5
|
|
|
5
|
0
|
8
|
my $class = shift(); |
20
|
5
|
|
|
|
|
7
|
my($filename) = @_; |
21
|
|
|
|
|
|
|
|
22
|
5
|
50
|
|
|
|
41
|
my $f = new IO::File("<$filename") |
23
|
|
|
|
|
|
|
or return undef; |
24
|
|
|
|
|
|
|
|
25
|
5
|
|
|
|
|
492
|
return bless { |
26
|
|
|
|
|
|
|
f => $f, |
27
|
|
|
|
|
|
|
filename => $filename, |
28
|
|
|
|
|
|
|
linenumber => 0, |
29
|
|
|
|
|
|
|
pushback => [], |
30
|
|
|
|
|
|
|
buf => "", # for getint() and getstring() only |
31
|
|
|
|
|
|
|
}, $class; |
32
|
|
|
|
|
|
|
} |
33
|
|
|
|
|
|
|
|
34
|
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
sub getline { |
36
|
676
|
|
|
676
|
0
|
873
|
my $this = shift(); |
37
|
676
|
|
|
|
|
734
|
my($trim) = @_; |
38
|
|
|
|
|
|
|
|
39
|
676
|
|
|
|
|
701
|
my $line = pop @{ $this->{pushback} }; |
|
676
|
|
|
|
|
1268
|
|
40
|
847
|
100
|
|
|
|
1796
|
if (!defined $line) { |
41
|
666
|
|
|
|
|
976
|
AGAIN: |
42
|
|
|
|
|
|
|
$this->{linenumber}++; |
43
|
666
|
|
|
|
|
16625
|
$line = $this->{f}->getline(); |
44
|
666
|
100
|
|
|
|
33476
|
return undef if !defined $line; |
45
|
|
|
|
|
|
|
} |
46
|
|
|
|
|
|
|
|
47
|
841
|
50
|
|
|
|
1564
|
if ($trim) { |
48
|
841
|
|
|
|
|
1331
|
$line =~ s/#.*//; |
49
|
841
|
|
|
|
|
2589
|
$line =~ s/\s+$//; |
50
|
841
|
100
|
|
|
|
7822
|
goto AGAIN if $line =~ /^$/; |
51
|
|
|
|
|
|
|
} |
52
|
|
|
|
|
|
|
|
53
|
670
|
|
|
|
|
2432
|
return $line; |
54
|
|
|
|
|
|
|
} |
55
|
|
|
|
|
|
|
|
56
|
|
|
|
|
|
|
|
57
|
|
|
|
|
|
|
sub ungetline { |
58
|
181
|
|
|
181
|
0
|
220
|
my $this = shift(); |
59
|
181
|
|
|
|
|
226
|
my($line) = @_; |
60
|
|
|
|
|
|
|
|
61
|
181
|
|
|
|
|
188
|
push @{ $this->{pushback} }, $line; |
|
181
|
|
|
|
|
572
|
|
62
|
|
|
|
|
|
|
} |
63
|
|
|
|
|
|
|
|
64
|
|
|
|
|
|
|
|
65
|
|
|
|
|
|
|
# Calls to getint() and getstring() may be freely intermixed, but |
66
|
|
|
|
|
|
|
# won't play nice if mixed with getline() and ungetline() calls. |
67
|
|
|
|
|
|
|
|
68
|
|
|
|
|
|
|
sub getint { |
69
|
0
|
|
|
0
|
0
|
|
my $this = shift(); |
70
|
0
|
|
|
|
|
|
$this->_refresh(); |
71
|
0
|
0
|
|
|
|
|
die "getint($this) on non-int buffer '" . $this->{buf} . "'" |
72
|
|
|
|
|
|
|
if $this->{buf} !~ /^\d/; |
73
|
|
|
|
|
|
|
|
74
|
0
|
|
|
|
|
|
$this->{buf} =~ s/(\d+)//; |
75
|
0
|
|
|
|
|
|
return $1; |
76
|
|
|
|
|
|
|
} |
77
|
|
|
|
|
|
|
|
78
|
|
|
|
|
|
|
sub getstring { |
79
|
0
|
|
|
0
|
0
|
|
my $this = shift(); |
80
|
0
|
|
|
|
|
|
$this->_refresh(); |
81
|
|
|
|
|
|
|
|
82
|
0
|
0
|
|
|
|
|
$this->{buf} =~ s/^[""]// |
83
|
|
|
|
|
|
|
or die "getstring($this) on non-string buffer '" . $this->{buf} . "'"; |
84
|
|
|
|
|
|
|
|
85
|
0
|
|
|
|
|
|
my $string = ""; |
86
|
0
|
|
|
|
|
|
while ($this->{buf} !~ /[""]/) { |
87
|
0
|
|
|
|
|
|
$string .= $this->{buf}; |
88
|
0
|
|
|
|
|
|
$this->{buf} = $this->getline(); |
89
|
|
|
|
|
|
|
} |
90
|
|
|
|
|
|
|
|
91
|
0
|
0
|
|
|
|
|
$this->{buf} =~ s/^(.*?)[""]// |
92
|
|
|
|
|
|
|
or die "can't happen"; |
93
|
|
|
|
|
|
|
|
94
|
0
|
|
|
|
|
|
$string .= $1; |
95
|
0
|
|
|
|
|
|
$string =~ s/[``"]/"/g; |
96
|
0
|
|
|
|
|
|
return $string; |
97
|
|
|
|
|
|
|
} |
98
|
|
|
|
|
|
|
|
99
|
|
|
|
|
|
|
# PRIVATE to getint() and getstring() |
100
|
|
|
|
|
|
|
sub _refresh { |
101
|
0
|
|
|
0
|
|
|
my $this = shift(); |
102
|
0
|
|
|
|
|
|
while ($this->{buf} =~ /^\s*$/) { |
103
|
0
|
|
|
|
|
|
$this->{buf} = $this->getline(); |
104
|
|
|
|
|
|
|
} |
105
|
0
|
|
|
|
|
|
$this->{buf} =~ s/^\s*//; |
106
|
|
|
|
|
|
|
} |
107
|
|
|
|
|
|
|
|
108
|
|
|
|
|
|
|
|
109
|
|
|
|
|
|
|
sub warn { |
110
|
0
|
|
|
0
|
0
|
|
my $this = shift(); |
111
|
|
|
|
|
|
|
|
112
|
0
|
|
|
|
|
|
print STDERR $this->{filename}, ':', $this->{linenumber}, ': ', |
113
|
|
|
|
|
|
|
'WARNING: ', @_, "\n"; |
114
|
|
|
|
|
|
|
} |
115
|
|
|
|
|
|
|
|
116
|
|
|
|
|
|
|
|
117
|
|
|
|
|
|
|
sub fatal { |
118
|
0
|
|
|
0
|
0
|
|
my $this = shift(); |
119
|
|
|
|
|
|
|
|
120
|
0
|
|
0
|
|
|
|
my $filename = $this->{filename} || '[unknown]'; |
121
|
0
|
|
0
|
|
|
|
my $linenumber = $this->{linenumber} || '[unknown]'; |
122
|
0
|
|
|
|
|
|
print STDERR $filename, ':', $linenumber, ': ERROR: ', @_, "\n"; |
123
|
0
|
|
|
|
|
|
exit 1; |
124
|
|
|
|
|
|
|
} |
125
|
|
|
|
|
|
|
|
126
|
|
|
|
|
|
|
|
127
|
|
|
|
|
|
|
sub close { |
128
|
0
|
|
|
0
|
0
|
|
my $this = shift(); |
129
|
|
|
|
|
|
|
|
130
|
0
|
|
|
|
|
|
$this->{f}->close(); |
131
|
|
|
|
|
|
|
} |
132
|
|
|
|
|
|
|
|
133
|
|
|
|
|
|
|
|
134
|
|
|
|
|
|
|
1; |