line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package DBD::PO::Text::PO;
|
2
|
|
|
|
|
|
|
|
3
|
18
|
|
|
18
|
|
150875
|
use strict;
|
|
18
|
|
|
|
|
39
|
|
|
18
|
|
|
|
|
593
|
|
4
|
18
|
|
|
18
|
|
146
|
use warnings;
|
|
18
|
|
|
|
|
45
|
|
|
18
|
|
|
|
|
837
|
|
5
|
|
|
|
|
|
|
|
6
|
|
|
|
|
|
|
our $VERSION = '2.08';
|
7
|
|
|
|
|
|
|
|
8
|
18
|
|
|
18
|
|
97
|
use Carp qw(croak);
|
|
18
|
|
|
|
|
35
|
|
|
18
|
|
|
|
|
955
|
|
9
|
18
|
|
|
18
|
|
1899
|
use English qw(-no_match_vars $OS_ERROR);
|
|
18
|
|
|
|
|
5417
|
|
|
18
|
|
|
|
|
299
|
|
10
|
18
|
|
|
18
|
|
21066
|
use Params::Validate qw(:all);
|
|
18
|
|
|
|
|
215754
|
|
|
18
|
|
|
|
|
5042
|
|
11
|
18
|
|
|
18
|
|
14275
|
use DBD::PO::Locale::PO qw(@FORMAT_FLAGS $ALLOW_LOST_BLANK_LINES);
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
12
|
|
|
|
|
|
|
use Socket qw($CRLF);
|
13
|
|
|
|
|
|
|
use Set::Scalar;
|
14
|
|
|
|
|
|
|
|
15
|
|
|
|
|
|
|
use parent qw(Exporter);
|
16
|
|
|
|
|
|
|
our @EXPORT_OK = qw(
|
17
|
|
|
|
|
|
|
$EOL_DEFAULT
|
18
|
|
|
|
|
|
|
$SEPARATOR_DEFAULT
|
19
|
|
|
|
|
|
|
$CHARSET_DEFAULT
|
20
|
|
|
|
|
|
|
@COL_NAMES
|
21
|
|
|
|
|
|
|
);
|
22
|
|
|
|
|
|
|
|
23
|
|
|
|
|
|
|
our $EOL_DEFAULT = $CRLF;
|
24
|
|
|
|
|
|
|
our $SEPARATOR_DEFAULT = "\n";
|
25
|
|
|
|
|
|
|
our $CHARSET_DEFAULT = 'iso-8859-1';
|
26
|
|
|
|
|
|
|
|
27
|
|
|
|
|
|
|
our @COL_NAMES;
|
28
|
|
|
|
|
|
|
my @COL_PARAMETERS;
|
29
|
|
|
|
|
|
|
my @COL_METHODS;
|
30
|
|
|
|
|
|
|
our $LOST_BLANK_LINES;
|
31
|
|
|
|
|
|
|
|
32
|
|
|
|
|
|
|
sub init {
|
33
|
|
|
|
|
|
|
my (undef, @config) = @_;
|
34
|
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
my $config = Set::Scalar->new(@config);
|
36
|
|
|
|
|
|
|
my $allowed = Set::Scalar->new(
|
37
|
|
|
|
|
|
|
qw( :all :plural :previous :format allow_lost_blank_lines ),
|
38
|
|
|
|
|
|
|
@FORMAT_FLAGS,
|
39
|
|
|
|
|
|
|
);
|
40
|
|
|
|
|
|
|
my $not_allowed = $config - $allowed;
|
41
|
|
|
|
|
|
|
if ( ! $not_allowed->is_empty() ) {
|
42
|
|
|
|
|
|
|
croak 'Unkonwn config parameter: ', join ', ', $not_allowed->elements();
|
43
|
|
|
|
|
|
|
}
|
44
|
|
|
|
|
|
|
if ( $config->has(':all') ) {
|
45
|
|
|
|
|
|
|
$config->delete(':all');
|
46
|
|
|
|
|
|
|
$config->insert(qw(:plural :previous :format allow_lost_blank_lines));
|
47
|
|
|
|
|
|
|
}
|
48
|
|
|
|
|
|
|
my $has_plural = $config->has(':plural');
|
49
|
|
|
|
|
|
|
$config->delete(':plural');
|
50
|
|
|
|
|
|
|
my $has_previous = $config->has(':previous');
|
51
|
|
|
|
|
|
|
$config->delete(':previous');
|
52
|
|
|
|
|
|
|
if ( $config->has(':format') ) {
|
53
|
|
|
|
|
|
|
$config->delete(':format');
|
54
|
|
|
|
|
|
|
$config->insert(@FORMAT_FLAGS);
|
55
|
|
|
|
|
|
|
}
|
56
|
|
|
|
|
|
|
$ALLOW_LOST_BLANK_LINES = $config->has('allow_lost_blank_lines');
|
57
|
|
|
|
|
|
|
$config->delete('allow_lost_blank_lines');
|
58
|
|
|
|
|
|
|
|
59
|
|
|
|
|
|
|
my @cols = (
|
60
|
|
|
|
|
|
|
# typical
|
61
|
|
|
|
|
|
|
[ qw( msgid -msgid msgid ) ], # original text
|
62
|
|
|
|
|
|
|
[ qw( msgstr -msgstr msgstr ) ], # translation
|
63
|
|
|
|
|
|
|
[ qw( comment -comment comment ) ], # translater comment
|
64
|
|
|
|
|
|
|
[ qw( automatic -automatic automatic ) ], # automatic comment
|
65
|
|
|
|
|
|
|
[ qw( reference -reference reference ) ],
|
66
|
|
|
|
|
|
|
[ qw( msgctxt -msgctxt msgctxt ) ], # context
|
67
|
|
|
|
|
|
|
# flags
|
68
|
|
|
|
|
|
|
[ qw( fuzzy -fuzzy fuzzy ) ],
|
69
|
|
|
|
|
|
|
# switch to ignore
|
70
|
|
|
|
|
|
|
[ qw( obsolete -obsolete obsolete ) ],
|
71
|
|
|
|
|
|
|
# plural only
|
72
|
|
|
|
|
|
|
(
|
73
|
|
|
|
|
|
|
$has_plural
|
74
|
|
|
|
|
|
|
? (
|
75
|
|
|
|
|
|
|
[ qw( msgid_plural -msgid_plural msgid_plural ) ],
|
76
|
|
|
|
|
|
|
# dummy # dummy
|
77
|
|
|
|
|
|
|
[ qw( msgstr_0 -msgstr_0 msgstr_0 ) ], # singular or zero
|
78
|
|
|
|
|
|
|
[ qw( msgstr_1 -msgstr_1 msgstr_1 ) ], # plural or singular
|
79
|
|
|
|
|
|
|
[ qw( msgstr_2 -msgstr_2 msgstr_2 ) ], # plural
|
80
|
|
|
|
|
|
|
[ qw( msgstr_3 -msgstr_3 msgstr_3 ) ], # plural
|
81
|
|
|
|
|
|
|
[ qw( msgstr_4 -msgstr_4 msgstr_4 ) ], # plural
|
82
|
|
|
|
|
|
|
[ qw( msgstr_5 -msgstr_5 msgstr_5 ) ], # plural
|
83
|
|
|
|
|
|
|
)
|
84
|
|
|
|
|
|
|
: ()
|
85
|
|
|
|
|
|
|
),
|
86
|
|
|
|
|
|
|
# prevoius
|
87
|
|
|
|
|
|
|
(
|
88
|
|
|
|
|
|
|
$has_previous
|
89
|
|
|
|
|
|
|
? (
|
90
|
|
|
|
|
|
|
[ qw( previous_msgctxt -previous_msgctxt previous_msgctxt ) ],
|
91
|
|
|
|
|
|
|
[ qw( previous_msgid -previous_msgid previous_msgid ) ],
|
92
|
|
|
|
|
|
|
[ qw( previous_msgid_plural -previous_msgid_plural previous_msgid_plural ) ],
|
93
|
|
|
|
|
|
|
)
|
94
|
|
|
|
|
|
|
: ()
|
95
|
|
|
|
|
|
|
),
|
96
|
|
|
|
|
|
|
# format-flags
|
97
|
|
|
|
|
|
|
(
|
98
|
|
|
|
|
|
|
map { ## no critic (ComplexMappings)
|
99
|
|
|
|
|
|
|
(my $col_name = $_) =~ tr{-}{_};
|
100
|
|
|
|
|
|
|
# dummy
|
101
|
|
|
|
|
|
|
([ $col_name, "-$_", $_ ]);
|
102
|
|
|
|
|
|
|
} $config->elements()
|
103
|
|
|
|
|
|
|
),
|
104
|
|
|
|
|
|
|
);
|
105
|
|
|
|
|
|
|
|
106
|
|
|
|
|
|
|
@COL_NAMES = map {$_->[0]} @cols; # for SQL
|
107
|
|
|
|
|
|
|
@COL_PARAMETERS = map {$_->[1]} @cols; # for DBD::PO::Locale::PO->new(...)
|
108
|
|
|
|
|
|
|
@COL_METHODS = map {$_->[2]} @cols; # it is the method for the $po object
|
109
|
|
|
|
|
|
|
|
110
|
|
|
|
|
|
|
return;
|
111
|
|
|
|
|
|
|
}
|
112
|
|
|
|
|
|
|
init();
|
113
|
|
|
|
|
|
|
|
114
|
|
|
|
|
|
|
my $dequote = sub {
|
115
|
|
|
|
|
|
|
my $string = shift;
|
116
|
|
|
|
|
|
|
|
117
|
|
|
|
|
|
|
return if $string eq 'NULL';
|
118
|
|
|
|
|
|
|
if ($string =~ s{\A _Q_U_O_T_E_D_:}{}xms) {
|
119
|
|
|
|
|
|
|
$string =~ s{\\\\}{\\}xmsg;
|
120
|
|
|
|
|
|
|
}
|
121
|
|
|
|
|
|
|
|
122
|
|
|
|
|
|
|
return $string;
|
123
|
|
|
|
|
|
|
};
|
124
|
|
|
|
|
|
|
|
125
|
|
|
|
|
|
|
my $array_from_anything = sub {
|
126
|
|
|
|
|
|
|
my ($self, $anything) = @_;
|
127
|
|
|
|
|
|
|
|
128
|
|
|
|
|
|
|
my @array = map { ## no critic (ComplexMappings)
|
129
|
|
|
|
|
|
|
my $dequoted = $dequote->($_);
|
130
|
|
|
|
|
|
|
split m{\Q$self->{separator}\E}xms, $dequoted;
|
131
|
|
|
|
|
|
|
} ref $anything eq 'ARRAY'
|
132
|
|
|
|
|
|
|
? @{$anything}
|
133
|
|
|
|
|
|
|
: defined $anything
|
134
|
|
|
|
|
|
|
? $anything
|
135
|
|
|
|
|
|
|
: ();
|
136
|
|
|
|
|
|
|
|
137
|
|
|
|
|
|
|
return \@array;
|
138
|
|
|
|
|
|
|
};
|
139
|
|
|
|
|
|
|
|
140
|
|
|
|
|
|
|
sub new { ## no critic (RequireArgUnpacking)
|
141
|
|
|
|
|
|
|
my ($class, $options) = validate_pos(
|
142
|
|
|
|
|
|
|
@_,
|
143
|
|
|
|
|
|
|
{type => SCALAR},
|
144
|
|
|
|
|
|
|
{type => HASHREF},
|
145
|
|
|
|
|
|
|
);
|
146
|
|
|
|
|
|
|
$options = validate_with(
|
147
|
|
|
|
|
|
|
params => $options,
|
148
|
|
|
|
|
|
|
spec => {
|
149
|
|
|
|
|
|
|
eol => {type => SCALAR, default => $EOL_DEFAULT},
|
150
|
|
|
|
|
|
|
separator => {type => SCALAR, default => $SEPARATOR_DEFAULT},
|
151
|
|
|
|
|
|
|
charset => {type => SCALAR | UNDEF, optional => 1},
|
152
|
|
|
|
|
|
|
},
|
153
|
|
|
|
|
|
|
called => "2nd parameter of new('$class', \$hash_ref)",
|
154
|
|
|
|
|
|
|
);
|
155
|
|
|
|
|
|
|
|
156
|
|
|
|
|
|
|
if ($options->{charset}) {
|
157
|
|
|
|
|
|
|
$options->{encoding} = ":encoding($options->{charset})";
|
158
|
|
|
|
|
|
|
}
|
159
|
|
|
|
|
|
|
|
160
|
|
|
|
|
|
|
return bless $options, $class;
|
161
|
|
|
|
|
|
|
}
|
162
|
|
|
|
|
|
|
|
163
|
|
|
|
|
|
|
sub write_entry { ## no critic (ExcessComplexity)
|
164
|
|
|
|
|
|
|
my ($self, $file_name, $file_handle, $col_ref) = @_;
|
165
|
|
|
|
|
|
|
|
166
|
|
|
|
|
|
|
my %line;
|
167
|
|
|
|
|
|
|
for my $index (0 .. $#COL_NAMES) {
|
168
|
|
|
|
|
|
|
my $parameter = $COL_PARAMETERS[$index];
|
169
|
|
|
|
|
|
|
my $values = $array_from_anything->($self, $col_ref->[$index]);
|
170
|
|
|
|
|
|
|
if ( ## no critic (CascadingIfElse)
|
171
|
|
|
|
|
|
|
$parameter eq '-comment'
|
172
|
|
|
|
|
|
|
|| $parameter eq '-automatic'
|
173
|
|
|
|
|
|
|
|| $parameter eq '-reference'
|
174
|
|
|
|
|
|
|
) {
|
175
|
|
|
|
|
|
|
if (@{$values}) {
|
176
|
|
|
|
|
|
|
$line{$parameter} = join $self->{eol}, @{$values};
|
177
|
|
|
|
|
|
|
}
|
178
|
|
|
|
|
|
|
}
|
179
|
|
|
|
|
|
|
elsif (
|
180
|
|
|
|
|
|
|
$parameter eq '-obsolete'
|
181
|
|
|
|
|
|
|
|| $parameter eq '-fuzzy'
|
182
|
|
|
|
|
|
|
) {
|
183
|
|
|
|
|
|
|
$line{$parameter} = $values->[0] ? 1 : 0;
|
184
|
|
|
|
|
|
|
}
|
185
|
|
|
|
|
|
|
elsif (
|
186
|
|
|
|
|
|
|
my ($prefix) = $parameter =~ m{\A - ( [a-z-]+ ) -format \z}xms
|
187
|
|
|
|
|
|
|
) {
|
188
|
|
|
|
|
|
|
my $flag = $values->[0];
|
189
|
|
|
|
|
|
|
# translate:
|
190
|
|
|
|
|
|
|
# perl_false => nothing set
|
191
|
|
|
|
|
|
|
# -something => -no-flag = 1
|
192
|
|
|
|
|
|
|
# something => -flag = 1
|
193
|
|
|
|
|
|
|
if ($flag) {
|
194
|
|
|
|
|
|
|
$line{
|
195
|
|
|
|
|
|
|
(
|
196
|
|
|
|
|
|
|
$flag =~ m{\A -}xms
|
197
|
|
|
|
|
|
|
? '-no'
|
198
|
|
|
|
|
|
|
: q{}
|
199
|
|
|
|
|
|
|
)
|
200
|
|
|
|
|
|
|
. "-$prefix-format"
|
201
|
|
|
|
|
|
|
} = 1;
|
202
|
|
|
|
|
|
|
}
|
203
|
|
|
|
|
|
|
}
|
204
|
|
|
|
|
|
|
elsif ( $parameter =~ m{\A -msgstr_ ( \d ) \z}xms ) {
|
205
|
|
|
|
|
|
|
if ( @{$values} ) {
|
206
|
|
|
|
|
|
|
$line{'-msgstr_n'}->{$1} = join "\n", @{$values};
|
207
|
|
|
|
|
|
|
}
|
208
|
|
|
|
|
|
|
}
|
209
|
|
|
|
|
|
|
else {
|
210
|
|
|
|
|
|
|
if ( @{$values} ) {
|
211
|
|
|
|
|
|
|
$line{$parameter} = join "\n", @{$values};
|
212
|
|
|
|
|
|
|
if (! tell $file_handle) {
|
213
|
|
|
|
|
|
|
if ($parameter eq '-msgid') {
|
214
|
|
|
|
|
|
|
croak 'A header has no msgid';
|
215
|
|
|
|
|
|
|
}
|
216
|
|
|
|
|
|
|
else { # -msgstr
|
217
|
|
|
|
|
|
|
if ($line{$parameter} !~ m{\b charset =}xms) { ## no critic (DeepNests)
|
218
|
|
|
|
|
|
|
croak 'This can not be a header';
|
219
|
|
|
|
|
|
|
}
|
220
|
|
|
|
|
|
|
}
|
221
|
|
|
|
|
|
|
}
|
222
|
|
|
|
|
|
|
}
|
223
|
|
|
|
|
|
|
else {
|
224
|
|
|
|
|
|
|
if ($parameter eq '-msgid' && tell $file_handle) {
|
225
|
|
|
|
|
|
|
croak 'A line has to have a msgid';
|
226
|
|
|
|
|
|
|
}
|
227
|
|
|
|
|
|
|
elsif ($parameter eq '-msgstr' && ! tell $file_handle) {
|
228
|
|
|
|
|
|
|
croak 'A header has to have a msgstr';
|
229
|
|
|
|
|
|
|
}
|
230
|
|
|
|
|
|
|
}
|
231
|
|
|
|
|
|
|
}
|
232
|
|
|
|
|
|
|
++$index;
|
233
|
|
|
|
|
|
|
}
|
234
|
|
|
|
|
|
|
my $line = DBD::PO::Locale::PO->new(
|
235
|
|
|
|
|
|
|
eol => $self->{eol},
|
236
|
|
|
|
|
|
|
'-msgid' => q{},
|
237
|
|
|
|
|
|
|
(
|
238
|
|
|
|
|
|
|
exists $line{'-msgid_plural'}
|
239
|
|
|
|
|
|
|
? ('-msgstr_n' => { 0 => q{} })
|
240
|
|
|
|
|
|
|
: ('-msgstr' => q{})
|
241
|
|
|
|
|
|
|
),
|
242
|
|
|
|
|
|
|
%line,
|
243
|
|
|
|
|
|
|
)->dump();
|
244
|
|
|
|
|
|
|
print {$file_handle} $line
|
245
|
|
|
|
|
|
|
or croak "Print $file_name: $OS_ERROR";
|
246
|
|
|
|
|
|
|
|
247
|
|
|
|
|
|
|
return $self;
|
248
|
|
|
|
|
|
|
}
|
249
|
|
|
|
|
|
|
|
250
|
|
|
|
|
|
|
sub read_entry {
|
251
|
|
|
|
|
|
|
my ($self, $file_name, $file_handle) = @_;
|
252
|
|
|
|
|
|
|
|
253
|
|
|
|
|
|
|
if (! defined $self->{line_number}) {
|
254
|
|
|
|
|
|
|
$self->{line_number} = 0;
|
255
|
|
|
|
|
|
|
}
|
256
|
|
|
|
|
|
|
my $po = DBD::PO::Locale::PO->load_entry(
|
257
|
|
|
|
|
|
|
$file_name,
|
258
|
|
|
|
|
|
|
$file_handle,
|
259
|
|
|
|
|
|
|
\$self->{line_number},
|
260
|
|
|
|
|
|
|
$self->{eol},
|
261
|
|
|
|
|
|
|
);
|
262
|
|
|
|
|
|
|
# EOF
|
263
|
|
|
|
|
|
|
if (! $po) {
|
264
|
|
|
|
|
|
|
delete $self->{line_number};
|
265
|
|
|
|
|
|
|
return [];
|
266
|
|
|
|
|
|
|
}
|
267
|
|
|
|
|
|
|
# run a line, it is a po object
|
268
|
|
|
|
|
|
|
my @cols;
|
269
|
|
|
|
|
|
|
my $index = 0;
|
270
|
|
|
|
|
|
|
METHOD:
|
271
|
|
|
|
|
|
|
for my $method (@COL_METHODS) {
|
272
|
|
|
|
|
|
|
if ( ## no critic (CascadingIfElse)
|
273
|
|
|
|
|
|
|
$method eq 'comment'
|
274
|
|
|
|
|
|
|
|| $method eq 'automatic'
|
275
|
|
|
|
|
|
|
|| $method eq 'reference'
|
276
|
|
|
|
|
|
|
) {
|
277
|
|
|
|
|
|
|
my $comment = $po->$method();
|
278
|
|
|
|
|
|
|
$cols[$index]
|
279
|
|
|
|
|
|
|
= defined $comment
|
280
|
|
|
|
|
|
|
? (
|
281
|
|
|
|
|
|
|
join $self->{separator},
|
282
|
|
|
|
|
|
|
split m{\Q$self->{eol}\E}xms,
|
283
|
|
|
|
|
|
|
$comment
|
284
|
|
|
|
|
|
|
)
|
285
|
|
|
|
|
|
|
: q{};
|
286
|
|
|
|
|
|
|
}
|
287
|
|
|
|
|
|
|
elsif (
|
288
|
|
|
|
|
|
|
$method eq 'obsolete'
|
289
|
|
|
|
|
|
|
|| $method eq 'fuzzy'
|
290
|
|
|
|
|
|
|
) {
|
291
|
|
|
|
|
|
|
$cols[$index] = $po->$method() ? 1 : 0;
|
292
|
|
|
|
|
|
|
}
|
293
|
|
|
|
|
|
|
elsif ( $method =~ m{\A [a-z-]+ -format \z}xms) {
|
294
|
|
|
|
|
|
|
my $flag = $po->format_flag($method);
|
295
|
|
|
|
|
|
|
# translate:
|
296
|
|
|
|
|
|
|
# undef => 0
|
297
|
|
|
|
|
|
|
# 0 => -1
|
298
|
|
|
|
|
|
|
# 1 => 1
|
299
|
|
|
|
|
|
|
$cols[$index] = defined $flag
|
300
|
|
|
|
|
|
|
? (
|
301
|
|
|
|
|
|
|
$flag ? 1 : -1 ## no critic (MagicNumbers)
|
302
|
|
|
|
|
|
|
)
|
303
|
|
|
|
|
|
|
: 0;
|
304
|
|
|
|
|
|
|
}
|
305
|
|
|
|
|
|
|
elsif (
|
306
|
|
|
|
|
|
|
$method =~ m{
|
307
|
|
|
|
|
|
|
\A (?:
|
308
|
|
|
|
|
|
|
msgstr
|
309
|
|
|
|
|
|
|
| (?: msg | previous_msg ) (?: ctxt | id | id_plural )
|
310
|
|
|
|
|
|
|
) \z
|
311
|
|
|
|
|
|
|
}xms
|
312
|
|
|
|
|
|
|
) {
|
313
|
|
|
|
|
|
|
my $data = $po->$method();
|
314
|
|
|
|
|
|
|
if (! defined $data) {
|
315
|
|
|
|
|
|
|
$data = q{};
|
316
|
|
|
|
|
|
|
}
|
317
|
|
|
|
|
|
|
$cols[$index]
|
318
|
|
|
|
|
|
|
= join $self->{separator},
|
319
|
|
|
|
|
|
|
split m{\\n}xms,
|
320
|
|
|
|
|
|
|
$data;
|
321
|
|
|
|
|
|
|
}
|
322
|
|
|
|
|
|
|
elsif ( my ($n) = $method =~ m{\A msgstr_ ( \d ) \z}xms ) {
|
323
|
|
|
|
|
|
|
my $data = $po->msgstr_n();
|
324
|
|
|
|
|
|
|
if ($data) {
|
325
|
|
|
|
|
|
|
$data = $data->{$n};
|
326
|
|
|
|
|
|
|
}
|
327
|
|
|
|
|
|
|
if (! defined $data) {
|
328
|
|
|
|
|
|
|
$data = q{};
|
329
|
|
|
|
|
|
|
}
|
330
|
|
|
|
|
|
|
$cols[$index]
|
331
|
|
|
|
|
|
|
= join $self->{separator},
|
332
|
|
|
|
|
|
|
split m{\\n}xms,
|
333
|
|
|
|
|
|
|
$data;
|
334
|
|
|
|
|
|
|
}
|
335
|
|
|
|
|
|
|
else {
|
336
|
|
|
|
|
|
|
croak "Strange extract method $method";
|
337
|
|
|
|
|
|
|
}
|
338
|
|
|
|
|
|
|
++$index;
|
339
|
|
|
|
|
|
|
}
|
340
|
|
|
|
|
|
|
|
341
|
|
|
|
|
|
|
return \@cols;
|
342
|
|
|
|
|
|
|
}
|
343
|
|
|
|
|
|
|
|
344
|
|
|
|
|
|
|
1;
|
345
|
|
|
|
|
|
|
|
346
|
|
|
|
|
|
|
__END__
|