line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
# |
2
|
|
|
|
|
|
|
# Revision History: |
3
|
|
|
|
|
|
|
# |
4
|
|
|
|
|
|
|
# 27-Nov-2002 Dick Munroe (munroe@csworks.com) |
5
|
|
|
|
|
|
|
# Break structure initialization out of the new function to make |
6
|
|
|
|
|
|
|
# inheritance easier. |
7
|
|
|
|
|
|
|
# Allow Stanzas to have keywords without arguments when converting |
8
|
|
|
|
|
|
|
# back to strings. |
9
|
|
|
|
|
|
|
# |
10
|
|
|
|
|
|
|
# 20-Dec-2002 Dick Munroe (munroe@csworks.com) |
11
|
|
|
|
|
|
|
# Add use strict, restrict the version of perl to 5.8.0 or higher, |
12
|
|
|
|
|
|
|
# and necessary changes imposed by use strict. |
13
|
|
|
|
|
|
|
# |
14
|
|
|
|
|
|
|
# |
15
|
|
|
|
|
|
|
# 17-May-2003 Dick Munroe (munroe@csworks.com) |
16
|
|
|
|
|
|
|
# Fix things so that package variables can't leak. |
17
|
|
|
|
|
|
|
# |
18
|
|
|
|
|
|
|
# 20-May-2003 Dick Munroe (munroe@csworks.com) |
19
|
|
|
|
|
|
|
# Make the test harness happy. |
20
|
|
|
|
|
|
|
# Forgot the tests in the MANIFEST. |
21
|
|
|
|
|
|
|
# Backport to 5.6.1 |
22
|
|
|
|
|
|
|
# |
23
|
|
|
|
|
|
|
|
24
|
|
|
|
|
|
|
package StanzaFile ; |
25
|
|
|
|
|
|
|
|
26
|
1
|
|
|
1
|
|
604
|
use strict ; |
|
1
|
|
|
|
|
1
|
|
|
1
|
|
|
|
|
48
|
|
27
|
1
|
|
|
1
|
|
6
|
use vars qw($VERSION) ; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
39
|
|
28
|
|
|
|
|
|
|
|
29
|
1
|
|
|
1
|
|
964
|
use FileHandle ; |
|
1
|
|
|
|
|
13524
|
|
|
1
|
|
|
|
|
7
|
|
30
|
1
|
|
|
1
|
|
400
|
use Stanza ; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
2784
|
|
31
|
|
|
|
|
|
|
|
32
|
|
|
|
|
|
|
our $VERSION = "1.05" ; |
33
|
|
|
|
|
|
|
|
34
|
|
|
|
|
|
|
sub _new |
35
|
|
|
|
|
|
|
{ |
36
|
0
|
|
|
0
|
|
|
my $thePackage = shift ; |
37
|
|
|
|
|
|
|
|
38
|
0
|
|
0
|
|
|
|
$thePackage = ref($thePackage) || $thePackage ; |
39
|
|
|
|
|
|
|
|
40
|
0
|
|
|
|
|
|
my $theStanzaFile = |
41
|
|
|
|
|
|
|
{ |
42
|
|
|
|
|
|
|
'stanzaFlag' => undef, |
43
|
|
|
|
|
|
|
'header' => new Stanza('header'), |
44
|
|
|
|
|
|
|
'stanza' => {}, |
45
|
|
|
|
|
|
|
'order' => [] |
46
|
|
|
|
|
|
|
} ; |
47
|
|
|
|
|
|
|
|
48
|
0
|
|
|
|
|
|
return bless $theStanzaFile, $thePackage ; |
49
|
|
|
|
|
|
|
} ; |
50
|
|
|
|
|
|
|
|
51
|
|
|
|
|
|
|
# |
52
|
|
|
|
|
|
|
# Create a new stanza file object. |
53
|
|
|
|
|
|
|
# |
54
|
|
|
|
|
|
|
# Arguments: |
55
|
|
|
|
|
|
|
# |
56
|
|
|
|
|
|
|
# file_name => string |
57
|
|
|
|
|
|
|
# file_handle => FileHandle object reference. |
58
|
|
|
|
|
|
|
# file_string => string |
59
|
|
|
|
|
|
|
# |
60
|
|
|
|
|
|
|
|
61
|
|
|
|
|
|
|
sub new |
62
|
|
|
|
|
|
|
{ |
63
|
0
|
|
|
0
|
0
|
|
my $thePackage = shift ; |
64
|
|
|
|
|
|
|
|
65
|
0
|
0
|
|
|
|
|
die "Odd number of arguments passed to StanzaFile::new" if ((scalar(@_) % 2) != 0) ; |
66
|
|
|
|
|
|
|
|
67
|
0
|
|
|
|
|
|
my %ARGS = @_ ; |
68
|
|
|
|
|
|
|
|
69
|
0
|
|
|
|
|
|
my $theStanzaFile = $thePackage->_new() ; |
70
|
|
|
|
|
|
|
|
71
|
0
|
0
|
|
|
|
|
$theStanzaFile->read(%ARGS) if (%ARGS) ; |
72
|
|
|
|
|
|
|
|
73
|
0
|
|
|
|
|
|
return $theStanzaFile ; |
74
|
|
|
|
|
|
|
} ; |
75
|
|
|
|
|
|
|
|
76
|
|
|
|
|
|
|
# |
77
|
|
|
|
|
|
|
# Interface to be able to add "header" information which is simply |
78
|
|
|
|
|
|
|
# information that appears in the file prior to the occurance of |
79
|
|
|
|
|
|
|
# a stanza. By default, this is an invalid syntax. |
80
|
|
|
|
|
|
|
# |
81
|
|
|
|
|
|
|
|
82
|
|
|
|
|
|
|
sub addHeader |
83
|
|
|
|
|
|
|
{ |
84
|
0
|
|
|
0
|
0
|
|
my ($theObject, $theHeader) = @_ ; |
85
|
|
|
|
|
|
|
|
86
|
0
|
|
|
|
|
|
die "Information not in a Stanza: $theHeader" ; |
87
|
|
|
|
|
|
|
} ; |
88
|
|
|
|
|
|
|
|
89
|
|
|
|
|
|
|
# |
90
|
|
|
|
|
|
|
# Add a new stanza. Keep track of the order of addition. |
91
|
|
|
|
|
|
|
# |
92
|
|
|
|
|
|
|
|
93
|
|
|
|
|
|
|
sub add |
94
|
|
|
|
|
|
|
{ |
95
|
0
|
|
|
0
|
0
|
|
my ($theObject, $theStanza) = @_ ; |
96
|
|
|
|
|
|
|
|
97
|
0
|
0
|
|
|
|
|
die "Can't add anything but Stanza's" if (ref($theStanza) ne "Stanza") ; |
98
|
|
|
|
|
|
|
|
99
|
0
|
|
|
|
|
|
$theObject->{'stanza'}->{$theStanza->name}=$theStanza ; |
100
|
0
|
|
|
|
|
|
push @{$theObject->{'order'}},$theStanza->name ; |
|
0
|
|
|
|
|
|
|
101
|
|
|
|
|
|
|
|
102
|
0
|
|
|
|
|
|
return $theObject ; |
103
|
|
|
|
|
|
|
} ; |
104
|
|
|
|
|
|
|
|
105
|
|
|
|
|
|
|
# |
106
|
|
|
|
|
|
|
# Does the specified stanza exist? |
107
|
|
|
|
|
|
|
# |
108
|
|
|
|
|
|
|
|
109
|
|
|
|
|
|
|
sub exists |
110
|
|
|
|
|
|
|
{ |
111
|
0
|
0
|
|
0
|
0
|
|
die "Too few arguments passed to StanzaFile::exists" if (scalar(@_) < 2) ; |
112
|
|
|
|
|
|
|
|
113
|
0
|
|
|
|
|
|
my ($theObject, $theStanzaName) = @_ ; |
114
|
|
|
|
|
|
|
|
115
|
0
|
0
|
0
|
|
|
|
if (ref($theStanzaName) && ($theStanzaName->isa('Stanza'))) |
116
|
|
|
|
|
|
|
{ |
117
|
0
|
|
|
|
|
|
return $theObject->{'stanza'}->{$theStanzaName->name()} ; |
118
|
|
|
|
|
|
|
} |
119
|
|
|
|
|
|
|
else |
120
|
|
|
|
|
|
|
{ |
121
|
0
|
|
|
|
|
|
return $theObject->{'stanza'}->{$theStanzaName} ; |
122
|
|
|
|
|
|
|
} ; |
123
|
|
|
|
|
|
|
} ; |
124
|
|
|
|
|
|
|
|
125
|
|
|
|
|
|
|
# |
126
|
|
|
|
|
|
|
# True if this is the beginning of a stanza, otherwise false. The |
127
|
|
|
|
|
|
|
# true value is the contents marking the beginning of a stanza. |
128
|
|
|
|
|
|
|
# |
129
|
|
|
|
|
|
|
|
130
|
|
|
|
|
|
|
sub isBeginning |
131
|
|
|
|
|
|
|
{ |
132
|
0
|
0
|
|
0
|
0
|
|
die "Too few arguments passed to StanzaFile::isBeginning" if (scalar(@_) < 2) ; |
133
|
|
|
|
|
|
|
|
134
|
0
|
|
|
|
|
|
my ($theObject, $theLine) = @_ ; |
135
|
|
|
|
|
|
|
|
136
|
0
|
0
|
|
|
|
|
if ($theLine =~ m/\s*\[([^\]]+)\]/) |
137
|
|
|
|
|
|
|
{ |
138
|
0
|
|
|
|
|
|
my $theName = $1 ; |
139
|
|
|
|
|
|
|
|
140
|
0
|
|
|
|
|
|
$theName =~ s/^\s+(.*)/$1/ ; |
141
|
0
|
|
|
|
|
|
$theName =~ s/(.*?)\s+$/$1/ ; |
142
|
0
|
|
|
|
|
|
$theName =~ s/\s{2,}/ /g ; |
143
|
|
|
|
|
|
|
|
144
|
0
|
|
|
|
|
|
return $theName ; |
145
|
|
|
|
|
|
|
} ; |
146
|
|
|
|
|
|
|
|
147
|
0
|
|
|
|
|
|
return undef ; |
148
|
|
|
|
|
|
|
} ; |
149
|
|
|
|
|
|
|
|
150
|
|
|
|
|
|
|
# |
151
|
|
|
|
|
|
|
# Return true if this is a comment or a blank line. |
152
|
|
|
|
|
|
|
# |
153
|
|
|
|
|
|
|
|
154
|
|
|
|
|
|
|
sub isComment |
155
|
|
|
|
|
|
|
{ |
156
|
0
|
0
|
|
0
|
0
|
|
die "Too few arguments passed to StanzaFile::isComment" if (scalar(@_) < 2) ; |
157
|
|
|
|
|
|
|
|
158
|
0
|
|
|
|
|
|
my ($theObject, $theLine) = @_ ; |
159
|
|
|
|
|
|
|
|
160
|
0
|
|
|
|
|
|
return $theLine =~ m/^\s*(\#|$)/ ; |
161
|
|
|
|
|
|
|
} ; |
162
|
|
|
|
|
|
|
|
163
|
|
|
|
|
|
|
# |
164
|
|
|
|
|
|
|
# Return the name/value pair if this is, indeed, a name/value pair |
165
|
|
|
|
|
|
|
# otherwise return false. |
166
|
|
|
|
|
|
|
# |
167
|
|
|
|
|
|
|
|
168
|
|
|
|
|
|
|
sub isValue |
169
|
|
|
|
|
|
|
{ |
170
|
0
|
|
|
0
|
0
|
|
my ($theObject, $theLine) = @_ ; |
171
|
|
|
|
|
|
|
|
172
|
0
|
0
|
|
|
|
|
if ($theLine =~ m/\s*([\w ]+?)\s*=\s*(.*)/) |
173
|
|
|
|
|
|
|
{ |
174
|
0
|
|
|
|
|
|
return ($1, $2) ; |
175
|
|
|
|
|
|
|
} ; |
176
|
|
|
|
|
|
|
|
177
|
0
|
|
|
|
|
|
return undef ; |
178
|
|
|
|
|
|
|
} ; |
179
|
|
|
|
|
|
|
|
180
|
|
|
|
|
|
|
# |
181
|
|
|
|
|
|
|
# Create a new stanza of the "appropriate" type. |
182
|
|
|
|
|
|
|
# |
183
|
|
|
|
|
|
|
|
184
|
|
|
|
|
|
|
sub newStanza |
185
|
|
|
|
|
|
|
{ |
186
|
0
|
|
|
0
|
0
|
|
my ($theObject, $theName) = @_ ; |
187
|
|
|
|
|
|
|
|
188
|
0
|
|
|
|
|
|
return new Stanza($theName) ; |
189
|
|
|
|
|
|
|
} ; |
190
|
|
|
|
|
|
|
|
191
|
|
|
|
|
|
|
# |
192
|
|
|
|
|
|
|
# Parse the stanza file into stanzas. The contents of the |
193
|
|
|
|
|
|
|
# file is passed as array arguments. |
194
|
|
|
|
|
|
|
# |
195
|
|
|
|
|
|
|
|
196
|
|
|
|
|
|
|
sub parse |
197
|
|
|
|
|
|
|
{ |
198
|
0
|
|
|
0
|
0
|
|
my $theObject = shift ; |
199
|
|
|
|
|
|
|
|
200
|
0
|
0
|
|
|
|
|
die "Too few arguments to StanzaFile::parse" if (scalar(@_) < 2) ; |
201
|
|
|
|
|
|
|
|
202
|
0
|
|
|
|
|
|
my $theStanza ; |
203
|
|
|
|
|
|
|
|
204
|
0
|
|
|
|
|
|
foreach (@_) |
205
|
|
|
|
|
|
|
{ |
206
|
|
|
|
|
|
|
# |
207
|
|
|
|
|
|
|
# Don't process comment characters or blank lines |
208
|
|
|
|
|
|
|
# |
209
|
|
|
|
|
|
|
|
210
|
0
|
0
|
|
|
|
|
next if $theObject->isComment($_) ; |
211
|
|
|
|
|
|
|
|
212
|
0
|
|
|
|
|
|
my $theStanzaName ; |
213
|
|
|
|
|
|
|
|
214
|
0
|
0
|
|
|
|
|
if ($theStanzaName = $theObject->isBeginning($_)) |
215
|
|
|
|
|
|
|
{ |
216
|
|
|
|
|
|
|
# |
217
|
|
|
|
|
|
|
# Found the beginning of a stanza, create a new stanza object, |
218
|
|
|
|
|
|
|
# add it to the contents of the current object and continue. |
219
|
|
|
|
|
|
|
# |
220
|
|
|
|
|
|
|
|
221
|
0
|
|
|
|
|
|
$theStanza = $theObject->newStanza($theStanzaName) ; |
222
|
|
|
|
|
|
|
|
223
|
0
|
|
|
|
|
|
$theObject->add($theStanza) ; |
224
|
|
|
|
|
|
|
|
225
|
0
|
|
|
|
|
|
$theObject->{'stanzaFlag'} = 1 ; |
226
|
|
|
|
|
|
|
} |
227
|
|
|
|
|
|
|
else |
228
|
|
|
|
|
|
|
{ |
229
|
|
|
|
|
|
|
# |
230
|
|
|
|
|
|
|
# If it isn't a comment, a stanza introduction, or a blank line, |
231
|
|
|
|
|
|
|
# then it must be a line to be added to the current stanza (if |
232
|
|
|
|
|
|
|
# there is a stanza in progress) or to the header (if there isn't |
233
|
|
|
|
|
|
|
# a stanza in progress). |
234
|
|
|
|
|
|
|
# |
235
|
|
|
|
|
|
|
|
236
|
0
|
0
|
|
|
|
|
if ($theObject->{'stanzaFlag'}) |
237
|
|
|
|
|
|
|
{ |
238
|
|
|
|
|
|
|
eval |
239
|
0
|
|
|
|
|
|
{ |
240
|
0
|
|
|
|
|
|
$theStanza->add($theObject->isValue($_)) ; |
241
|
|
|
|
|
|
|
} ; |
242
|
|
|
|
|
|
|
} |
243
|
|
|
|
|
|
|
else |
244
|
|
|
|
|
|
|
{ |
245
|
|
|
|
|
|
|
eval |
246
|
0
|
|
|
|
|
|
{ |
247
|
0
|
|
|
|
|
|
$theObject->addHeader($theObject->isValue($_)) ; |
248
|
|
|
|
|
|
|
} ; |
249
|
|
|
|
|
|
|
} ; |
250
|
|
|
|
|
|
|
|
251
|
0
|
0
|
|
|
|
|
die "Invalid format in Stanza $theStanza->name(): $_" if ($@) ; |
252
|
|
|
|
|
|
|
} ; |
253
|
|
|
|
|
|
|
} ; |
254
|
|
|
|
|
|
|
|
255
|
0
|
|
|
|
|
|
return $theObject ; |
256
|
|
|
|
|
|
|
} ; |
257
|
|
|
|
|
|
|
|
258
|
|
|
|
|
|
|
# |
259
|
|
|
|
|
|
|
# Process a file into a set of stanzas. |
260
|
|
|
|
|
|
|
# |
261
|
|
|
|
|
|
|
# Arguments (one of the following): |
262
|
|
|
|
|
|
|
# |
263
|
|
|
|
|
|
|
# file_handle=>FileHandle object reference to opened file. |
264
|
|
|
|
|
|
|
# file_name =>Path to file. |
265
|
|
|
|
|
|
|
# file_string=>Contents of file. |
266
|
|
|
|
|
|
|
# |
267
|
|
|
|
|
|
|
|
268
|
|
|
|
|
|
|
sub read |
269
|
|
|
|
|
|
|
{ |
270
|
0
|
0
|
|
0
|
0
|
|
die "Too few arguments to StanzaFile::Read" if (scalar(@_) < 2) ; |
271
|
|
|
|
|
|
|
|
272
|
0
|
|
|
|
|
|
my $theObject = shift ; |
273
|
|
|
|
|
|
|
|
274
|
0
|
0
|
|
|
|
|
die "Wrong number of arguments passed to StanzaFile::read" if ((scalar(@_) % 2) ne 0) ; |
275
|
|
|
|
|
|
|
|
276
|
0
|
|
|
|
|
|
my %ARGS = @_ ; |
277
|
|
|
|
|
|
|
|
278
|
0
|
|
|
|
|
|
my @theFile ; |
279
|
|
|
|
|
|
|
|
280
|
0
|
0
|
|
|
|
|
if (defined($ARGS{'file_string'})) |
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
281
|
|
|
|
|
|
|
{ |
282
|
0
|
|
|
|
|
|
@theFile = split /\n/,$ARGS{'file_string'} ; |
283
|
|
|
|
|
|
|
} |
284
|
|
|
|
|
|
|
elsif (defined($ARGS{'file_name'})) |
285
|
|
|
|
|
|
|
{ |
286
|
0
|
|
|
|
|
|
my $theFileHandle = new FileHandle "< " . $ARGS{'file_name'} ; |
287
|
|
|
|
|
|
|
|
288
|
0
|
0
|
|
|
|
|
die "Can't open " . $ARGS{'file_name'} . " for input" if (!defined($theFileHandle)) ; |
289
|
|
|
|
|
|
|
|
290
|
0
|
|
|
|
|
|
@theFile = $theFileHandle->getlines() ; |
291
|
|
|
|
|
|
|
|
292
|
0
|
|
|
|
|
|
undef $theFileHandle ; |
293
|
|
|
|
|
|
|
} |
294
|
|
|
|
|
|
|
elsif (defined($ARGS{'file_handle'})) |
295
|
|
|
|
|
|
|
{ |
296
|
0
|
0
|
|
|
|
|
die "Must be a FileHandle class in StanzaFile::read('file_handle=>...)" if (!$ARGS{'file_handle'}-isa("FileHandle")) ; |
297
|
|
|
|
|
|
|
|
298
|
0
|
|
|
|
|
|
@theFile = $ARGS{'file_handle'}->getlines |
299
|
|
|
|
|
|
|
} |
300
|
|
|
|
|
|
|
else |
301
|
|
|
|
|
|
|
{ |
302
|
0
|
|
|
|
|
|
die "Missing argument for StanzaFile::read" ; |
303
|
|
|
|
|
|
|
} ; |
304
|
|
|
|
|
|
|
|
305
|
0
|
|
|
|
|
|
return $theObject->parse(@theFile) ; |
306
|
|
|
|
|
|
|
} ; |
307
|
|
|
|
|
|
|
|
308
|
|
|
|
|
|
|
# |
309
|
|
|
|
|
|
|
# Produce a string representation of a stanza file. The default |
310
|
|
|
|
|
|
|
# "windows.ini" form which the base class parses is of the form: |
311
|
|
|
|
|
|
|
# |
312
|
|
|
|
|
|
|
# [name] |
313
|
|
|
|
|
|
|
# name=value |
314
|
|
|
|
|
|
|
# ... |
315
|
|
|
|
|
|
|
# |
316
|
|
|
|
|
|
|
# [name] |
317
|
|
|
|
|
|
|
# ... |
318
|
|
|
|
|
|
|
# |
319
|
|
|
|
|
|
|
# Note that all comments are lost during the input/output process |
320
|
|
|
|
|
|
|
# using StanzaFile. |
321
|
|
|
|
|
|
|
# |
322
|
|
|
|
|
|
|
# FIX ME It seems more natural for the stanza's do be doing the |
323
|
|
|
|
|
|
|
# stringifying but the parseing is being done in the stanza file |
324
|
|
|
|
|
|
|
# class and all stanzas are are containers for data, so ... |
325
|
|
|
|
|
|
|
# |
326
|
|
|
|
|
|
|
|
327
|
|
|
|
|
|
|
sub headerAsString |
328
|
|
|
|
|
|
|
{ |
329
|
0
|
|
|
0
|
0
|
|
return "" ; |
330
|
|
|
|
|
|
|
} ; |
331
|
|
|
|
|
|
|
|
332
|
|
|
|
|
|
|
sub stanzaAsString |
333
|
|
|
|
|
|
|
{ |
334
|
0
|
|
|
0
|
0
|
|
my ($theObject, $theStanza) = @_ ; |
335
|
|
|
|
|
|
|
|
336
|
0
|
|
|
|
|
|
my $theString = "[" . $theStanza->name() . "]\n" ; |
337
|
|
|
|
|
|
|
|
338
|
0
|
|
|
|
|
|
foreach ($theStanza->order()) |
339
|
|
|
|
|
|
|
{ |
340
|
0
|
0
|
|
|
|
|
if (defined($theStanza->item($_))) |
341
|
|
|
|
|
|
|
{ |
342
|
0
|
|
|
|
|
|
$theString = $theString . $_ . "=" . $theStanza->item($_) . "\n" ; |
343
|
|
|
|
|
|
|
} |
344
|
|
|
|
|
|
|
else |
345
|
|
|
|
|
|
|
{ |
346
|
0
|
|
|
|
|
|
$theString = $theString . $_ . "\n" ; |
347
|
|
|
|
|
|
|
} ; |
348
|
|
|
|
|
|
|
} ; |
349
|
|
|
|
|
|
|
|
350
|
0
|
|
|
|
|
|
return $theString ; |
351
|
|
|
|
|
|
|
} ; |
352
|
|
|
|
|
|
|
|
353
|
|
|
|
|
|
|
sub asString |
354
|
|
|
|
|
|
|
{ |
355
|
0
|
|
|
0
|
0
|
|
my $theObject = shift ; |
356
|
|
|
|
|
|
|
|
357
|
0
|
|
|
|
|
|
my $theString = $theObject->headerAsString() . "\n" ; |
358
|
|
|
|
|
|
|
|
359
|
0
|
|
|
|
|
|
foreach ($theObject->order()) |
360
|
|
|
|
|
|
|
{ |
361
|
0
|
|
|
|
|
|
$theString = $theString . $theObject->stanzaAsString($theObject->stanza($_)) . "\n" ; |
362
|
|
|
|
|
|
|
} ; |
363
|
|
|
|
|
|
|
|
364
|
0
|
|
|
|
|
|
$theString =~ s/^\n+// ; |
365
|
0
|
|
|
|
|
|
chomp($theString) ; |
366
|
|
|
|
|
|
|
|
367
|
0
|
|
|
|
|
|
return $theString ; |
368
|
|
|
|
|
|
|
} ; |
369
|
|
|
|
|
|
|
|
370
|
|
|
|
|
|
|
# |
371
|
|
|
|
|
|
|
# Produce a file from a set of stanzas. |
372
|
|
|
|
|
|
|
# |
373
|
|
|
|
|
|
|
# Arguments (one of the following): |
374
|
|
|
|
|
|
|
# |
375
|
|
|
|
|
|
|
# file_handle=>FileHandle object reference to opened file. |
376
|
|
|
|
|
|
|
# file_name =>Path to file. |
377
|
|
|
|
|
|
|
# file_string=>Reference to string to contain file. |
378
|
|
|
|
|
|
|
# |
379
|
|
|
|
|
|
|
|
380
|
|
|
|
|
|
|
sub write |
381
|
|
|
|
|
|
|
{ |
382
|
0
|
0
|
|
0
|
0
|
|
die "Too few arguments to StanzaFile::write" if (scalar(@_) < 2) ; |
383
|
|
|
|
|
|
|
|
384
|
0
|
|
|
|
|
|
my $theObject = shift ; |
385
|
|
|
|
|
|
|
|
386
|
0
|
0
|
|
|
|
|
die "Wrong number of arguments passed to StanzaFile::read" if ((scalar(@_) % 2) ne 0) ; |
387
|
|
|
|
|
|
|
|
388
|
0
|
|
|
|
|
|
my %ARGS = @_ ; |
389
|
|
|
|
|
|
|
|
390
|
0
|
|
|
|
|
|
my $theFile = $theObject->asString() ; |
391
|
|
|
|
|
|
|
|
392
|
0
|
0
|
|
|
|
|
if (defined($ARGS{'file_string'})) |
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
393
|
|
|
|
|
|
|
{ |
394
|
0
|
|
|
|
|
|
${$ARGS{'file_string'}} = $theFile ; |
|
0
|
|
|
|
|
|
|
395
|
|
|
|
|
|
|
} |
396
|
|
|
|
|
|
|
elsif (defined($ARGS{'file_name'})) |
397
|
|
|
|
|
|
|
{ |
398
|
0
|
|
|
|
|
|
my $theFileHandle = new FileHandle "> " . $ARGS{'file_name'} ; |
399
|
|
|
|
|
|
|
|
400
|
0
|
0
|
|
|
|
|
die "Can't open " . $ARGS{'file_name'} . " for output" if (!defined($theFileHandle)) ; |
401
|
|
|
|
|
|
|
|
402
|
0
|
|
|
|
|
|
$theFileHandle->print($theFile) ; |
403
|
|
|
|
|
|
|
|
404
|
0
|
|
|
|
|
|
undef $theFileHandle ; |
405
|
|
|
|
|
|
|
} |
406
|
|
|
|
|
|
|
elsif (defined($ARGS{'file_handle'})) |
407
|
|
|
|
|
|
|
{ |
408
|
0
|
0
|
|
|
|
|
die "Must be a FileHandle class in StanzaFile::write('file_handle=>...)" if (!$ARGS{'file_handle'}-isa("FileHandle")) ; |
409
|
|
|
|
|
|
|
|
410
|
0
|
|
|
|
|
|
$ARGS{'file_handle'}->print($theFile) ; |
411
|
|
|
|
|
|
|
} |
412
|
|
|
|
|
|
|
else |
413
|
|
|
|
|
|
|
{ |
414
|
0
|
|
|
|
|
|
die "Missing argument for StanzaFile::write" ; |
415
|
|
|
|
|
|
|
} ; |
416
|
|
|
|
|
|
|
|
417
|
0
|
|
|
|
|
|
return $theFile ; |
418
|
|
|
|
|
|
|
} ; |
419
|
|
|
|
|
|
|
|
420
|
|
|
|
|
|
|
# |
421
|
|
|
|
|
|
|
# Replace an [possibly] existing Stanza. |
422
|
|
|
|
|
|
|
# |
423
|
|
|
|
|
|
|
|
424
|
|
|
|
|
|
|
sub replace |
425
|
|
|
|
|
|
|
{ |
426
|
0
|
|
|
0
|
0
|
|
my ($theObject, $theStanza) = @_ ; |
427
|
|
|
|
|
|
|
|
428
|
0
|
0
|
|
|
|
|
die "Can't replace anything but Stanza's" if (ref($theStanza) ne "Stanza") ; |
429
|
|
|
|
|
|
|
|
430
|
0
|
0
|
|
|
|
|
if (!$theObject->exists($theStanza)) |
431
|
|
|
|
|
|
|
{ |
432
|
0
|
|
|
|
|
|
push @{$theObject->{'order'}},$theStanza->name ; |
|
0
|
|
|
|
|
|
|
433
|
|
|
|
|
|
|
} ; |
434
|
|
|
|
|
|
|
|
435
|
0
|
|
|
|
|
|
$theObject->{'stanza'}->{$theStanza->name}=$theStanza ; |
436
|
|
|
|
|
|
|
|
437
|
0
|
|
|
|
|
|
return $theObject ; |
438
|
|
|
|
|
|
|
} ; |
439
|
|
|
|
|
|
|
|
440
|
|
|
|
|
|
|
# |
441
|
|
|
|
|
|
|
# Accessor Functions. |
442
|
|
|
|
|
|
|
# |
443
|
|
|
|
|
|
|
|
444
|
|
|
|
|
|
|
sub header |
445
|
|
|
|
|
|
|
{ |
446
|
0
|
|
|
0
|
0
|
|
my $theObject = shift ; |
447
|
|
|
|
|
|
|
|
448
|
0
|
|
|
|
|
|
return $theObject->{'header'} ; |
449
|
|
|
|
|
|
|
} ; |
450
|
|
|
|
|
|
|
|
451
|
|
|
|
|
|
|
sub order |
452
|
|
|
|
|
|
|
{ |
453
|
0
|
|
|
0
|
0
|
|
my $theObject = shift ; |
454
|
|
|
|
|
|
|
|
455
|
0
|
|
|
|
|
|
return @{$theObject->{'order'}} ; |
|
0
|
|
|
|
|
|
|
456
|
|
|
|
|
|
|
} ; |
457
|
|
|
|
|
|
|
|
458
|
|
|
|
|
|
|
sub stanza |
459
|
|
|
|
|
|
|
{ |
460
|
0
|
|
|
0
|
0
|
|
my ($theObject, $theName) = @_ ; |
461
|
|
|
|
|
|
|
|
462
|
0
|
0
|
0
|
|
|
|
if (ref($theName) && ($theName->isa('Stanza'))) |
463
|
|
|
|
|
|
|
{ |
464
|
0
|
|
|
|
|
|
return $theObject->{'stanza'}->{$theName->name()} ; |
465
|
|
|
|
|
|
|
} |
466
|
|
|
|
|
|
|
else |
467
|
|
|
|
|
|
|
{ |
468
|
0
|
|
|
|
|
|
return $theObject->{'stanza'}->{$theName} ; |
469
|
|
|
|
|
|
|
} ; |
470
|
|
|
|
|
|
|
} ; |
471
|
|
|
|
|
|
|
|
472
|
|
|
|
|
|
|
1 ; |
473
|
|
|
|
|
|
|
|
474
|
|
|
|
|
|
|
=pod |
475
|
|
|
|
|
|
|
|
476
|
|
|
|
|
|
|
=head1 NAME |
477
|
|
|
|
|
|
|
|
478
|
|
|
|
|
|
|
StanzaFile - read, parse, and write files containing "stanzas". |
479
|
|
|
|
|
|
|
|
480
|
|
|
|
|
|
|
=head1 SYNOPSIS |
481
|
|
|
|
|
|
|
|
482
|
|
|
|
|
|
|
# Parse a .ini format file into stanzas. |
483
|
|
|
|
|
|
|
# |
484
|
|
|
|
|
|
|
|
485
|
|
|
|
|
|
|
use StanzaFile ; |
486
|
|
|
|
|
|
|
my $a = new StanzaFile(file_name=>"/etc/wvdial.conf") ; |
487
|
|
|
|
|
|
|
|
488
|
|
|
|
|
|
|
# Add a new stanza to a StanzaFile. |
489
|
|
|
|
|
|
|
# |
490
|
|
|
|
|
|
|
$a->add(new Stanza('Stanza Name')) ; |
491
|
|
|
|
|
|
|
|
492
|
|
|
|
|
|
|
# Check for a stanza's existance. |
493
|
|
|
|
|
|
|
# |
494
|
|
|
|
|
|
|
if ($a->exists('New Stanza')) |
495
|
|
|
|
|
|
|
{ |
496
|
|
|
|
|
|
|
... |
497
|
|
|
|
|
|
|
} ; |
498
|
|
|
|
|
|
|
|
499
|
|
|
|
|
|
|
# Parse a .ini format file into stanzas. |
500
|
|
|
|
|
|
|
# |
501
|
|
|
|
|
|
|
|
502
|
|
|
|
|
|
|
use StanzaFile ; |
503
|
|
|
|
|
|
|
my $a = new StanzaFile ; |
504
|
|
|
|
|
|
|
$a->read(file_name=>"/etc/wvdial.conf") ; |
505
|
|
|
|
|
|
|
|
506
|
|
|
|
|
|
|
# Produce a string version of the StanzaFile |
507
|
|
|
|
|
|
|
# (Comments and other formatting are lost) |
508
|
|
|
|
|
|
|
# |
509
|
|
|
|
|
|
|
|
510
|
|
|
|
|
|
|
my $theString = $a->asString() ; |
511
|
|
|
|
|
|
|
|
512
|
|
|
|
|
|
|
# Write the StanzaFile. |
513
|
|
|
|
|
|
|
# |
514
|
|
|
|
|
|
|
$a->write("/etc/newFile.conf") ; |
515
|
|
|
|
|
|
|
|
516
|
|
|
|
|
|
|
# Add a new stanza to the file, replacing the stanza if it |
517
|
|
|
|
|
|
|
# already exists in the file. |
518
|
|
|
|
|
|
|
# |
519
|
|
|
|
|
|
|
$theNewStanza = new Stanza('New Stanza') ; |
520
|
|
|
|
|
|
|
$a->replace($theNewStanza) ; |
521
|
|
|
|
|
|
|
|
522
|
|
|
|
|
|
|
# Access the "header" stanza. |
523
|
|
|
|
|
|
|
# |
524
|
|
|
|
|
|
|
my $theHeaderStanza = $a->header() ; |
525
|
|
|
|
|
|
|
|
526
|
|
|
|
|
|
|
# Order in which the stanzas were added to the stanza file. |
527
|
|
|
|
|
|
|
# |
528
|
|
|
|
|
|
|
my @theAdditionOrder = $a->order() ; |
529
|
|
|
|
|
|
|
|
530
|
|
|
|
|
|
|
# Get a stanza object from the stanza file. |
531
|
|
|
|
|
|
|
# |
532
|
|
|
|
|
|
|
my $theStanzaObject = $a->stanza('The Stanza') ; |
533
|
|
|
|
|
|
|
|
534
|
|
|
|
|
|
|
=head1 DESCRIPTION |
535
|
|
|
|
|
|
|
|
536
|
|
|
|
|
|
|
A number of Linux configuration files are stored in a Windows format |
537
|
|
|
|
|
|
|
know as "stanzas" or WINDOWS.INI format. These files are of the form |
538
|
|
|
|
|
|
|
|
539
|
|
|
|
|
|
|
[name] |
540
|
|
|
|
|
|
|
variable=value |
541
|
|
|
|
|
|
|
variable1=value1 |
542
|
|
|
|
|
|
|
... |
543
|
|
|
|
|
|
|
|
544
|
|
|
|
|
|
|
[name1] |
545
|
|
|
|
|
|
|
variableA=valueA |
546
|
|
|
|
|
|
|
variable1A=value1A |
547
|
|
|
|
|
|
|
|
548
|
|
|
|
|
|
|
and so on. This class is designed to provide parsing and processing |
549
|
|
|
|
|
|
|
capabilities for the WINDOWS.INI format and provide a general enough |
550
|
|
|
|
|
|
|
framework so that other formats of stanzas can be easily supported |
551
|
|
|
|
|
|
|
(see StanzaFile::Grub for an example). |
552
|
|
|
|
|
|
|
|
553
|
|
|
|
|
|
|
With the StanzaFile and it's companion class Stanza it is reasonably |
554
|
|
|
|
|
|
|
easy to read, parse, process, and write virtually any type of stanza |
555
|
|
|
|
|
|
|
formatted information. |
556
|
|
|
|
|
|
|
|
557
|
|
|
|
|
|
|
=head1 EXAMPLES |
558
|
|
|
|
|
|
|
|
559
|
|
|
|
|
|
|
The following is a somewhat contrived example, but it shows the |
560
|
|
|
|
|
|
|
merging of two StanzaFiles. |
561
|
|
|
|
|
|
|
|
562
|
|
|
|
|
|
|
my $a = new StanzaFile("/etc/wvfile.conf") ; |
563
|
|
|
|
|
|
|
my $b = new StanzaFile("newWvfile.conf") ; |
564
|
|
|
|
|
|
|
|
565
|
|
|
|
|
|
|
foreach ($b->order()) |
566
|
|
|
|
|
|
|
{ |
567
|
|
|
|
|
|
|
if ($a->exists($_)) |
568
|
|
|
|
|
|
|
{ |
569
|
|
|
|
|
|
|
$a->stanza($_)->merge($b->stanza($_)) ; |
570
|
|
|
|
|
|
|
} |
571
|
|
|
|
|
|
|
else |
572
|
|
|
|
|
|
|
{ |
573
|
|
|
|
|
|
|
$a->add($b->stanza($_)) ; |
574
|
|
|
|
|
|
|
} ; |
575
|
|
|
|
|
|
|
} ; |
576
|
|
|
|
|
|
|
|
577
|
|
|
|
|
|
|
$a->write(file_name=>"/etc/mergedWvdial.conf") ; |
578
|
|
|
|
|
|
|
|
579
|
|
|
|
|
|
|
=head1 BUGS |
580
|
|
|
|
|
|
|
|
581
|
|
|
|
|
|
|
None known. |
582
|
|
|
|
|
|
|
|
583
|
|
|
|
|
|
|
=head1 WARNINGS |
584
|
|
|
|
|
|
|
|
585
|
|
|
|
|
|
|
=head1 AUTHOR |
586
|
|
|
|
|
|
|
|
587
|
|
|
|
|
|
|
Dick Munroe (munroe@csworks.com). |
588
|
|
|
|
|
|
|
|
589
|
|
|
|
|
|
|
I'm looking for work (contract or permanent). I |
590
|
|
|
|
|
|
|
do a lot more than just hack Perl. Take a look at my: |
591
|
|
|
|
|
|
|
|
592
|
|
|
|
|
|
|
Resume: http://www.csworks.com/resume |
593
|
|
|
|
|
|
|
Skills: http://www.csworks.com/skills |
594
|
|
|
|
|
|
|
CV: http://www.csworks.com/cv |
595
|
|
|
|
|
|
|
|
596
|
|
|
|
|
|
|
for the gory details. If you see a match, drop me a note and we'll see what we |
597
|
|
|
|
|
|
|
can work out. |
598
|
|
|
|
|
|
|
|
599
|
|
|
|
|
|
|
=head1 SEE ALSO |
600
|
|
|
|
|
|
|
|
601
|
|
|
|
|
|
|
=cut |
602
|
|
|
|
|
|
|
|