1 | # Copyright (C) 1997, 2001, 2002, 2003 Free Software Foundation, Inc.
|
---|
2 |
|
---|
3 | # This program is free software; you can redistribute it and/or modify
|
---|
4 | # it under the terms of the GNU General Public License as published by
|
---|
5 | # the Free Software Foundation; either version 2, or (at your option)
|
---|
6 | # any later version.
|
---|
7 |
|
---|
8 | # This program is distributed in the hope that it will be useful,
|
---|
9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
|
---|
10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
---|
11 | # GNU General Public License for more details.
|
---|
12 |
|
---|
13 | # You should have received a copy of the GNU General Public License
|
---|
14 | # along with this program; if not, write to the Free Software
|
---|
15 | # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
---|
16 | # 02111-1307, USA.
|
---|
17 |
|
---|
18 | package Automake::DisjConditions;
|
---|
19 |
|
---|
20 | use Carp;
|
---|
21 | use strict;
|
---|
22 | use Automake::Condition qw/TRUE FALSE/;
|
---|
23 |
|
---|
24 | =head1 NAME
|
---|
25 |
|
---|
26 | Automake::DisjConditions - record a disjunction of Conditions
|
---|
27 |
|
---|
28 | =head1 SYNOPSIS
|
---|
29 |
|
---|
30 | use Automake::Condition;
|
---|
31 | use Automake::DisjConditions;
|
---|
32 |
|
---|
33 | # Create a Condition to represent "COND1 and not COND2".
|
---|
34 | my $cond = new Automake::Condition "COND1_TRUE", "COND2_FALSE";
|
---|
35 | # Create a Condition to represent "not COND3".
|
---|
36 | my $other = new Automake::Condition "COND3_FALSE";
|
---|
37 |
|
---|
38 | # Create a DisjConditions to represent
|
---|
39 | # "(COND1 and not COND2) or (not COND3)"
|
---|
40 | my $set = new Automake::DisjConditions $cond, $other;
|
---|
41 |
|
---|
42 | # Return the list of Conditions involved in $set.
|
---|
43 | my @conds = $set->conds;
|
---|
44 |
|
---|
45 | # Return one of the Condition involved in $set.
|
---|
46 | my $cond = $set->one_cond;
|
---|
47 |
|
---|
48 | # Return true iff $set is always true (i.e. its subconditions
|
---|
49 | # conver all cases).
|
---|
50 | if ($set->true) { ... }
|
---|
51 |
|
---|
52 | # Return false iff $set is always false (i.e. is empty, or contains
|
---|
53 | # only false conditions).
|
---|
54 | if ($set->false) { ... }
|
---|
55 |
|
---|
56 | # Return a string representing the DisjConditions.
|
---|
57 | # "COND1_TRUE COND2_FALSE | COND3_FALSE"
|
---|
58 | my $str = $set->string;
|
---|
59 |
|
---|
60 | # Return a human readable string representing the DisjConditions.
|
---|
61 | # "(COND1 and !COND2) or (!COND3)"
|
---|
62 | my $str = $set->human;
|
---|
63 |
|
---|
64 | # Invert a DisjConditions, i.e., create a new DisjConditions
|
---|
65 | # that complements $set.
|
---|
66 | my $inv = $set->invert;
|
---|
67 |
|
---|
68 | # Multiply two DisjConditions.
|
---|
69 | my $prod = $set1->multiply ($set2);
|
---|
70 |
|
---|
71 | # Return the subconditions of a DisjConditions with respect to
|
---|
72 | # a Condition. See the description for a real example.
|
---|
73 | my $subconds = $set->sub_conditions ($cond);
|
---|
74 |
|
---|
75 | # Check whether a new definition in condition $cond would be
|
---|
76 | # ambiguous w.r.t. existing definitions in $set.
|
---|
77 | ($msg, $ambig_cond) = $set->ambiguous_p ($what, $cond);
|
---|
78 |
|
---|
79 | =head1 DESCRIPTION
|
---|
80 |
|
---|
81 | A C<DisjConditions> is a disjunction of C<Condition>s. In Automake
|
---|
82 | they are used to represent the conditions into which Makefile
|
---|
83 | variables and Makefile rules are defined.
|
---|
84 |
|
---|
85 | If the variable C<VAR> is defined as
|
---|
86 |
|
---|
87 | if COND1
|
---|
88 | if COND2
|
---|
89 | VAR = value1
|
---|
90 | endif
|
---|
91 | endif
|
---|
92 | if !COND3
|
---|
93 | if COND4
|
---|
94 | VAR = value2
|
---|
95 | endif
|
---|
96 | endif
|
---|
97 |
|
---|
98 | then it will be associated a C<DisjConditions> created with
|
---|
99 | the following statement.
|
---|
100 |
|
---|
101 | new Automake::DisjConditions
|
---|
102 | (new Automake::Condition ("COND1_TRUE", "COND2_TRUE"),
|
---|
103 | new Automake::Condition ("COND3_FALSE", "COND4_TRUE"));
|
---|
104 |
|
---|
105 | As you can see, a C<DisjConditions> is made from a list of
|
---|
106 | C<Condition>s. Since C<DisjConditions> is a disjunction, and
|
---|
107 | C<Condition> is a conjunction, the above can be read as
|
---|
108 | follows.
|
---|
109 |
|
---|
110 | (COND1 and COND2) or ((not COND3) and COND4)
|
---|
111 |
|
---|
112 | That's indeed the condition into which C<VAR> has a value.
|
---|
113 |
|
---|
114 | Like C<Condition> objects, a C<DisjConditions> object is unique
|
---|
115 | with respect to its conditions. Two C<DisjConditions> objects created
|
---|
116 | for the same set of conditions will have the same adress. This makes
|
---|
117 | it easy to compare C<DisjConditions>s: just compare the references.
|
---|
118 |
|
---|
119 | =head2 Methods
|
---|
120 |
|
---|
121 | =over 4
|
---|
122 |
|
---|
123 | =item C<$set = new Automake::DisjConditions [@conds]>
|
---|
124 |
|
---|
125 | Create a C<DisjConditions> object from the list of C<Condition>
|
---|
126 | objects passed in arguments.
|
---|
127 |
|
---|
128 | If the C<@conds> list is empty, the C<DisjConditions> is assumed to be
|
---|
129 | false.
|
---|
130 |
|
---|
131 | As explained previously, the reference (object) returned is unique
|
---|
132 | with respect to C<@conds>. For this purpose, duplicate elements are
|
---|
133 | ignored.
|
---|
134 |
|
---|
135 | =cut
|
---|
136 |
|
---|
137 | # Keys in this hash are DisjConditions strings. Values are the
|
---|
138 | # associated object DisjConditions. This is used by `new' to reuse
|
---|
139 | # DisjConditions objects with identical conditions.
|
---|
140 | use vars '%_disjcondition_singletons';
|
---|
141 |
|
---|
142 | sub new ($;@)
|
---|
143 | {
|
---|
144 | my ($class, @conds) = @_;
|
---|
145 | my $self = {
|
---|
146 | hash => {},
|
---|
147 | };
|
---|
148 | bless $self, $class;
|
---|
149 |
|
---|
150 | for my $cond (@conds)
|
---|
151 | {
|
---|
152 | confess "`$cond' isn't a reference" unless ref $cond;
|
---|
153 | confess "`$cond' isn't an Automake::Condition"
|
---|
154 | unless $cond->isa ("Automake::Condition");
|
---|
155 |
|
---|
156 | # This is a disjunction of conditions, so we drop
|
---|
157 | # false conditions. We'll always treat an "empty"
|
---|
158 | # DisjConditions as false for this reason.
|
---|
159 | next if $cond->false;
|
---|
160 |
|
---|
161 | # Store conditions as keys AND as values, because blessed
|
---|
162 | # objects are converted to string when used as keys (so
|
---|
163 | # at least we still have the value when we need to call
|
---|
164 | # a method).
|
---|
165 | $self->{'hash'}{$cond} = $cond;
|
---|
166 | }
|
---|
167 |
|
---|
168 | my $key = $self->string;
|
---|
169 | if (exists $_disjcondition_singletons{$key})
|
---|
170 | {
|
---|
171 | return $_disjcondition_singletons{$key};
|
---|
172 | }
|
---|
173 | $_disjcondition_singletons{$key} = $self;
|
---|
174 | return $self;
|
---|
175 | }
|
---|
176 |
|
---|
177 | =item C<@conds = $set-E<gt>conds>
|
---|
178 |
|
---|
179 | Return the list of C<Condition> objects involved in C<$set>.
|
---|
180 |
|
---|
181 | =cut
|
---|
182 |
|
---|
183 | sub conds ($ )
|
---|
184 | {
|
---|
185 | my ($self) = @_;
|
---|
186 | return @{$self->{'conds'}} if exists $self->{'conds'};
|
---|
187 | my @conds = values %{$self->{'hash'}};
|
---|
188 | @conds = sort { $a->string cmp $b->string } @conds;
|
---|
189 | $self->{'conds'} = [@conds];
|
---|
190 | return @conds;
|
---|
191 | }
|
---|
192 |
|
---|
193 | =item C<$cond = $set-E<gt>one_cond>
|
---|
194 |
|
---|
195 | Return one C<Condition> object involved in C<$set>.
|
---|
196 |
|
---|
197 | =cut
|
---|
198 |
|
---|
199 | sub one_cond ($)
|
---|
200 | {
|
---|
201 | my ($self) = @_;
|
---|
202 | return (%{$self->{'hash'}},)[1];
|
---|
203 | }
|
---|
204 |
|
---|
205 | =item C<$et = $set-E<gt>false>
|
---|
206 |
|
---|
207 | Return 1 iff the C<DisjConditions> object is always false (i.e., if it
|
---|
208 | is empty, or if it contains only false C<Condition>s). Return 0
|
---|
209 | otherwise.
|
---|
210 |
|
---|
211 | =cut
|
---|
212 |
|
---|
213 | sub false ($ )
|
---|
214 | {
|
---|
215 | my ($self) = @_;
|
---|
216 | return 0 == keys %{$self->{'hash'}};
|
---|
217 | }
|
---|
218 |
|
---|
219 | =item C<$et = $set-E<gt>true>
|
---|
220 |
|
---|
221 | Return 1 iff the C<DisjConditions> object is always true (i.e. covers all
|
---|
222 | conditions). Return 0 otherwise.
|
---|
223 |
|
---|
224 | =cut
|
---|
225 |
|
---|
226 | sub true ($ )
|
---|
227 | {
|
---|
228 | my ($self) = @_;
|
---|
229 | return $self->invert->false;
|
---|
230 | }
|
---|
231 |
|
---|
232 | =item C<$str = $set-E<gt>string>
|
---|
233 |
|
---|
234 | Build a string which denotes the C<DisjConditions>.
|
---|
235 |
|
---|
236 | =cut
|
---|
237 |
|
---|
238 | sub string ($ )
|
---|
239 | {
|
---|
240 | my ($self) = @_;
|
---|
241 |
|
---|
242 | return $self->{'string'} if defined $self->{'string'};
|
---|
243 |
|
---|
244 | my $res = '';
|
---|
245 | if ($self->false)
|
---|
246 | {
|
---|
247 | $res = 'FALSE';
|
---|
248 | }
|
---|
249 | else
|
---|
250 | {
|
---|
251 | $res = join (' | ', map { $_->string } $self->conds);
|
---|
252 | }
|
---|
253 |
|
---|
254 | $self->{'string'} = $res;
|
---|
255 | return $res;
|
---|
256 | }
|
---|
257 |
|
---|
258 | =item C<$cond-E<gt>human>
|
---|
259 |
|
---|
260 | Build a human readable string which denotes the C<DisjConditions>.
|
---|
261 |
|
---|
262 | =cut
|
---|
263 |
|
---|
264 | sub human ($ )
|
---|
265 | {
|
---|
266 | my ($self) = @_;
|
---|
267 |
|
---|
268 | return $self->{'human'} if defined $self->{'human'};
|
---|
269 |
|
---|
270 | my $res = '';
|
---|
271 | if ($self->false)
|
---|
272 | {
|
---|
273 | $res = 'FALSE';
|
---|
274 | }
|
---|
275 | else
|
---|
276 | {
|
---|
277 | my @c = $self->conds;
|
---|
278 | if (1 == @c)
|
---|
279 | {
|
---|
280 | $res = $c[0]->human;
|
---|
281 | }
|
---|
282 | else
|
---|
283 | {
|
---|
284 | $res = '(' . join (') or (', map { $_->human } $self->conds) . ')';
|
---|
285 | }
|
---|
286 | }
|
---|
287 | $self->{'human'} = $res;
|
---|
288 | return $res;
|
---|
289 | }
|
---|
290 |
|
---|
291 |
|
---|
292 | =item C<$prod = $set1-E<gt>multiply ($set2)>
|
---|
293 |
|
---|
294 | Multiply two conditional sets.
|
---|
295 |
|
---|
296 | my $set1 = new Automake::DisjConditions
|
---|
297 | (new Automake::Condition ("A_TRUE"),
|
---|
298 | new Automake::Condition ("B_TRUE"));
|
---|
299 | my $set2 = new Automake::DisjConditions
|
---|
300 | (new Automake::Condition ("C_FALSE"),
|
---|
301 | new Automake::Condition ("D_FALSE"));
|
---|
302 |
|
---|
303 | C<$set1-E<gt>multiply ($set2)> will return
|
---|
304 |
|
---|
305 | new Automake::DisjConditions
|
---|
306 | (new Automake::Condition ("A_TRUE", "C_FALSE"),
|
---|
307 | new Automake::Condition ("B_TRUE", "C_FALSE"),;
|
---|
308 | new Automake::Condition ("A_TRUE", "D_FALSE"),
|
---|
309 | new Automake::Condition ("B_TRUE", "D_FALSE"));
|
---|
310 |
|
---|
311 | The argument can also be a C<Condition>.
|
---|
312 |
|
---|
313 | =cut
|
---|
314 |
|
---|
315 | # Same as multiply() but take a list of Conditonals as second argument.
|
---|
316 | # We use this in invert().
|
---|
317 | sub _multiply ($@)
|
---|
318 | {
|
---|
319 | my ($self, @set) = @_;
|
---|
320 | my @res = map { $_->multiply (@set) } $self->conds;
|
---|
321 | return new Automake::DisjConditions (Automake::Condition::reduce_or @res);
|
---|
322 | }
|
---|
323 |
|
---|
324 | sub multiply ($$)
|
---|
325 | {
|
---|
326 | my ($self, $set) = @_;
|
---|
327 | return $self->_multiply ($set) if $set->isa('Automake::Condition');
|
---|
328 | return $self->_multiply ($set->conds);
|
---|
329 | }
|
---|
330 |
|
---|
331 | =item C<$inv = $set-E<gt>invert>
|
---|
332 |
|
---|
333 | Invert a C<DisjConditions>. Return a C<DisjConditions> which is true
|
---|
334 | when C<$set> is false, and vice-versa.
|
---|
335 |
|
---|
336 | my $set = new Automake::DisjConditions
|
---|
337 | (new Automake::Condition ("A_TRUE", "B_TRUE"),
|
---|
338 | new Automake::Condition ("A_FALSE", "B_FALSE"));
|
---|
339 |
|
---|
340 | Calling C<$set-E<gt>invert> will return the following C<DisjConditions>.
|
---|
341 |
|
---|
342 | new Automake::DisjConditions
|
---|
343 | (new Automake::Condition ("A_TRUE", "B_FALSE"),
|
---|
344 | new Automake::Condition ("A_FALSE", "B_TRUE"));
|
---|
345 |
|
---|
346 | We implement the inversion by a product-of-sums to sum-of-products
|
---|
347 | conversion using repeated multiplications. Because of the way we
|
---|
348 | implement multiplication, the result of inversion is in canonical
|
---|
349 | prime implicant form.
|
---|
350 |
|
---|
351 | =cut
|
---|
352 |
|
---|
353 | sub invert($ )
|
---|
354 | {
|
---|
355 | my ($self) = @_;
|
---|
356 |
|
---|
357 | return $self->{'invert'} if defined $self->{'invert'};
|
---|
358 |
|
---|
359 | # The invert of an empty DisjConditions is TRUE.
|
---|
360 | my $res = new Automake::DisjConditions TRUE;
|
---|
361 |
|
---|
362 | # !((a.b)+(c.d)+(e.f))
|
---|
363 | # = (!a+!b).(!c+!d).(!e+!f)
|
---|
364 | # We develop this into a sum of product iteratively, starting from TRUE:
|
---|
365 | # 1) TRUE
|
---|
366 | # 2) TRUE.!a + TRUE.!b
|
---|
367 | # 3) TRUE.!a.!c + TRUE.!b.!c + TRUE.!a.!d + TRUE.!b.!d
|
---|
368 | # 4) TRUE.!a.!c.!e + TRUE.!b.!c.!e + TRUE.!a.!d.!e + TRUE.!b.!d.!e
|
---|
369 | # + TRUE.!a.!c.!f + TRUE.!b.!c.!f + TRUE.!a.!d.!f + TRUE.!b.!d.!f
|
---|
370 | foreach my $cond ($self->conds)
|
---|
371 | {
|
---|
372 | $res = $res->_multiply ($cond->not);
|
---|
373 | }
|
---|
374 |
|
---|
375 | # Cache result.
|
---|
376 | $self->{'invert'} = $res;
|
---|
377 | # It's tempting to also set $res->{'invert'} to $self, but that
|
---|
378 | # is a bad idea as $self hasn't been normalized in any way.
|
---|
379 | # (Different inputs can produce the same inverted set.)
|
---|
380 | return $res;
|
---|
381 | }
|
---|
382 |
|
---|
383 | =item C<$self-E<gt>simplify>
|
---|
384 |
|
---|
385 | Return a C<Disjunction> which is a simplified canonical form of C<$self>.
|
---|
386 | This canonical form contains only prime implicants, but it can contain
|
---|
387 | non-essential prime implicants.
|
---|
388 |
|
---|
389 | =cut
|
---|
390 |
|
---|
391 | sub simplify ($)
|
---|
392 | {
|
---|
393 | my ($self) = @_;
|
---|
394 | return $self->invert->invert;
|
---|
395 | }
|
---|
396 |
|
---|
397 | =item C<$self-E<gt>sub_conditions ($cond)>
|
---|
398 |
|
---|
399 | Return the subconditions of C<$self> that contains C<$cond>, with
|
---|
400 | C<$cond> stripped. More formally, return C<$res> such that
|
---|
401 | C<$res-E<gt>multiply ($cond) == $self-E<gt>multiply ($cond)> and
|
---|
402 | C<$res> does not mention any of the variables in C<$cond>.
|
---|
403 |
|
---|
404 | For instance, consider:
|
---|
405 |
|
---|
406 | my $a = new Automake::DisjConditions
|
---|
407 | (new Automake::Condition ("A_TRUE", "B_TRUE"),
|
---|
408 | new Automake::Condition ("A_TRUE", "C_FALSE"),
|
---|
409 | new Automake::Condition ("A_TRUE", "B_FALSE", "C_TRUE"),
|
---|
410 | new Automake::Condition ("A_FALSE"));
|
---|
411 | my $b = new Automake::DisjConditions
|
---|
412 | (new Automake::Condition ("A_TRUE", "B_FALSE"));
|
---|
413 |
|
---|
414 | Calling C<$a-E<gt>sub_conditions ($b)> will return the following
|
---|
415 | C<DisjConditions>.
|
---|
416 |
|
---|
417 | new Automake::DisjConditions
|
---|
418 | (new Automake::Condition ("C_FALSE"), # From A_TRUE C_FALSE
|
---|
419 | new Automake::Condition ("C_TRUE")); # From A_TRUE B_FALSE C_TRUE"
|
---|
420 |
|
---|
421 | =cut
|
---|
422 |
|
---|
423 | sub sub_conditions ($$)
|
---|
424 | {
|
---|
425 | my ($self, $subcond) = @_;
|
---|
426 |
|
---|
427 | # Make $subcond blindingly apparent in the DisjConditions.
|
---|
428 | # For instance `$b->multiply($a->conds)' (from the POD example) is:
|
---|
429 | # (new Automake::Condition ("FALSE"),
|
---|
430 | # new Automake::Condition ("A_TRUE", "B_FALSE", "C_FALSE"),
|
---|
431 | # new Automake::Condition ("A_TRUE", "B_FALSE", "C_TRUE"),
|
---|
432 | # new Automake::Condition ("FALSE"))
|
---|
433 | my @prodconds = $subcond->multiply ($self->conds);
|
---|
434 |
|
---|
435 | # Now, strip $subcond from the remaining (i.e., non-false) Conditions.
|
---|
436 | my @res = map { $_->false ? () : $_->strip ($subcond) } @prodconds;
|
---|
437 |
|
---|
438 | return new Automake::DisjConditions @res;
|
---|
439 | }
|
---|
440 |
|
---|
441 | =item C<($string, $ambig_cond) = $condset-E<gt>ambiguous_p ($what, $cond)>
|
---|
442 |
|
---|
443 | Check for an ambiguous condition. Return an error message and the
|
---|
444 | other condition involved if we have an ambiguity. Return an empty
|
---|
445 | string and FALSE otherwise.
|
---|
446 |
|
---|
447 | C<$what> is the name of the thing being defined, to use in the error
|
---|
448 | message. C<$cond> is the C<Condition> under which it is being
|
---|
449 | defined. C<$condset> is the C<DisjConditions> under which it had
|
---|
450 | already been defined.
|
---|
451 |
|
---|
452 | =cut
|
---|
453 |
|
---|
454 | sub ambiguous_p ($$$)
|
---|
455 | {
|
---|
456 | my ($self, $var, $cond) = @_;
|
---|
457 |
|
---|
458 | # Note that these rules don't consider the following
|
---|
459 | # example as ambiguous.
|
---|
460 | #
|
---|
461 | # if COND1
|
---|
462 | # FOO = foo
|
---|
463 | # endif
|
---|
464 | # if COND2
|
---|
465 | # FOO = bar
|
---|
466 | # endif
|
---|
467 | #
|
---|
468 | # It's up to the user to not define COND1 and COND2
|
---|
469 | # simultaneously.
|
---|
470 |
|
---|
471 | return ("$var multiply defined in condition " . $cond->human, $cond)
|
---|
472 | if exists $self->{'hash'}{$cond};
|
---|
473 |
|
---|
474 | foreach my $vcond ($self->conds)
|
---|
475 | {
|
---|
476 | return ("$var was already defined in condition " . $vcond->human
|
---|
477 | . ", which includes condition ". $cond->human, $vcond)
|
---|
478 | if $vcond->true_when ($cond);
|
---|
479 |
|
---|
480 | return ("$var was already defined in condition " . $vcond->human
|
---|
481 | . ", which is included in condition " . $cond->human, $vcond)
|
---|
482 | if $cond->true_when ($vcond);
|
---|
483 | }
|
---|
484 | return ('', FALSE);
|
---|
485 | }
|
---|
486 |
|
---|
487 | =head1 SEE ALSO
|
---|
488 |
|
---|
489 | L<Automake::Condition>.
|
---|
490 |
|
---|
491 | =head1 HISTORY
|
---|
492 |
|
---|
493 | C<AM_CONDITIONAL>s and supporting code were added to Automake 1.1o by
|
---|
494 | Ian Lance Taylor <ian@cygnus.org> in 1997. Since then it has been
|
---|
495 | improved by Tom Tromey <tromey@redhat.com>, Richard Boulton
|
---|
496 | <richard@tartarus.org>, Raja R Harinath <harinath@cs.umn.edu>, Akim
|
---|
497 | Demaille <akim@epita.fr>, Pavel Roskin <proski@gnu.org>, and
|
---|
498 | Alexandre Duret-Lutz <adl@gnu.org>.
|
---|
499 |
|
---|
500 | =cut
|
---|
501 |
|
---|
502 | 1;
|
---|
503 |
|
---|
504 | ### Setup "GNU" style for perl-mode and cperl-mode.
|
---|
505 | ## Local Variables:
|
---|
506 | ## perl-indent-level: 2
|
---|
507 | ## perl-continued-statement-offset: 2
|
---|
508 | ## perl-continued-brace-offset: 0
|
---|
509 | ## perl-brace-offset: 0
|
---|
510 | ## perl-brace-imaginary-offset: 0
|
---|
511 | ## perl-label-offset: -2
|
---|
512 | ## cperl-indent-level: 2
|
---|
513 | ## cperl-brace-offset: 0
|
---|
514 | ## cperl-continued-brace-offset: 0
|
---|
515 | ## cperl-label-offset: -2
|
---|
516 | ## cperl-extra-newline-before-brace: t
|
---|
517 | ## cperl-merge-trailing-else: nil
|
---|
518 | ## cperl-continued-statement-offset: 2
|
---|
519 | ## End:
|
---|