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