[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: Renaming Conditional.pm and ConditionalSet.pm... to what?
From: |
Alexandre Duret-Lutz |
Subject: |
Re: Renaming Conditional.pm and ConditionalSet.pm... to what? |
Date: |
Mon, 20 Jan 2003 00:00:01 +0100 |
User-agent: |
Gnus/5.090008 (Oort Gnus v0.08) Emacs/21.2 (i386-pc-linux-gnu) |
>>> "Raja" == Raja R Harinath <address@hidden> writes:
[...]
Raja> Conditional.pm => Condition.pm
Raja> ConditionalSet.pm => DisjConditions.pm
Raja> and define 'Condition' to be a conjunction of "conditionals": a
Raja> "conditional" being an atomic condition defined by AM_CONDITIONAL.
This looks perfect. Thanks!
I'm installing this on HEAD.
2003-01-19 Alexandre Duret-Lutz <address@hidden>
Rename more files to accomodate 8+3 file systems, and adjust the
vocabulary at the same time: AM_CONDITIONAL defines "conditionals",
and we call "condition" a conjunction of "conditionals".
* lib/am/Conditional.pm: Rename to lib/am/Condition.pm.
* lib/am/tests/Conditional.pl: Rename to lib/am/tests/Condition.pl.
* lib/am/ConditionalSet.pm: Rename to lib/am/DisjConditions.pm.
* lib/am/tests/ConditionalSet.pl: Rename to
lib/am/tests/DisjConditions.pl
* lib/am/Conditional.pm (condition_negate): Rename to ...
* lib/am/Condition.pm (conditional_negate): ... this.
* automake.in: Adjust references to Condition and DisjConditions.
(check_ambiguous_conditional, conditional_ambiguous_p): Rename to ...
(check_ambiguous_condition, condition_ambiguous_p): ... these.
Index: automake.in
===================================================================
RCS file: /cvs/automake/automake/automake.in,v
retrieving revision 1.1416
diff -u -r1.1416 automake.in
--- automake.in 13 Jan 2003 14:04:39 -0000 1.1416
+++ automake.in 19 Jan 2003 22:53:17 -0000
@@ -117,8 +117,8 @@
use Automake::Channels;
use Automake::ChannelDefs;
use Automake::Location;
-use Automake::Conditional qw/TRUE FALSE/;
-use Automake::ConditionalSet;
+use Automake::Condition qw/TRUE FALSE/;
+use Automake::DisjConditions;
use File::Basename;
use Tie::RefHash;
use Carp;
@@ -546,7 +546,8 @@
use constant TARGET_AUTOMAKE => 0; # Target defined by Automake.
use constant TARGET_USER => 1; # Target defined in the user's Makefile.am.
-# This is the conditional stack.
+# This is the conditional stack, updated on if/else/endif, and
+# used to build Condition objects.
my @cond_stack;
# This holds the set of included files.
@@ -700,7 +701,7 @@
# are the values of the variable for condition COND1 and COND2.
my %subobjvar = ();
-# This hash records helper variables used to implement '+=' in conditionals.
+# This hash records helper variables used to implement conditional '+='.
# Keys have the form "VAR:CONDITIONS". The value associated to a key is
# the named of the helper variable used to append to VAR in CONDITIONS.
my %appendvar = ();
@@ -1860,7 +1861,7 @@
# make can't handle backslashes for continuing comments on
# the following line.
define_pretty_variable ('DEP_FILES',
- new Automake::Conditional ('AMDEP_TRUE'),
+ new Automake::Condition ('AMDEP_TRUE'),
INTERNAL, @deplist);
# Generate each `include' individually. Irix 6 make will
@@ -2354,7 +2355,7 @@
my $dname = $derived;
if (variable_defined ($derived . '_SHORTNAME'))
{
- # FIXME: should use the same conditional as
+ # FIXME: should use the same Condition as
# the _SOURCES variable. But this is really
# silly overkill -- nobody should have
# conditional shortnames.
@@ -2951,7 +2952,7 @@
if ($xname ne '')
{
my $depvar = $xname . '_DEPENDENCIES';
- if ((conditional_ambiguous_p ($depvar, $cond,
+ if ((condition_ambiguous_p ($depvar, $cond,
variable_conditions ($depvar)))[0] ne '')
{
# Note that we've examined this.
@@ -4097,7 +4098,7 @@
# relented.
if (variable_defined ('EXTRA_DIST'))
{
- # FIXME: This should be fixed to work with conditionals. That
+ # FIXME: This should be fixed to work with conditions. That
# will require only making the entries in %dist_dirs under the
# appropriate condition. This is meaningful if the nature of
# the distribution should depend upon the configure options
@@ -5867,9 +5868,9 @@
################################################################
-## ------------------------------ ##
-## Handling the condition stack. ##
-## ------------------------------ ##
+## -------------------------------- ##
+## Handling the conditional stack. ##
+## -------------------------------- ##
# $STRING
@@ -5880,7 +5881,7 @@
my ($negate, $cond) = @_;
$cond = "${cond}_TRUE"
unless $cond =~ /^TRUE|FALSE$/;
- $cond = Automake::Conditional::condition_negate ($cond)
+ $cond = Automake::Condition::conditional_negate ($cond)
if $negate;
return $cond;
}
@@ -5898,7 +5899,7 @@
push (@cond_stack, make_conditional_string ($negate, $cond));
- return new Automake::Conditional (@cond_stack);
+ return new Automake::Condition (@cond_stack);
}
@@ -5916,7 +5917,7 @@
}
$cond_stack[$#cond_stack] =
- Automake::Conditional::condition_negate ($cond_stack[$#cond_stack]);
+ Automake::Condition::conditional_negate ($cond_stack[$#cond_stack]);
# If $COND is given, check against it.
if (defined $cond)
@@ -5928,7 +5929,7 @@
if $cond_stack[$#cond_stack] ne $cond;
}
- return new Automake::Conditional (@cond_stack);
+ return new Automake::Condition (@cond_stack);
}
@@ -5958,7 +5959,7 @@
pop @cond_stack;
- return new Automake::Conditional (@cond_stack);
+ return new Automake::Condition (@cond_stack);
}
@@ -5970,17 +5971,17 @@
## ------------------------ ##
-# check_ambiguous_conditional ($VAR, $COND, $WHERE)
+# check_ambiguous_condition ($VAR, $COND, $WHERE)
# -------------------------------------------------
# Check for an ambiguous conditional. This is called when a variable
# is being defined conditionally. If we already know about a
# definition that is true under the same conditions, then we have an
# ambiguity.
-sub check_ambiguous_conditional ($$$)
+sub check_ambiguous_condition ($$$)
{
my ($var, $cond, $where) = @_;
my ($message, $ambig_cond) =
- conditional_ambiguous_p ($var, $cond, variable_conditions ($var));
+ condition_ambiguous_p ($var, $cond, variable_conditions ($var));
if ($message)
{
msg 'syntax', $where, "$message ...", partial => 1;
@@ -5990,14 +5991,14 @@
}
# $STRING, $AMBIG_COND
-# conditional_ambiguous_p ($WHAT, $COND, $CONDSET)
+# condition_ambiguous_p ($WHAT, $COND, $CONDSET)
# ----------------------------------------------
-# Check for an ambiguous conditional. Return an error message and
+# Check for an ambiguous condition. Return an error message and
# the other condition involved if we have one, two empty strings otherwise.
# WHAT: the thing being defined
-# COND: the Conditional under which it is being defined
-# CONDSET: the ConditionalSet under which it had already been defined
-sub conditional_ambiguous_p ($$$)
+# COND: the Condition under which it is being defined
+# CONDSET: the DisjConditions under which it had already been defined
+sub condition_ambiguous_p ($$$)
{
my ($var, $cond, $condset) = @_;
@@ -6062,7 +6063,7 @@
# C = mumble
#
# we should have (we display result as conditional strings in this
-# illustration, but we really return ConditionalSet objects):
+# illustration, but we really return DisjConditions objects):
# variable_not_always_defined_in_cond ('A', 'COND1_TRUE COND2_TRUE')
# => ()
# variable_not_always_defined_in_cond ('A', 'COND1_TRUE')
@@ -6265,7 +6266,7 @@
# There must be no previous value unless the user is redefining
# an Automake variable or an AC_SUBST variable for an existing
# condition.
- check_ambiguous_conditional ($var, $cond, $where)
+ check_ambiguous_condition ($var, $cond, $where)
unless (exists $var_owner{$var}{$cond}
&& (($var_owner{$var}{$cond} == VAR_AUTOMAKE
&& $owner != VAR_AUTOMAKE)
@@ -6486,7 +6487,8 @@
# &variable_conditions_recursive ($VAR)
# -------------------------------------
-# Return the set of conditions for which a variable is defined.
+# Return the set of conditions (as a DisjConditions)
+# for which a variable is defined.
# If the variable is not defined conditionally, and is not defined in
# terms of any variables which are defined conditionally, then this
@@ -6512,7 +6514,7 @@
# Now we want to return all permutations of the subvariable
# conditions.
- return (new Automake::ConditionalSet @new_conds)->permutations;
+ return (new Automake::DisjConditions @new_conds)->permutations;
}
@@ -6527,7 +6529,7 @@
{
my ($var) = @_;
my @conds = keys %{$var_value{$var}};
- return new Automake::ConditionalSet @conds;
+ return new Automake::DisjConditions @conds;
}
@@ -6539,7 +6541,7 @@
{
my ($target) = @_;
my @conds = keys %{$targets{$target}};
- return new Automake::ConditionalSet @conds;
+ return new Automake::DisjConditions @conds;
}
# $BOOLEAN
@@ -6659,7 +6661,7 @@
}
else
{
- push (@new_conds, Automake::Conditional::reduce (@subvar_conds));
+ push (@new_conds, Automake::Condition::reduce (@subvar_conds));
}
}
@@ -6675,7 +6677,7 @@
foreach my $this_cond (@this_conds)
{
my @perms =
- (new Automake::ConditionalSet $this_cond)->permutations->conds;
+ (new Automake::DisjConditions $this_cond)->permutations->conds;
foreach my $perm (@perms)
{
my $ok = 1;
@@ -6829,7 +6831,6 @@
# "TRUE" condition will be returned.
# $PARENT is the variable in which the variable is used: this is used
# only for error messages.
-# Returns the list of conditions.
# For example, if A is defined as "foo $(B) bar", and B is defined as
# "baz", this will return ("foo", "$(B)", "bar")
sub variable_value_as_list
@@ -6879,12 +6880,11 @@
# recursively follow $(...) and ${...} inclusions. It preserves @...@
# substitutions. If COND is 'all', then all values under all
# conditions should be returned; if COND is a particular condition
-# (all conditions are surrounded by @...@) then only the value for
-# that condition should be returned; otherwise, warn if VAR is
-# conditionally defined. If PARENT is specified, it is the name of
-# the including variable; this is only used for error reports.
-# If $LOC_WANTED is set, return a list of [$location, @values] instead
-# of a list of @values.
+# then only the value for that condition should be returned;
+# otherwise, warn if VAR is conditionally defined. If PARENT is
+# specified, it is the name of the including variable; this is only
+# used for error reports. If $LOC_WANTED is set, return a list of
+# [$location, @values] instead of a list of @values.
sub variable_value_as_list_recursive_worker ($$$$)
{
my ($var, $cond, $parent, $loc_wanted) = @_;
@@ -7037,7 +7037,7 @@
# &define_pretty_variable ($VAR, $COND, $WHERE, @VALUE)
# -----------------------------------------------------
# Like define_variable, but the value is a list, and the variable may
-# be defined conditionally. The second argument is the conditional
+# be defined conditionally. The second argument is the Condition
# under which the value should be defined; this should be the empty
# string to define the variable unconditionally. The third argument
# is a list holding the values to use for the variable. The value is
@@ -7201,9 +7201,9 @@
# Define a new rule. $TARGET is the rule name. $SOURCE
# is the filename the rule comes from. $OWNER is the
# owner of the rule (TARGET_AUTOMAKE or TARGET_USER).
-# $COND is the condition string under which the rule is defined.
-# $WHERE is the location where the rule is defined.
-# Returns a (possibly empty) list of conditions where the rule
+# $COND is the Condition under which the rule is defined.
+# $WHERE is the Location where the rule is defined.
+# Returns a (possibly empty) list of Conditions where the rule
# should be defined.
sub rule_define ($$$$$)
{
@@ -7290,7 +7290,7 @@
# "... `$target' previously defined here");
}
# Return so we don't redefine the rule in our tables,
- # don't check for ambiguous conditional, etc. The rule
+ # don't check for ambiguous condition, etc. The rule
# will be output anyway beauce &read_am_file ignore the
# return code.
return ();
@@ -7340,7 +7340,7 @@
# Check ambiguous conditional definitions.
my ($message, $ambig_cond) =
- conditional_ambiguous_p ($target, $cond, target_conditions ($target));
+ condition_ambiguous_p ($target, $cond, target_conditions ($target));
if ($message) # We have an ambiguty.
{
if ($owner == TARGET_USER)
@@ -7354,7 +7354,7 @@
else
{
# FIXME: for Automake rules, we can't diagnose ambiguities yet.
- # The point is that Automake doesn't propagate conditionals
+ # The point is that Automake doesn't propagate conditions
# everywhere. For instance &handle_PROGRAMS doesn't care if
# bin_PROGRAMS was defined conditionally or not.
# On the following input
@@ -7368,7 +7368,7 @@
# in condition TRUE (which conflicts with COND1). Fixing
# this in &handle_PROGRAMS and siblings seems hard: you'd
# have to explain &file_contents what to do with a
- # conditional. So for now we do our best *here*. If `foo:'
+ # condition. So for now we do our best *here*. If `foo:'
# was already defined in condition COND1 and we want to define
# it in condition TRUE, then define it only in condition !COND1.
# (See cond14.test and cond15.test for some test cases.)
@@ -7522,7 +7522,7 @@
# sure it is the same on exit. This lets us conditonally include
# other files.
my @saved_cond_stack = @cond_stack;
- my $cond = new Automake::Conditional (@cond_stack);
+ my $cond = new Automake::Condition (@cond_stack);
my $last_var_name = '';
my $last_var_type = '';
@@ -7568,7 +7568,7 @@
{
if ($prev_state == IN_RULE_DEF)
{
- my $cond = new Automake::Conditional @cond_stack;
+ my $cond = new Automake::Condition @cond_stack;
$output_trailer .= $cond->subst_string;
$output_trailer .= $_;
}
@@ -7629,7 +7629,7 @@
check_variable_expansions ($_, $where);
$output_trailer .= $comment . $spacing;
- my $cond = new Automake::Conditional @cond_stack;
+ my $cond = new Automake::Condition @cond_stack;
$output_trailer .= $cond->subst_string;
$output_trailer .= $_;
$comment = $spacing = '';
@@ -7702,7 +7702,7 @@
$prev_state = IN_RULE_DEF;
check_variable_expansions ($_, $where);
$output_trailer .= $comment . $spacing;
- my $cond = new Automake::Conditional @cond_stack;
+ my $cond = new Automake::Condition @cond_stack;
$output_trailer .= $cond->subst_string;
$output_trailer .= $_;
$comment = $spacing = '';
@@ -7931,7 +7931,7 @@
# sure it is the same on exit. This lets us conditonally include
# other files.
my @saved_cond_stack = @cond_stack;
- my $cond = new Automake::Conditional (@cond_stack);
+ my $cond = new Automake::Condition (@cond_stack);
foreach (make_paragraphs ($file, %transform))
{
@@ -8019,7 +8019,7 @@
# in %dependencies and $targets will have two rules).
# FIXME: 2. The logic here is not able to output a
- # multi-paragraph rule several time (e.g. for each conditional
+ # multi-paragraph rule several time (e.g. for each condition
# it is defined for) because it only knows the first paragraph.
# FIXME: 3. We are not robust to people defining a subset
Index: lib/Automake/Condition.pm
===================================================================
RCS file: lib/Automake/Condition.pm
diff -N lib/Automake/Condition.pm
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ lib/Automake/Condition.pm 19 Jan 2003 22:53:19 -0000
@@ -0,0 +1,587 @@
+# Copyright (C) 1997, 2001, 2002, 2003 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+# 02111-1307, USA.
+
+package Automake::Condition;
+use strict;
+use Carp;
+
+require Exporter;
+use vars '@ISA', '@EXPORT_OK';
address@hidden = qw/Exporter/;
address@hidden = qw/TRUE FALSE reduce/;
+
+=head1 NAME
+
+Automake::Condition - record a conjunction of conditionals
+
+=head1 SYNOPSIS
+
+ use Automake::Condition;
+
+ # Create a condition to represent "COND1 and not COND2".
+ my $cond = new Automake::Condition "COND1_TRUE", "COND2_FALSE";
+ # Create a condition to represent "not COND3".
+ my $other = new Automake::Condition "COND3_FALSE";
+
+ # Create a condition to represent
+ # "COND1 and not COND2 and not COND3".
+ my $both = $cond->merge ($other);
+
+ # Likewise, but using a list of conditional strings
+ my $both2 = $cond->merge_conds ("COND3_FALSE");
+
+ # Strip from $both any subconditions which are in $other.
+ # This is the opposite of merge.
+ $cond = $both->strip ($other);
+
+ # Return the list of conditions ("COND1_TRUE", "COND2_FALSE"):
+ my @conds = $cond->conds;
+
+ # Is $cond always true? (Not in this example)
+ if ($cond->true) { ... }
+
+ # Is $cond always false? (Not in this example)
+ if ($cond->false) { ... }
+
+ # Return the list of conditionals as a string:
+ # "COND1_TRUE COND2_FALSE"
+ my $str = $cond->string;
+
+ # Return the list of conditionals as a human readable string:
+ # "COND1 and !COND2"
+ my $str = $cond->human;
+
+ # Return the list of conditionals as a AC_SUBST-style string:
+ # "@COND1_TRUE@@COND2_FALSE@"
+ my $subst = $cond->subst_string;
+
+ # Is $cond true when $both is true? (Yes in this example)
+ if ($cond->true_when ($both)) { ... }
+
+ # Is $cond redundant w.r.t. {$other, $both}?
+ # (Yes in this example)
+ if ($cond->redundant_wrt ($other, $both)) { ... }
+
+ # Does $cond imply any of {$other, $both}?
+ # (Not in this example)
+ if ($cond->implies_any ($other, $both)) { ... }
+
+ # Remove superfluous conditionals.
+ # (Returns @cons = ($both) in this example, because
+ # $other and $cond are implied by $both.)
+ @conds = Automake::Condition::reduce ($other, $both, $cond);
+
+ # Invert a Condition. This returns a list of Conditions.
+ @conds = $both->not;
+
+=head1 DESCRIPTION
+
+A C<Condition> is a conjunction of conditionals (i.e., atomic conditions
+defined in F<configure.ac> by C<AM_CONDITIONAL>. In Automake they
+are used to represent the conditions into which F<Makefile> variables and
+F<Makefile> rules are defined.
+
+If the variable C<VAR> is defined as
+
+ if COND1
+ if COND2
+ VAR = value
+ endif
+ endif
+
+then it will be associated a C<Condition> created with
+the following statement.
+
+ new Automake::Condition "COND1_TRUE", "COND2_TRUE";
+
+Remember that a C<Condition> is a I<conjunction> of conditionals, so
+the above C<Condition> means C<VAR> is defined when C<COND1>
+B<and> C<COND2> are true. There is no way to express disjunctions
+(i.e., I<or>s) with this class (but see L<DisjConditions>).
+
+Another point worth to mention is that each C<Condition> object is
+unique with respect to its conditionals. Two C<Condition> objects
+created for the same set of conditionals will have the same adress.
+This makes it easy to compare C<Condition>s, just compare the
+references.
+
+ my $c1 = new Automake::Condition "COND1_TRUE", "COND2_TRUE";
+ my $c2 = new Automake::Condition "COND1_TRUE", "COND2_TRUE";
+ $c1 == $c2; # True!
+
+=head2 Methods
+
+=over 4
+
+=item C<$cond = new Automake::Condition address@hidden>
+
+Return a C<Condition> objects for the conjunctions of conditionals
+listed in C<@conds> as strings.
+
+An item in C<@conds> should be either C<"FALSE">, C<"TRUE">, or have
+the form C<"NAME_FALSE"> or C<"NAME_TRUE"> where C<NAME> can be
+anything (in practice C<NAME> should be the name of a conditional
+declared in F<configure.ac> with C<AM_CONDITIONAL>, but it's not
+C<Automake::Condition>'s responsability to ensure this).
+
+An empty C<@conds> means C<"TRUE">.
+
+As explained previously, the reference (object) returned is unique
+with respect to C<@conds>. For this purpose, duplicate elements are
+ignored, and C<@conds> is rewriten as C<("FALSE")> if it contains
+C<"FALSE"> or two contradictory conditionals (such as C<"NAME_FALSE">
+and C<"NAME_TRUE">.)
+
+Therefore the following two statements create the same object (they
+both create the C<"FALSE"> condition).
+
+ my $c3 = new Automake::Condition "COND1_TRUE", "COND1_FALSE";
+ my $c4 = new Automake::Condition "COND2_TRUE", "FALSE";
+ $c3 == $c4; # True!
+ $c3 == FALSE; # True!
+
+=cut
+
+# Keys in this hash are conditional strings. Values are the
+# associated object conditions. This is used by `new' to reuse
+# Condition objects with identical conditionals.
+use vars '%_condition_singletons';
+# Do NOT reset this hash here. It's already empty by default,
+# and any setting would otherwise occur AFTER the `TRUE' and `FALSE'
+# constants definitions.
+# %_condition_singletons = ();
+
+sub new ($;@)
+{
+ my ($class, @conds) = @_;
+ my $self = {
+ hash => {},
+ };
+ bless $self, $class;
+
+ # Accept strings like "FOO BAR" as shorthand for ("FOO", "BAR").
+ @conds = map { split (' ', $_) } @conds;
+
+ for my $cond (@conds)
+ {
+ next if $cond eq 'TRUE';
+
+ # Catch some common programming errors:
+ # - A Condition passed to new
+ confess "`$cond' is a reference, expected a string" if ref $cond;
+ # - A Condition passed as a string to new
+ confess "`$cond' does not look like a condition" if $cond =~ /::/;
+
+ # Detect cases when @conds can be simplified to FALSE.
+ if (($cond eq 'FALSE' && $#conds > 0)
+ || ($cond =~ /^(.*)_TRUE$/ && exists $self->{'hash'}{"${1}_FALSE"})
+ || ($cond =~ /^(.*)_FALSE$/ && exists $self->{'hash'}{"${1}_TRUE"}))
+ {
+ return &FALSE;
+ }
+
+ $self->{'hash'}{$cond} = 1;
+ }
+
+ my $key = $self->string;
+ if (exists $_condition_singletons{$key})
+ {
+ return $_condition_singletons{$key};
+ }
+ $_condition_singletons{$key} = $self;
+ return $self;
+}
+
+=item C<$newcond = $cond-E<gt>merge ($othercond)>
+
+Return a new condition which is the conjunction of
+C<$cond> and C<$othercond>.
+
+=cut
+
+sub merge ($$)
+{
+ my ($self, $other) = @_;
+ new Automake::Condition $self->conds, $other->conds;
+}
+
+=item C<$newcond = $cond-E<gt>merge_conds (@conds)>
+
+Return a new condition which is the conjunction of C<$cond> and
+C<@conds>, where C<@conds> is a list of conditional strings, as
+passed to C<new>.
+
+=cut
+
+sub merge_conds ($@)
+{
+ my ($self, @conds) = @_;
+ new Automake::Condition $self->conds, @conds;
+}
+
+=item C<$newcond = $cond-E<gt>strip ($minuscond)>
+
+Return a new condition which has all the conditionals of C<$cond>
+except those of C<$minuscond>. This is the opposite of C<merge>.
+
+=cut
+
+sub strip ($$)
+{
+ my ($self, $minus) = @_;
+ my @res;
+ foreach my $cond ($self->conds)
+ {
+ push @res, $cond unless $minus->has ($cond);
+ }
+ return new Automake::Condition @res;
+}
+
+=item C<@list = $cond-E<gt>conds>
+
+Return the set of conditionals defining C<$cond>, as strings. Note that
+this might not be exactly the list passed to C<new> (or a
+concatenation of such lists if C<merge> was used), because of the
+cleanup mentioned in C<new>'s description.
+
+For instance C<$c3-E<gt>conds> will simply return C<("FALSE")>.
+
+=cut
+
+sub conds ($ )
+{
+ my ($self) = @_;
+ my @conds = keys %{$self->{'hash'}};
+ return ("TRUE") unless @conds;
+ return sort @conds;
+}
+
+# Undocumented, shouldn't be needed out of this class.
+sub has ($$)
+{
+ my ($self, $cond) = @_;
+ return exists $self->{'hash'}{$cond};
+}
+
+=item C<$cond-E<gt>false>
+
+Return 1 iff this condition is always false.
+
+=cut
+
+sub false ($ )
+{
+ my ($self) = @_;
+ return $self->has ('FALSE');
+}
+
+=item C<$cond-E<gt>true>
+
+Return 1 iff this condition is always true.
+
+=cut
+
+sub true ($ )
+{
+ my ($self) = @_;
+ return 0 == keys %{$self->{'hash'}};
+}
+
+=item C<$cond-E<gt>string>
+
+Build a string which denotes the condition.
+
+For instance using the C<$cond> definition from L<SYNOPSYS>,
+C<$cond-E<gt>string> will return C<"COND1_TRUE COND2_FALSE">.
+
+=cut
+
+sub string ($ )
+{
+ my ($self) = @_;
+
+ return $self->{'string'} if defined $self->{'string'};
+
+ my $res = '';
+ if ($self->false)
+ {
+ $res = 'FALSE';
+ }
+ else
+ {
+ $res = join (' ', $self->conds);
+ }
+ $self->{'string'} = $res;
+ return $res;
+}
+
+=item C<$cond-E<gt>human>
+
+Build a human readable string which denotes the condition.
+
+For instance using the C<$cond> definition from L<SYNOPSYS>,
+C<$cond-E<gt>string> will return C<"COND1 and !COND2">.
+
+=cut
+
+sub _to_human ($ )
+{
+ my ($s) = @_;
+ if ($s =~ /^(.*)_(TRUE|FALSE)$/)
+ {
+ return (($2 eq 'FALSE') ? '!' : '') . $1;
+ }
+ else
+ {
+ return $s;
+ }
+}
+
+sub human ($ )
+{
+ my ($self) = @_;
+
+ return $self->{'human'} if defined $self->{'human'};
+
+ my $res = '';
+ if ($self->false)
+ {
+ $res = 'FALSE';
+ }
+ else
+ {
+ $res = join (' and ', map { _to_human $_ } $self->conds);
+ }
+ $self->{'human'} = $res;
+ return $res;
+}
+
+=item C<$cond-E<gt>subst_string>
+
+Build a C<AC_SUBST>-style string for output in F<Makefile.in>.
+
+For instance using the C<$cond> definition from L<SYNOPSYS>,
+C<$cond-E<gt>subst_string> will return C<"@COND1_TRUE@@COND2_FALSE@">.
+
+=cut
+
+sub subst_string ($ )
+{
+ my ($self) = @_;
+
+ return $self->{'subst_string'} if defined $self->{'subst_string'};
+
+ my $res = '';
+ if ($self->false)
+ {
+ $res = '#';
+ }
+ elsif (! $self->true)
+ {
+ $res = '@' . join ('@@', sort $self->conds) . '@';
+ }
+ $self->{'subst_string'} = $res;
+ return $res;
+}
+
+=item C<$cond-E<gt>true_when ($when)>
+
+Return 1 iff C<$cond> is true when C<$when> is true.
+Return 0 otherwise.
+
+Using the definitions from L<SYNOPSYS>, C<$cond> is true
+when C<$both> is true, but the converse is wrong.
+
+=cut
+
+sub true_when ($$)
+{
+ my ($self, $when) = @_;
+
+ # Nothing is true when FALSE (not even FALSE itself, but it
+ # shouldn't hurt if you decide to change that).
+ return 0 if $self->false || $when->false;
+
+ # If we are true, we stay true when $when is true :)
+ return 1 if $self->true;
+
+ # $SELF is true under $WHEN if each conditional component of $SELF
+ # exists in $WHEN.
+ foreach my $cond ($self->conds)
+ {
+ return 0 unless $when->has ($cond);
+ }
+ return 1;
+}
+
+=item C<$cond-E<gt>redundant_wrt (@conds)>
+
+Return 1 iff C<$cond> is true for any condition in C<@conds>.
+If @conds is empty, return 1 iff C<$cond> is C<FALSE>.
+Return 0 otherwise.
+
+=cut
+
+sub redundant_wrt ($@)
+{
+ my ($self, @conds) = @_;
+
+ foreach my $cond (@conds)
+ {
+ return 1 if $self->true_when ($cond);
+ }
+ return $self->false;
+}
+
+=item C<$cond-E<gt>implies_any (@conds)>
+
+Return 1 iff C<$cond> implies any of the conditions in C<@conds>.
+Return 0 otherwise.
+
+=cut
+
+sub implies_any ($@)
+{
+ my ($self, @conds) = @_;
+
+ foreach my $cond (@conds)
+ {
+ return 1 if $cond->true_when ($self);
+ }
+ return 0;
+}
+
+=item C<$cond-E<gt>not>
+
+Return a negation of @<$cond> as a list of C<Condition>s.
+This list should be used to construct a C<DisjConditions>
+(we cannot return a C<DisjConditions> from C<Automake::Condition>,
+because that would make these two packages interdependent).
+
+=cut
+
+sub not ($ )
+{
+ my ($self) = @_;
+ return @{$self->{'not'}} if defined $self->{'not'};
+ my @res;
+ for my $cond ($self->conds)
+ {
+ push @res, new Automake::Condition &conditional_negate ($cond);
+ }
+ $self->{'not'} = address@hidden;
+ return @res;
+}
+
+=head2 Other helper functions
+
+=over 4
+
+=item C<TRUE>
+
+The C<"TRUE"> conditional.
+
+=item C<FALSE>
+
+The C<"FALSE"> conditional.
+
+=cut
+
+use constant TRUE => new Automake::Condition "TRUE";
+use constant FALSE => new Automake::Condition "FALSE";
+
+=item C<reduce (@conds)>
+
+Filter a list of conditions so that only the exclusive ones are
+retained. For example, if both C<COND1_TRUE COND2_TRUE> and
+C<COND1_TRUE> are in the list, discard the latter.
+If the input list is empty, return C<(TRUE)>.
+
+=cut
+
+sub reduce (@)
+{
+ my (@conds) = @_;
+ my @ret = ();
+ my $cond;
+ while (@conds > 0)
+ {
+ $cond = shift @conds;
+
+ # FALSE is absorbent.
+ return FALSE
+ if $cond == FALSE;
+
+ if (! $cond->redundant_wrt (@ret, @conds))
+ {
+ push (@ret, $cond);
+ }
+ }
+
+ return TRUE if @ret == 0;
+ return @ret;
+}
+
+=item C<conditional_negate ($condstr)>
+
+Negate a conditional string.
+
+=cut
+
+sub conditional_negate ($)
+{
+ my ($cond) = @_;
+
+ $cond =~ s/TRUE$/TRUEO/;
+ $cond =~ s/FALSE$/TRUE/;
+ $cond =~ s/TRUEO$/FALSE/;
+
+ return $cond;
+}
+
+=head1 SEE ALSO
+
+L<Automake::DisjConditions>.
+
+=head1 HISTORY
+
+C<AM_CONDITIONAL>s and supporting code were added to Automake 1.1o by
+Ian Lance Taylor <address@hidden> in 1997. Since then it has been
+improved by Tom Tromey <address@hidden>, Richard Boulton
+<address@hidden>, Raja R Harinath <address@hidden>,
+Akim Demaille <address@hidden>, and Alexandre Duret-Lutz <address@hidden>.
+
+=cut
+
+1;
+
+### Setup "GNU" style for perl-mode and cperl-mode.
+## Local Variables:
+## perl-indent-level: 2
+## perl-continued-statement-offset: 2
+## perl-continued-brace-offset: 0
+## perl-brace-offset: 0
+## perl-brace-imaginary-offset: 0
+## perl-label-offset: -2
+## cperl-indent-level: 2
+## cperl-brace-offset: 0
+## cperl-continued-brace-offset: 0
+## cperl-label-offset: -2
+## cperl-extra-newline-before-brace: t
+## cperl-merge-trailing-else: nil
+## cperl-continued-statement-offset: 2
+## End:
Index: lib/Automake/Conditional.pm
===================================================================
RCS file: lib/Automake/Conditional.pm
diff -N lib/Automake/Conditional.pm
--- lib/Automake/Conditional.pm 20 Nov 2002 22:33:15 -0000 1.8
+++ /dev/null 1 Jan 1970 00:00:00 -0000
@@ -1,587 +0,0 @@
-# Copyright (C) 1997, 2001, 2002 Free Software Foundation, Inc.
-
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2, or (at your option)
-# any later version.
-
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-# 02111-1307, USA.
-
-package Automake::Conditional;
-use strict;
-use Carp;
-
-require Exporter;
-use vars '@ISA', '@EXPORT_OK';
address@hidden = qw/Exporter/;
address@hidden = qw/TRUE FALSE reduce/;
-
-=head1 NAME
-
-Automake::Conditional - record a conjunction of conditions
-
-=head1 SYNOPSIS
-
- use Automake::Conditional;
-
- # Create a conditional to represent "COND1 and not COND2".
- my $cond = new Automake::Conditional "COND1_TRUE", "COND2_FALSE";
- # Create a conditional to represent "not COND3".
- my $other = new Automake::Conditional "COND3_FALSE";
-
- # Create a conditional to represent
- # "COND1 and not COND2 and not COND3".
- my $both = $cond->merge ($other);
-
- # Likewise, but using a list of atomic conditional strings
- my $both2 = $cond->merge_conds ("COND3_FALSE");
-
- # Strip from $both any subconditions which are in $other.
- # This is the opposite of merge.
- $cond = $both->strip ($other);
-
- # Return the list of conditions ("COND1_TRUE", "COND2_FALSE"):
- my @conds = $cond->conds;
-
- # Is $cond always true? (Not in this example)
- if ($cond->true) { ... }
-
- # Is $cond always false? (Not in this example)
- if ($cond->false) { ... }
-
- # Return the list of conditions as a string:
- # "COND1_TRUE COND2_FALSE"
- my $str = $cond->string;
-
- # Return the list of conditions as a human readable string:
- # "COND1 and !COND2"
- my $str = $cond->human;
-
- # Return the list of conditions as a AC_SUBST-style string:
- # "@COND1_TRUE@@COND2_FALSE@"
- my $subst = $cond->subst_string;
-
- # Is $cond true when $both is true? (Yes in this example)
- if ($cond->true_when ($both)) { ... }
-
- # Is $cond redundant w.r.t. {$other, $both}?
- # (Yes in this example)
- if ($cond->redundant_wrt ($other, $both)) { ... }
-
- # Does $cond imply any of {$other, $both}?
- # (Not in this example)
- if ($cond->implies_any ($other, $both)) { ... }
-
- # Remove superfluous conditions.
- # (Returns @cons = ($both) in this example, because
- # $other and $cond are implied by $both.)
- @conds = Automake::Conditional::reduce ($other, $both, $cond);
-
- # Invert a Conditional. This returns a list of Conditionals.
- @conds = $both->not;
-
-=head1 DESCRIPTION
-
-A C<Conditional> is a conjunction of atomic conditions. In Automake they
-are used to represent the conditions into which Makefile variables and
-Makefile rules are defined.
-
-If the variable C<VAR> is defined as
-
- if COND1
- if COND2
- VAR = value
- endif
- endif
-
-then it will be associated a C<Conditional> created with
-the following statement.
-
- new Automake::Conditional "COND1_TRUE", "COND2_TRUE";
-
-Remember that a C<Conditional> is a I<conjunction> of conditions, so
-the above C<Conditional> means C<VAR> is defined when C<COND1> is true
-B<and> C<COND2> are true. There is no way to express disjunctions
-(i.e., I<or>s) with this class (see L<ConditionalSet>).
-
-Another point worth to mention is that each C<Conditional> object is
-unique with respect to its conditions. Two C<Conditional> objects
-created for the same set of conditions will have the same adress.
-This makes it easy to compare C<Conditional>s, just compare the
-references.
-
- my $c1 = new Automake::Conditional "COND1_TRUE", "COND2_TRUE";
- my $c2 = new Automake::Conditional "COND1_TRUE", "COND2_TRUE";
- $c1 == $c2; # True!
-
-=head2 Methods
-
-=over 4
-
-=item C<$cond = new Automake::Conditional address@hidden>
-
-Return a C<Conditional> objects for the conjunctions of conditions
-listed in C<@conds> as strings.
-
-An item in C<@conds> should be either C<"FALSE">, C<"TRUE">, or have
-the form C<"NAME_FALSE"> or C<"NAME_TRUE"> where C<NAME> can be
-anything (in practice C<NAME> should be the name of a conditional
-declared in F<configure.ac> with C<AM_CONDITIONAL>, but it's not
-C<Automake::Conditional>'s responsability to ensure this).
-
-An empty C<@conds> means C<"TRUE">.
-
-As explained previously, the reference (object) returned is unique
-with respect to C<@conds>. For this purpose, duplicate elements are
-ignored, and C<@conds> is rewriten as C<("FALSE")> if it contains
-C<"FALSE"> or two contradictory conditions (such as C<"NAME_FALSE">
-and C<"NAME_TRUE">.)
-
-Therefore the following two statements create the same object (they
-both create the C<"FALSE"> conditional).
-
- my $c3 = new Automake::Conditional "COND1_TRUE", "COND1_FALSE";
- my $c4 = new Automake::Conditional "COND2_TRUE", "FALSE";
- $c3 == $c4; # True!
- $c3 == FALSE; # True!
-
-=cut
-
-# Keys in this hash are conditionnal strings. Values are the
-# associated object conditions. This is used by `new' to reuse
-# Conditional objects with identical conditions.
-use vars '%_conditional_singletons';
-# Do NOT reset this hash here. It's already empty by default,
-# and any reset would otherwise occur AFTER the `TRUE' and `FALSE'
-# constants definitions.
-# %_conditional_singletons = ();
-
-sub new ($;@)
-{
- my ($class, @conds) = @_;
- my $self = {
- hash => {},
- };
- bless $self, $class;
-
- # Accept strings like "FOO BAR" as shorthand for ("FOO", "BAR").
- @conds = map { split (' ', $_) } @conds;
-
- for my $cond (@conds)
- {
- next if $cond eq 'TRUE';
-
- # Catch some common programming errors:
- # - A conditional passed to new
- confess "`$cond' is a reference, expected a string" if ref $cond;
- # - A conditional passed as a string to new
- confess "`$cond' doesn't look like a condition" if $cond =~ /::/;
-
- # Detect cases when @conds can be simplified to FALSE.
- if (($cond eq 'FALSE' && $#conds > 0)
- || ($cond =~ /^(.*)_TRUE$/ && exists $self->{'hash'}{"${1}_FALSE"})
- || ($cond =~ /^(.*)_FALSE$/ && exists $self->{'hash'}{"${1}_TRUE"}))
- {
- return &FALSE;
- }
-
- $self->{'hash'}{$cond} = 1;
- }
-
- my $key = $self->string;
- if (exists $_conditional_singletons{$key})
- {
- return $_conditional_singletons{$key};
- }
- $_conditional_singletons{$key} = $self;
- return $self;
-}
-
-=item C<$newcond = $cond-E<gt>merge ($othercond)>
-
-Return a new condition which is the conjunction of
-C<$cond> and C<$othercond>.
-
-=cut
-
-sub merge ($$)
-{
- my ($self, $other) = @_;
- new Automake::Conditional $self->conds, $other->conds;
-}
-
-=item C<$newcond = $cond-E<gt>merge_conds (@conds)>
-
-Return a new condition which is the conjunction of C<$cond> and
-C<@conds>, where C<@conds> is a list of atomic condition strings, as
-passed to C<new>.
-
-=cut
-
-sub merge_conds ($@)
-{
- my ($self, @conds) = @_;
- new Automake::Conditional $self->conds, @conds;
-}
-
-=item C<$newcond = $cond-E<gt>strip ($minuscond)>
-
-Return a new condition which has all the subconditions of C<$cond>
-except those of C<$minuscond>. This is the opposite of C<merge>.
-
-=cut
-
-sub strip ($$)
-{
- my ($self, $minus) = @_;
- my @res;
- foreach my $cond ($self->conds)
- {
- push @res, $cond unless $minus->has ($cond);
- }
- return new Automake::Conditional @res;
-}
-
-=item C<@list = $cond-E<gt>conds>
-
-Return the set of conditions defining C<$cond>, as strings. Note that
-this might not be exactly the list passed to C<new> (or a
-concatenation of such lists if C<merge> was used), because of the
-cleanup mentioned in C<new>'s description.
-
-For instance C<$c3-E<gt>conds> will simply return C<("FALSE")>.
-
-=cut
-
-sub conds ($ )
-{
- my ($self) = @_;
- my @conds = keys %{$self->{'hash'}};
- return ("TRUE") unless @conds;
- return sort @conds;
-}
-
-# Undocumented, shouldn't be needed out of this class.
-sub has ($$)
-{
- my ($self, $cond) = @_;
- return exists $self->{'hash'}{$cond};
-}
-
-=item C<$cond-E<gt>false>
-
-Return 1 iff this condition is always false.
-
-=cut
-
-sub false ($ )
-{
- my ($self) = @_;
- return $self->has ('FALSE');
-}
-
-=item C<$cond-E<gt>true>
-
-Return 1 iff this condition is always true.
-
-=cut
-
-sub true ($ )
-{
- my ($self) = @_;
- return 0 == keys %{$self->{'hash'}};
-}
-
-=item C<$cond-E<gt>string>
-
-Build a string which denotes the conditional.
-
-For instance using the C<$cond> definition from L<SYNOPSYS>,
-C<$cond-E<gt>string> will return C<"COND1_TRUE COND2_FALSE">.
-
-=cut
-
-sub string ($ )
-{
- my ($self) = @_;
-
- return $self->{'string'} if defined $self->{'string'};
-
- my $res = '';
- if ($self->false)
- {
- $res = 'FALSE';
- }
- else
- {
- $res = join (' ', $self->conds);
- }
- $self->{'string'} = $res;
- return $res;
-}
-
-=item C<$cond-E<gt>human>
-
-Build a human readable string which denotes the conditional.
-
-For instance using the C<$cond> definition from L<SYNOPSYS>,
-C<$cond-E<gt>string> will return C<"COND1 and !COND2">.
-
-=cut
-
-sub _to_human ($ )
-{
- my ($s) = @_;
- if ($s =~ /^(.*)_(TRUE|FALSE)$/)
- {
- return (($2 eq 'FALSE') ? '!' : '') . $1;
- }
- else
- {
- return $s;
- }
-}
-
-sub human ($ )
-{
- my ($self) = @_;
-
- return $self->{'human'} if defined $self->{'human'};
-
- my $res = '';
- if ($self->false)
- {
- $res = 'FALSE';
- }
- else
- {
- $res = join (' and ', map { _to_human $_ } $self->conds);
- }
- $self->{'human'} = $res;
- return $res;
-}
-
-=item C<$cond-E<gt>subst_string>
-
-Build a C<AC_SUBST>-style string for output in F<Makefile.in>.
-
-For instance using the C<$cond> definition from L<SYNOPSYS>,
-C<$cond-E<gt>subst_string> will return C<"@COND1_TRUE@@COND2_FALSE@">.
-
-=cut
-
-sub subst_string ($ )
-{
- my ($self) = @_;
-
- return $self->{'subst_string'} if defined $self->{'subst_string'};
-
- my $res = '';
- if ($self->false)
- {
- $res = '#';
- }
- elsif (! $self->true)
- {
- $res = '@' . join ('@@', sort $self->conds) . '@';
- }
- $self->{'subst_string'} = $res;
- return $res;
-}
-
-=item C<$cond-E<gt>true_when ($when)>
-
-Return 1 iff C<$cond> is true when C<$when> is true.
-Return 0 otherwise.
-
-Using the definitions from L<SYNOPSYS>, C<$cond> is true
-when C<$both> is true, but the converse is wrong.
-
-=cut
-
-sub true_when ($$)
-{
- my ($self, $when) = @_;
-
- # Nothing is true when FALSE (not even FALSE itself, but it
- # shouldn't hurt if you decide to change that).
- return 0 if $self->false || $when->false;
-
- # If we are true, we stay true when $when is true :)
- return 1 if $self->true;
-
- # $SELF is true under $WHEN if each conditional component of $SELF
- # exists in $WHEN.
- foreach my $cond ($self->conds)
- {
- return 0 unless $when->has ($cond);
- }
- return 1;
-}
-
-=item C<$cond-E<gt>redundant_wrt (@conds)>
-
-Return 1 iff C<$cond> is true for any condition in C<@conds>.
-If @conds is empty, return 1 iff C<$cond> is C<FALSE>.
-Return 0 otherwise.
-
-=cut
-
-sub redundant_wrt ($@)
-{
- my ($self, @conds) = @_;
-
- foreach my $cond (@conds)
- {
- return 1 if $self->true_when ($cond);
- }
- return $self->false;
-}
-
-=item C<$cond-E<gt>implies_any (@conds)>
-
-Return 1 iff C<$cond> implies any of the conditions in C<@conds>.
-Return 0 otherwise.
-
-=cut
-
-sub implies_any ($@)
-{
- my ($self, @conds) = @_;
-
- foreach my $cond (@conds)
- {
- return 1 if $cond->true_when ($self);
- }
- return 0;
-}
-
-=item C<$cond-E<gt>not>
-
-Return a negation of @<$cond> as a list of C<Conditional>s.
-This list should be used to construct a C<ConditionalSet>
-(we cannot return a C<ConditionalSet> from C<Automake::Conditional>,
-because that would make these two packages interdependent).
-
-=cut
-
-sub not ($ )
-{
- my ($self) = @_;
- return @{$self->{'not'}} if defined $self->{'not'};
- my @res;
- for my $cond ($self->conds)
- {
- push @res, new Automake::Conditional &condition_negate ($cond);
- }
- $self->{'not'} = address@hidden;
- return @res;
-}
-
-=head2 Other helper functions
-
-=over 4
-
-=item C<TRUE>
-
-The C<"TRUE"> conditional.
-
-=item C<FALSE>
-
-The C<"FALSE"> conditional.
-
-=cut
-
-use constant TRUE => new Automake::Conditional "TRUE";
-use constant FALSE => new Automake::Conditional "FALSE";
-
-=item C<reduce (@conds)>
-
-Filter a list of conditionals so that only the exclusive ones are
-retained. For example, if both C<COND1_TRUE COND2_TRUE> and
-C<COND1_TRUE> are in the list, discard the latter.
-If the input list is empty, return C<(TRUE)>.
-
-=cut
-
-sub reduce (@)
-{
- my (@conds) = @_;
- my @ret = ();
- my $cond;
- while (@conds > 0)
- {
- $cond = shift @conds;
-
- # FALSE is absorbent.
- return FALSE
- if $cond == FALSE;
-
- if (! $cond->redundant_wrt (@ret, @conds))
- {
- push (@ret, $cond);
- }
- }
-
- return TRUE if @ret == 0;
- return @ret;
-}
-
-=item C<condition_negate ($condstr)>
-
-Negate a condition string.
-
-=cut
-
-sub condition_negate ($)
-{
- my ($cond) = @_;
-
- $cond =~ s/TRUE$/TRUEO/;
- $cond =~ s/FALSE$/TRUE/;
- $cond =~ s/TRUEO$/FALSE/;
-
- return $cond;
-}
-
-=head1 SEE ALSO
-
-L<Automake::ConditionalSet>.
-
-=head1 HISTORY
-
-C<AM_CONDITIONAL>s and supporting code were added to Automake 1.1o by
-Ian Lance Taylor <address@hidden> in 1997. Since then it has been
-improved by Tom Tromey <address@hidden>, Richard Boulton
-<address@hidden>, Raja R Harinath <address@hidden>, and
-Akim Demaille <address@hidden>. Alexandre Duret-Lutz <address@hidden>
-extracted the code out of Automake to create this package in 2002.
-
-=cut
-
-1;
-
-### Setup "GNU" style for perl-mode and cperl-mode.
-## Local Variables:
-## perl-indent-level: 2
-## perl-continued-statement-offset: 2
-## perl-continued-brace-offset: 0
-## perl-brace-offset: 0
-## perl-brace-imaginary-offset: 0
-## perl-label-offset: -2
-## cperl-indent-level: 2
-## cperl-brace-offset: 0
-## cperl-continued-brace-offset: 0
-## cperl-label-offset: -2
-## cperl-extra-newline-before-brace: t
-## cperl-merge-trailing-else: nil
-## cperl-continued-statement-offset: 2
-## End:
Index: lib/Automake/ConditionalSet.pm
===================================================================
RCS file: lib/Automake/ConditionalSet.pm
diff -N lib/Automake/ConditionalSet.pm
--- lib/Automake/ConditionalSet.pm 20 Nov 2002 22:33:15 -0000 1.9
+++ /dev/null 1 Jan 1970 00:00:00 -0000
@@ -1,774 +0,0 @@
-package Automake::ConditionalSet;
-
-use Carp;
-use strict;
-use Automake::Conditional qw/TRUE FALSE/;
-
-=head1 NAME
-
-Automake::ConditionalSet - record a disjunction of conditions
-
-=head1 SYNOPSIS
-
- use Automake::Conditional;
- use Automake::ConditionalSet;
-
- # Create a conditional to represent "COND1 and not COND2".
- my $cond = new Automake::Conditional "COND1_TRUE", "COND2_FALSE";
- # Create a conditional to represent "not COND3".
- my $other = new Automake::Conditional "COND3_FALSE";
-
- # Create a ConditionalSet to represent
- # "(COND1 and not COND2) or (not COND3)"
- my $set = new Automake::ConditionalSet $cond, $other;
-
- # Return the list of Conditionals involved in $set.
- my @conds = $set->conds;
-
- # Return one of the Conditional involved in $set.
- my $cond = $set->one_cond;
-
- # Return true iff $set is always true (i.e. its subconditions
- # conver all cases).
- if ($set->true) { ... }
-
- # Return false iff $set is always false (i.e. is empty, or contains
- # only false conditions).
- if ($set->false) { ... }
-
- # Return a string representing the ConditionalSet.
- # "COND1_TRUE COND2_FALSE | COND3_FALSE"
- my $str = $set->string;
-
- # Return a human readable string representing the ConditionalSet.
- # "(COND1 and !COND2) or (!COND3)"
- my $str = $set->human;
-
- # Build a new ConditionalSet from the permuation of all
- # subconditions appearing in $set.
- my $perm = $set->permutations;
-
- # Invert a ConditionalSet, i.e., create a new ConditionalSet
- # that complements $set.
- my $inv = $set->invert;
-
- # Multiply two ConditionalSets.
- my $prod = $set1->multiply ($set2)
-
- # Return the subconditions of a ConditionalSet with respect to
- # a Conditional. See the description for a real example.
- my $subconds = $set->sub_conditions ($cond)
-
-=head1 DESCRIPTION
-
-A C<ConditionalSet> is a disjunction of atomic conditions. In
-Automake they are used to represent the conditions into which Makefile
-variables and Makefile rules are defined.
-
-If the variable C<VAR> is defined as
-
- if COND1
- if COND2
- VAR = value1
- endif
- endif
- if !COND3
- if COND4
- VAR = value2
- endif
- endif
-
-then it will be associated a C<ConditionalSet> created with
-the following statement.
-
- new Automake::ConditionalSet
- (new Automake::Conditional ("COND1_TRUE", "COND2_TRUE"),
- new Automake::Conditional ("COND3_FALSE", "COND4_TRUE"));
-
-As you can see, a C<ConditionalSet> is made from a list of
-C<Conditional>s. Since C<ConditionalSet> is a disjunction, and
-C<Conditional> is a conjunction, the above can be read as
-follows.
-
- (COND1 and COND2) or ((not COND3) and COND4)
-
-Like C<Conditional> objects, a C<ConditionalSet> object is unisque
-with respect to its conditions. Two C<ConditionalSet> objects created
-for the same set of conditions will have the same adress. This makes
-it easy to compare C<ConditionalSet>s: just compare the references.
-
-=head2 Methods
-
-=over 4
-
-=item C<$set = new Automake::ConditionalSet address@hidden>
-
-Create a C<ConditionalSet> object from the list of C<Conditional>
-objects passed in arguments.
-
-If the C<@conds> list is empty, the C<ConditionalSet> is assumed to be
-false.
-
-As explained previously, the reference (object) returned is unique
-with respect to C<@conds>. For this purpose, duplicate elements are
-ignored.
-
-=cut
-
-# Keys in this hash are ConditionalSet strings. Values are the
-# associated object ConditionalSet. This is used by `new' to reuse
-# ConditionalSet objects with identical conditions.
-use vars '%_conditional_set_singletons';
-
-sub new ($;@)
-{
- my ($class, @conds) = @_;
- my $self = {
- hash => {},
- };
- bless $self, $class;
-
- for my $cond (@conds)
- {
- confess "`$cond' isn't a reference" unless ref $cond;
- confess "`$cond' isn't an Automake::Conditional"
- unless $cond->isa ("Automake::Conditional");
-
- # This is a disjunction of conditions, so we drop
- # false conditions. We'll always treat an "empty"
- # ConditionalSet as false for this reason.
- next if $cond->false;
-
- # Store conditions as keys AND as values, because blessed
- # objects are converted to string when used as keys (so
- # at least we still have the value when we need to call
- # a method).
- $self->{'hash'}{$cond} = $cond;
- }
-
- my $key = $self->string;
- if (exists $_conditional_set_singletons{$key})
- {
- return $_conditional_set_singletons{$key};
- }
- $_conditional_set_singletons{$key} = $self;
- return $self;
-}
-
-=item C<@conds = $set-E<gt>conds>
-
-Return the list of C<Conditional> objects involved in C<$set>.
-
-=cut
-
-sub conds ($ )
-{
- my ($self) = @_;
- return @{$self->{'conds'}} if exists $self->{'conds'};
- my @conds = values %{$self->{'hash'}};
- @conds = sort { $a->string cmp $b->string } @conds;
- $self->{'conds'} = address@hidden;
- return @conds;
-}
-
-=item C<$cond = $set-E<gt>one_cond>
-
-Return one C<Conditional> object involved in C<$set>.
-
-=cut
-
-sub one_cond ($)
-{
- my ($self) = @_;
- return (%{$self->{'hash'}},)[1];
-}
-
-=item C<$et = $set-E<gt>false>
-
-Return 1 iff the C<ConditionalSet> object is always false (i.e., if it
-is empty, or if it contains only false C<Conditional>s). Return 0
-otherwise.
-
-=cut
-
-sub false ($ )
-{
- my ($self) = @_;
- return 0 == keys %{$self->{'hash'}};
-}
-
-=item C<$et = $set-E<gt>true>
-
-Return 1 iff the C<ConditionalSet> object is always true (i.e. covers all
-conditions). Return 0 otherwise.
-
-=cut
-
-sub true ($ )
-{
- my ($self) = @_;
- # We cache 'true' so that simplify() can use the value if it's available.
- return $self->{'true'} if defined $self->{'true'};
- my $res = $self->invert->false;
- $self->{'true'} = $res;
- return $res;
-}
-
-=item C<$str = $set-E<gt>string>
-
-Build a string which denotes the C<ConditionalSet>.
-
-=cut
-
-sub string ($ )
-{
- my ($self) = @_;
-
- return $self->{'string'} if defined $self->{'string'};
-
- my $res = '';
- if ($self->false)
- {
- $res = 'FALSE';
- }
- else
- {
- $res = join (' | ', map { $_->string } $self->conds);
- }
-
- $self->{'string'} = $res;
- return $res;
-}
-
-=item C<$cond-E<gt>human>
-
-Build a human readable string which denotes the C<ConditionalSet>.
-
-=cut
-
-sub human ($ )
-{
- my ($self) = @_;
-
- return $self->{'human'} if defined $self->{'human'};
-
- my $res = '';
- if ($self->false)
- {
- $res = 'FALSE';
- }
- else
- {
- my @c = $self->conds;
- if (1 == @c)
- {
- $res = $self->human;
- }
- else
- {
- $res = '(' . join (') or (', map { $_->human } $self->conds) . ')';
- }
- }
- $self->{'human'} = $res;
- return $res;
-}
-
-
-sub _permutations_worker (@)
-{
- my @conds = @_;
- return () unless @conds;
-
- my $cond = shift @conds;
-
- # Ignore "TRUE" conditions, since they add nothing to permutations.
- return &_permutations_worker (@conds) if $cond eq "TRUE";
-
- (my $neg = $cond) =~ s/TRUE$/FALSE/;
-
- # Recurse.
- my @ret = ();
- foreach my $c (&_permutations_worker (@conds))
- {
- push (@ret, $c->merge_conds ($cond));
- push (@ret, $c->merge_conds ($neg));
- }
- if (! @ret)
- {
- push (@ret, new Automake::Conditional $cond);
- push (@ret, new Automake::Conditional $neg);
- }
-
- return @ret;
-}
-
-=item C<$perm = $set-E<gt>permutations>
-
-Return a permutations of the subconditions involved in a C<ConditionalSet>.
-
-For instance consider this initial C<ConditionalSet>.
-
- my $set = new Automake::ConditionalSet
- (new Automake::Conditional ("COND1_TRUE", "COND2_TRUE"),
- new Automake::Conditional ("COND3_FALSE", "COND2_TRUE"));
-
-Calling C<$set-E<gt>permutations> will return the following Conditional set.
-
- new Automake::ConditionalSet
- (new Automake::Conditional ("COND1_TRUE", "COND2_TRUE", "COND3_TRUE"),
- new Automake::Conditional ("COND1_FALSE","COND2_TRUE", "COND3_TRUE"),
- new Automake::Conditional ("COND1_TRUE", "COND2_FALSE","COND3_TRUE"),
- new Automake::Conditional ("COND1_FALSE","COND2_FALSE","COND3_TRUE"),
- new Automake::Conditional ("COND1_TRUE", "COND2_TRUE", "COND3_FALSE"),
- new Automake::Conditional ("COND1_FALSE","COND2_TRUE", "COND3_FALSE"),
- new Automake::Conditional ("COND1_TRUE", "COND2_FALSE","COND3_FALSE"),
- new Automake::Conditional ("COND1_FALSE","COND2_FALSE","COND3_FALSE"));
-
-=cut
-
-sub permutations ($ )
-{
- my ($self) = @_;
-
- return $self->{'permutations'} if defined $self->{'permutations'};
-
- my %atomic_conds = ();
-
- for my $conditional ($self->conds)
- {
- for my $cond ($conditional->conds)
- {
- $cond =~ s/FALSE$/TRUE/;
- $atomic_conds{$cond} = 1;
- }
- }
-
- my @res = _permutations_worker (keys %atomic_conds);
- # An empty permutation is TRUE, because we ignore TRUE conditions
- # in the recursions.
- @res = (TRUE) unless @res;
- my $res = new Automake::ConditionalSet @res;
-
- $self->{'permutations'} = $res;
-
- return $res;
-}
-
-=item C<$prod = $set1->multiply ($set2)>
-
-Multiply two conditional sets.
-
- my $set1 = new Automake::ConditionalSet
- (new Automake::Conditional ("A_TRUE"),
- new Automake::Conditional ("B_TRUE"));
- my $set2 = new Automake::ConditionalSet
- (new Automake::Conditional ("C_FALSE"),
- new Automake::Conditional ("D_FALSE"));
-
-C<$set1-E<gt>multiply ($set2)> will return
-
- new Automake::ConditionalSet
- (new Automake::Conditional ("A_TRUE", "C_FALSE"),
- new Automake::Conditional ("B_TRUE", "C_FALSE"),;
- new Automake::Conditional ("A_TRUE", "D_FALSE"),
- new Automake::Conditional ("B_TRUE", "D_FALSE"));
-
-The argument can also be a C<Conditional>.
-
-=cut
-
-# Same as multiply() but take a list of Conditonal as second argument.
-# We use this in invert().
-sub _multiply ($@)
-{
- my ($self, @set) = @_;
- my @res = ();
- foreach my $selfcond ($self->conds)
- {
- foreach my $setcond (@set)
- {
- push @res, $selfcond->merge ($setcond);
- }
- }
- return new Automake::ConditionalSet @res;
-}
-
-sub multiply ($$)
-{
- my ($self, $set) = @_;
- return $self->_multiply ($set) if $set->isa('Automake::Conditional');
- return $self->_multiply ($set->conds);
-}
-
-=item C<$inv = $set-E<gt>invert>
-
-Invert a C<ConditionalSet>. Return a C<ConditionalSet> which is true
-when C<$set> is false, and vice-versa.
-
- my $set = new Automake::ConditionalSet
- (new Automake::Conditional ("A_TRUE", "B_TRUE"),
- new Automake::Conditional ("A_FALSE", "B_FALSE"));
-
-Calling C<$set-E<gt>invert> will return the following C<ConditionalSet>.
-
- new Automake::ConditionalSet
- (new Automake::Conditional ("A_TRUE", "B_FALSE"),
- new Automake::Conditional ("A_FALSE", "B_TRUE"));
-
-=cut
-
-sub invert($ )
-{
- my ($self) = @_;
-
- return $self->{'invert'} if defined $self->{'invert'};
-
- # The invert of an empty ConditionalSet is TRUE.
- my $res = new Automake::ConditionalSet TRUE;
-
- # !((a.b)+(c.d)+(e.f))
- # = (!a+!b).(!c+!d).(!e+!f)
- # We develop this into a sum of product iteratively, starting from TRUE:
- # 1) TRUE
- # 2) TRUE.!a + TRUE.!b
- # 3) TRUE.!a.!c + TRUE.!b.!c + TRUE.!a.!d + TRUE.!b.!d
- # 4) TRUE.!a.!c.!e + TRUE.!b.!c.!e + TRUE.!a.!d.!e + TRUE.!b.!d.!e
- # + TRUE.!a.!c.!f + TRUE.!b.!c.!f + TRUE.!a.!d.!f + TRUE.!b.!d.!f
- foreach my $cond ($self->conds)
- {
- $res = $res->_multiply ($cond->not);
- }
-
- # Cache result.
- $self->{'invert'} = $res;
- # It's tempting to also set $res->{'invert'} to $self, but that
- # is a bad idea as $self hasn't been normalized in any way.
- # (Different inputs can produce the same inverted set.)
- return $res;
-}
-
-=item C<$simp = $set->simplify>
-
-Find prime implicants and return a simplified C<ConditionalSet>.
-
-=cut
-
-sub _simplify ($) # Based on Quine-McCluskey's algorithm.
-{
- my ($self) = @_;
-
- # If we know this ConditionalSet is always true, we have nothing to do.
- # Use the cached value if true if available. Never call true()
- # as this would call invert() which can be slow.
- return new Automake::ConditionalSet TRUE
- if $self->{'hash'}{&TRUE} || $self->{'true'};
-
- my $nvars = 0;
- my %var_rank;
- my @rank_var;
-
- # Initialization.
- # Translate and-terms into bit string pairs: [$true, $false].
- #
- # Each variable is given a bit position in the strings.
- #
- # The first string in the pair tells wether a variable is
- # uncomplemented in the term.
- # The second string tells whether a variable is complemented.
- # If a variable does not appear in the term, then its
- # corresponding bit is unset in both strings.
-
- # Order the resulting bit string pairs by the number of
- # variables involved:
- # @{$subcubes[2]} is the list of string pairs involving two variables.
- # (Level 0 is used for "TRUE".)
- my @subcubes;
- for my $and_conds ($self->conds)
- {
- my $true = 0; # Bit string for uncomplemented variables.
- my $false = 0; # Bit string for complemented variables.
-
- my @conds = $and_conds->conds;
- for my $cond (@conds)
- {
- # Which variable is this condition about?
- confess "can't parse `$cond'"
- unless $cond =~ /^(.*_)(FALSE|TRUE)$/;
-
- # Get the variabe's rank, or assign it a new one.
- my $rank = $var_rank{$1};
- if (! defined $rank)
- {
- $rank = $nvars++;
-
- # FIXME: simplify() cannot work with more that 31 variables.
- # We need a bitset implementation to allow more variables.
- # For now we just return the input, as is, not simplified.
- return $self if $rank >= 31;
-
- $var_rank{$1} = $rank;
- $rank_var[$rank] = $1;
- }
-
- # Fire the relevant bit in the strings.
- if ($2 eq 'FALSE')
- {
- $false |= 1 << $rank;
- }
- else
- {
- $true |= 1 << $rank;
- }
- }
-
- # Register this term.
- push @{$subcubes[1 + $#conds]}, [$true, $false];
- }
-
- # Real work. Let's combine terms.
-
- # Process terms in diminishing size order. Those
- # involving the maximum number of variables first.
- for (my $m = $#subcubes; $m > 0; --$m)
- {
- my $m_subcubes = $#{$subcubes[$m]};
-
- # Consider all terms with $m variables.
- for (my $j = 0; $j <= $m_subcubes; ++$j)
- {
- my $tj = $subcubes[$m][$j];
- my $jtrue = $tj->[0];
- my $jfalse = $tj->[1];
-
- # Compare them with all other terms with $m variables.
- COMBINATION:
- for (my $k = $j + 1; $k <= $m_subcubes; ++$k)
- {
- my $tk = $subcubes[$m][$k];
- my $ktrue = $tk->[0];
- my $kfalse = $tk->[1];
-
- # Two terms can combine if they differ only by one variable
- # (i.e., a bit here), which is complemented in one term
- # and uncomplemented in the other.
- my $true = $jtrue ^ $ktrue;
- my $false = $jfalse ^ $kfalse;
- next COMBINATION if $true != $false;
- # There should be exactly one bit set.
- # (`$true & ($true - 1)' unsets the rightmost 1 bit in $true.)
- next COMBINATION if $true == 0 || $true & ($true - 1);
-
- # At this point we know we can combine the two terms.
-
- # Mark these two terms as "combined", so they will be
- # deleted after we have processed all other combinations.
- $tj->[2] = 1;
- $tk->[2] = 1;
-
- # Actually combine the two terms.
- my $ctrue = $jtrue & $ktrue;
- my $cfalse = $jfalse & $kfalse;
-
- # Don't add the combined term if it already exists.
- DUP_SEARCH:
- for my $c (@{$subcubes[$m - 1]})
- {
- next DUP_SEARCH if $ctrue != $c->[0];
- next COMBINATION if $cfalse == $c->[1];
- }
- push @{$subcubes[$m - 1]}, [$ctrue, $cfalse];
- }
- }
-
- # Delete all covered terms.
- for (my $j = 0; $j <= $m_subcubes; ++$j)
- {
- delete $subcubes[$m][$j] if $subcubes[$m][$j][2];
- }
- }
-
- # Finally merge bit strings back into a Automake::ConditionalSet.
-
- # If level 0 has been filled, we've found `TRUE'. No need to translate
- # anything.
- return new Automake::ConditionalSet TRUE if $#{$subcubes[0]} >= 0;
-
- # Otherwise, translate uncombined terms in other levels.
-
- my @or_conds = ();
- # Process terms in diminishing size order. Those
- # involving the maximum number of variables first.
- for (my $m = 1; $m <= $#subcubes; ++$m)
- {
- my $m_subcubes = $#{$subcubes[$m]};
- # Consider all terms with $m variables.
- for (my $j = 0; $j <= $m_subcubes; ++$j)
- {
- my $tj = $subcubes[$m][$j];
- next unless $tj; # Skip deleted terms.
- my $jtrue = $tj->[0];
- my $jfalse = $tj->[1];
-
- # Filter-out implied terms.
- #
- # An and-term at level N might cover and-terms at level M>N.
- # We need to mark all these covered terms so that they are
- # not output in the result formula.
- #
- # If $tj was generated by combining two terms at level N+1,
- # there two terms are already marked. However there might be
- # implied terms deeper.
- #
- # For instance consider this input: "A_TRUE | A_TRUE C_FALSE".
- #
- # This can also occur with and-term generated by the
- # combining algorith. E.g., consider
- # "A_TRUE B_TRUE" | "A_TRUE B_FALSE" | "A_TRUE C_FALSE D_FALSE"
- # - at level 3 we can't combine "A_TRUE C_FALSE D_FALSE"
- # - at level 2 we can combine "A_TRUE B_TRUE" | "A_TRUE B_FALSE"
- # into "A_TRUE
- # - at level 1 we an't combine "A_TRUE"
- # so without more simplification we would output
- # "A_TRUE | A_TRUE C_FALSE D_FALSE"
- #
- # So let's filter-out and-terms which are implied by other
- # and-terms. An and-term $tk is implied by an and-term $tj if $k
- # involves more variables than $tj (i.e., N>M) and if
- # all variables occurring in $tk also occur in A in the
- # same state (complemented or uncomplemented.)
- for (my $n = $m + 1; $n <= $#subcubes; ++$n)
- {
- my $n_subcubes = $#{$subcubes[$n]};
- for (my $k = 0; $k <= $n_subcubes; ++$k)
- {
- my $tk = $subcubes[$n][$k];
- next unless $tk; # Skip deleted terms.
- my $ktrue = $tk->[0];
- my $kfalse = $tk->[1];
-
- next unless $ktrue == ($ktrue | $jtrue);
- next unless $kfalse == ($kfalse | $jfalse);
-
- delete $subcubes[$n][$k];
- }
- }
-
- # Translate $tj.
- my @and_conds = ();
- my $rank = 0;
- while ($jtrue > 0)
- {
- if ($jtrue & 1)
- {
- push @and_conds, $rank_var[$rank] . 'TRUE';
- }
- $jtrue >>= 1;
- ++$rank;
- }
- $rank = 0;
- while ($jfalse > 0)
- {
- if ($jfalse & 1)
- {
- push @and_conds, $rank_var[$rank] . 'FALSE';
- }
- $jfalse >>= 1;
- ++$rank;
- }
-
- push @or_conds, new Automake::Conditional @and_conds if @and_conds;
- }
- }
-
- return new Automake::ConditionalSet @or_conds;
-}
-
-sub simplify ($)
-{
- my ($self) = @_;
- return $self->{'simplify'} if defined $self->{'simplify'};
- my $res = $self->_simplify ;
- $self->{'simplify'} = $res;
- return $res;
-}
-
-=item C<$self-E<gt>sub_conditions ($cond)>
-
-Return the subconditions of C<$self> that contains C<$cond>, with
-C<$cond> stripped.
-
-For instance, consider:
-
- my $a = new Automake::ConditionalSet
- (new Automake::Conditional ("A_TRUE", "B_TRUE"),
- new Automake::Conditional ("A_TRUE", "C_FALSE"),
- new Automake::Conditional ("A_TRUE", "B_FALSE", "C_TRUE"),
- new Automake::Conditional ("A_FALSE"));
- my $b = new Automake::ConditionalSet
- (new Automake::Conditional ("A_TRUE", "B_FALSE"));
-
-Calling C<$a-E<gt>sub_conditions ($b)> will return the following
-C<ConditionalSet>.
-
- new Automake::ConditionalSet
- (new Automake::Conditional ("C_FALSE"), # From A_TRUE C_FALSE
- new Automake::Conditional ("C_TRUE")); # From A_TRUE B_FALSE C_TRUE"
-
-=cut
-
-sub sub_conditions ($$)
-{
- my ($self, $subcond) = @_;
-
- # Make $subcond blindingly apparent in the ConditionalSet.
- # For instance `$a->_multiply($b)' (from the POD example) is:
- # new Automake::ConditionalSet
- # (new Automake::Conditional ("FALSE"),
- # new Automake::Conditional ("A_TRUE", "B_FALSE", "C_FALSE"),
- # new Automake::Conditional ("A_TRUE", "B_FALSE", "C_TRUE"),
- # new Automake::Conditional ("FALSE"));
- my $prod = $self->_multiply ($subcond);
-
- # Now, strip $subcond from the remaining (i.e., non-false) Conditionals.
- my @res;
- foreach my $c ($prod->conds)
- {
- push @res, $c->strip ($subcond) unless $c->false;
- }
- return new Automake::ConditionalSet @res;
-}
-
-=head1 SEE ALSO
-
-L<Automake::Conditional>.
-
-=head1 HISTORY
-
-C<AM_CONDITIONAL>s and supporting code were added to Automake 1.1o by
-Ian Lance Taylor <address@hidden> in 1997. Since then it has been
-improved by Tom Tromey <address@hidden>, Richard Boulton
-<address@hidden>, Raja R Harinath <address@hidden>, Akim
-Demaille <address@hidden>, and Pavel Roskin <address@hidden>.
-Alexandre Duret-Lutz <address@hidden> extracted the code out of Automake
-to create this package in 2002.
-
-=cut
-
-1;
-
-### Setup "GNU" style for perl-mode and cperl-mode.
-## Local Variables:
-## perl-indent-level: 2
-## perl-continued-statement-offset: 2
-## perl-continued-brace-offset: 0
-## perl-brace-offset: 0
-## perl-brace-imaginary-offset: 0
-## perl-label-offset: -2
-## cperl-indent-level: 2
-## cperl-brace-offset: 0
-## cperl-continued-brace-offset: 0
-## cperl-label-offset: -2
-## cperl-extra-newline-before-brace: t
-## cperl-merge-trailing-else: nil
-## cperl-continued-statement-offset: 2
-## End:
Index: lib/Automake/DisjConditions.pm
===================================================================
RCS file: lib/Automake/DisjConditions.pm
diff -N lib/Automake/DisjConditions.pm
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ lib/Automake/DisjConditions.pm 19 Jan 2003 22:53:20 -0000
@@ -0,0 +1,792 @@
+# Copyright (C) 1997, 2001, 2002, 2003 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+# 02111-1307, USA.
+
+package Automake::DisjConditions;
+
+use Carp;
+use strict;
+use Automake::Condition qw/TRUE FALSE/;
+
+=head1 NAME
+
+Automake::DisjConditions - record a disjunction of Conditions
+
+=head1 SYNOPSIS
+
+ use Automake::Condition;
+ use Automake::DisjConditions;
+
+ # Create a Condition to represent "COND1 and not COND2".
+ my $cond = new Automake::Condition "COND1_TRUE", "COND2_FALSE";
+ # Create a Condition to represent "not COND3".
+ my $other = new Automake::Condition "COND3_FALSE";
+
+ # Create a DisjConditions to represent
+ # "(COND1 and not COND2) or (not COND3)"
+ my $set = new Automake::DisjConditions $cond, $other;
+
+ # Return the list of Conditions involved in $set.
+ my @conds = $set->conds;
+
+ # Return one of the Condition involved in $set.
+ my $cond = $set->one_cond;
+
+ # Return true iff $set is always true (i.e. its subconditions
+ # conver all cases).
+ if ($set->true) { ... }
+
+ # Return false iff $set is always false (i.e. is empty, or contains
+ # only false conditions).
+ if ($set->false) { ... }
+
+ # Return a string representing the DisjConditions.
+ # "COND1_TRUE COND2_FALSE | COND3_FALSE"
+ my $str = $set->string;
+
+ # Return a human readable string representing the DisjConditions.
+ # "(COND1 and !COND2) or (!COND3)"
+ my $str = $set->human;
+
+ # Build a new DisjConditions from the permuation of all
+ # Conditions appearing in $set.
+ my $perm = $set->permutations;
+
+ # Invert a DisjConditions, i.e., create a new DisjConditions
+ # that complements $set.
+ my $inv = $set->invert;
+
+ # Multiply two DisjConditions.
+ my $prod = $set1->multiply ($set2)
+
+ # Return the subconditions of a DisjConditions with respect to
+ # a Condition. See the description for a real example.
+ my $subconds = $set->sub_conditions ($cond)
+
+=head1 DESCRIPTION
+
+A C<DisjConditions> is a disjunction of C<Condition>s. In Automake
+they are used to represent the conditions into which Makefile
+variables and Makefile rules are defined.
+
+If the variable C<VAR> is defined as
+
+ if COND1
+ if COND2
+ VAR = value1
+ endif
+ endif
+ if !COND3
+ if COND4
+ VAR = value2
+ endif
+ endif
+
+then it will be associated a C<DisjConditions> created with
+the following statement.
+
+ new Automake::DisjConditions
+ (new Automake::Condition ("COND1_TRUE", "COND2_TRUE"),
+ new Automake::Condition ("COND3_FALSE", "COND4_TRUE"));
+
+As you can see, a C<DisjConditions> is made from a list of
+C<Condition>s. Since C<DisjConditions> is a disjunction, and
+C<Condition> is a conjunction, the above can be read as
+follows.
+
+ (COND1 and COND2) or ((not COND3) and COND4)
+
+That's indeed the condition into which C<VAR> has a value.
+
+Like C<Condition> objects, a C<DisjConditions> object is unique
+with respect to its conditions. Two C<DisjConditions> objects created
+for the same set of conditions will have the same adress. This makes
+it easy to compare C<DisjConditions>s: just compare the references.
+
+=head2 Methods
+
+=over 4
+
+=item C<$set = new Automake::DisjConditions address@hidden>
+
+Create a C<DisjConditions> object from the list of C<Condition>
+objects passed in arguments.
+
+If the C<@conds> list is empty, the C<DisjConditions> is assumed to be
+false.
+
+As explained previously, the reference (object) returned is unique
+with respect to C<@conds>. For this purpose, duplicate elements are
+ignored.
+
+=cut
+
+# Keys in this hash are DisjConditions strings. Values are the
+# associated object DisjConditions. This is used by `new' to reuse
+# DisjConditions objects with identical conditions.
+use vars '%_disjcondition_singletons';
+
+sub new ($;@)
+{
+ my ($class, @conds) = @_;
+ my $self = {
+ hash => {},
+ };
+ bless $self, $class;
+
+ for my $cond (@conds)
+ {
+ confess "`$cond' isn't a reference" unless ref $cond;
+ confess "`$cond' isn't an Automake::Condition"
+ unless $cond->isa ("Automake::Condition");
+
+ # This is a disjunction of conditions, so we drop
+ # false conditions. We'll always treat an "empty"
+ # DisjConditions as false for this reason.
+ next if $cond->false;
+
+ # Store conditions as keys AND as values, because blessed
+ # objects are converted to string when used as keys (so
+ # at least we still have the value when we need to call
+ # a method).
+ $self->{'hash'}{$cond} = $cond;
+ }
+
+ my $key = $self->string;
+ if (exists $_disjcondition_singletons{$key})
+ {
+ return $_disjcondition_singletons{$key};
+ }
+ $_disjcondition_singletons{$key} = $self;
+ return $self;
+}
+
+=item C<@conds = $set-E<gt>conds>
+
+Return the list of C<Condition> objects involved in C<$set>.
+
+=cut
+
+sub conds ($ )
+{
+ my ($self) = @_;
+ return @{$self->{'conds'}} if exists $self->{'conds'};
+ my @conds = values %{$self->{'hash'}};
+ @conds = sort { $a->string cmp $b->string } @conds;
+ $self->{'conds'} = address@hidden;
+ return @conds;
+}
+
+=item C<$cond = $set-E<gt>one_cond>
+
+Return one C<Condition> object involved in C<$set>.
+
+=cut
+
+sub one_cond ($)
+{
+ my ($self) = @_;
+ return (%{$self->{'hash'}},)[1];
+}
+
+=item C<$et = $set-E<gt>false>
+
+Return 1 iff the C<DisjConditions> object is always false (i.e., if it
+is empty, or if it contains only false C<Condition>s). Return 0
+otherwise.
+
+=cut
+
+sub false ($ )
+{
+ my ($self) = @_;
+ return 0 == keys %{$self->{'hash'}};
+}
+
+=item C<$et = $set-E<gt>true>
+
+Return 1 iff the C<DisjConditions> object is always true (i.e. covers all
+conditions). Return 0 otherwise.
+
+=cut
+
+sub true ($ )
+{
+ my ($self) = @_;
+ # We cache 'true' so that simplify() can use the value if it's available.
+ return $self->{'true'} if defined $self->{'true'};
+ my $res = $self->invert->false;
+ $self->{'true'} = $res;
+ return $res;
+}
+
+=item C<$str = $set-E<gt>string>
+
+Build a string which denotes the C<DisjConditions>.
+
+=cut
+
+sub string ($ )
+{
+ my ($self) = @_;
+
+ return $self->{'string'} if defined $self->{'string'};
+
+ my $res = '';
+ if ($self->false)
+ {
+ $res = 'FALSE';
+ }
+ else
+ {
+ $res = join (' | ', map { $_->string } $self->conds);
+ }
+
+ $self->{'string'} = $res;
+ return $res;
+}
+
+=item C<$cond-E<gt>human>
+
+Build a human readable string which denotes the C<DisjConditions>.
+
+=cut
+
+sub human ($ )
+{
+ my ($self) = @_;
+
+ return $self->{'human'} if defined $self->{'human'};
+
+ my $res = '';
+ if ($self->false)
+ {
+ $res = 'FALSE';
+ }
+ else
+ {
+ my @c = $self->conds;
+ if (1 == @c)
+ {
+ $res = $self->human;
+ }
+ else
+ {
+ $res = '(' . join (') or (', map { $_->human } $self->conds) . ')';
+ }
+ }
+ $self->{'human'} = $res;
+ return $res;
+}
+
+
+sub _permutations_worker (@)
+{
+ my @conds = @_;
+ return () unless @conds;
+
+ my $cond = shift @conds;
+
+ # Ignore "TRUE" conditions, since they add nothing to permutations.
+ return &_permutations_worker (@conds) if $cond eq "TRUE";
+
+ (my $neg = $cond) =~ s/TRUE$/FALSE/;
+
+ # Recurse.
+ my @ret = ();
+ foreach my $c (&_permutations_worker (@conds))
+ {
+ push (@ret, $c->merge_conds ($cond));
+ push (@ret, $c->merge_conds ($neg));
+ }
+ if (! @ret)
+ {
+ push (@ret, new Automake::Condition $cond);
+ push (@ret, new Automake::Condition $neg);
+ }
+
+ return @ret;
+}
+
+=item C<$perm = $set-E<gt>permutations>
+
+Return a permutations of the conditions involved in a C<DisjConditions>.
+
+For instance consider this initial C<DisjConditions>.
+
+ my $set = new Automake::DisjConditions
+ (new Automake::Condition ("COND1_TRUE", "COND2_TRUE"),
+ new Automake::Condition ("COND3_FALSE", "COND2_TRUE"));
+
+Calling C<$set-E<gt>permutations> will return the following DisjConditions.
+
+ new Automake::DisjConditions
+ (new Automake::Condition ("COND1_TRUE", "COND2_TRUE", "COND3_TRUE"),
+ new Automake::Condition ("COND1_FALSE","COND2_TRUE", "COND3_TRUE"),
+ new Automake::Condition ("COND1_TRUE", "COND2_FALSE","COND3_TRUE"),
+ new Automake::Condition ("COND1_FALSE","COND2_FALSE","COND3_TRUE"),
+ new Automake::Condition ("COND1_TRUE", "COND2_TRUE", "COND3_FALSE"),
+ new Automake::Condition ("COND1_FALSE","COND2_TRUE", "COND3_FALSE"),
+ new Automake::Condition ("COND1_TRUE", "COND2_FALSE","COND3_FALSE"),
+ new Automake::Condition ("COND1_FALSE","COND2_FALSE","COND3_FALSE"));
+
+=cut
+
+sub permutations ($ )
+{
+ my ($self) = @_;
+
+ return $self->{'permutations'} if defined $self->{'permutations'};
+
+ my %atomic_conds = ();
+
+ for my $conditional ($self->conds)
+ {
+ for my $cond ($conditional->conds)
+ {
+ $cond =~ s/FALSE$/TRUE/;
+ $atomic_conds{$cond} = 1;
+ }
+ }
+
+ my @res = _permutations_worker (keys %atomic_conds);
+ # An empty permutation is TRUE, because we ignore TRUE conditions
+ # in the recursions.
+ @res = (TRUE) unless @res;
+ my $res = new Automake::DisjConditions @res;
+
+ $self->{'permutations'} = $res;
+
+ return $res;
+}
+
+=item C<$prod = $set1->multiply ($set2)>
+
+Multiply two conditional sets.
+
+ my $set1 = new Automake::DisjConditions
+ (new Automake::Condition ("A_TRUE"),
+ new Automake::Condition ("B_TRUE"));
+ my $set2 = new Automake::DisjConditions
+ (new Automake::Condition ("C_FALSE"),
+ new Automake::Condition ("D_FALSE"));
+
+C<$set1-E<gt>multiply ($set2)> will return
+
+ new Automake::DisjConditions
+ (new Automake::Condition ("A_TRUE", "C_FALSE"),
+ new Automake::Condition ("B_TRUE", "C_FALSE"),;
+ new Automake::Condition ("A_TRUE", "D_FALSE"),
+ new Automake::Condition ("B_TRUE", "D_FALSE"));
+
+The argument can also be a C<Condition>.
+
+=cut
+
+# Same as multiply() but take a list of Conditonals as second argument.
+# We use this in invert().
+sub _multiply ($@)
+{
+ my ($self, @set) = @_;
+ my @res = ();
+ foreach my $selfcond ($self->conds)
+ {
+ foreach my $setcond (@set)
+ {
+ push @res, $selfcond->merge ($setcond);
+ }
+ }
+ return new Automake::DisjConditions @res;
+}
+
+sub multiply ($$)
+{
+ my ($self, $set) = @_;
+ return $self->_multiply ($set) if $set->isa('Automake::Condition');
+ return $self->_multiply ($set->conds);
+}
+
+=item C<$inv = $set-E<gt>invert>
+
+Invert a C<DisjConditions>. Return a C<DisjConditions> which is true
+when C<$set> is false, and vice-versa.
+
+ my $set = new Automake::DisjConditions
+ (new Automake::Condition ("A_TRUE", "B_TRUE"),
+ new Automake::Condition ("A_FALSE", "B_FALSE"));
+
+Calling C<$set-E<gt>invert> will return the following C<DisjConditions>.
+
+ new Automake::DisjConditions
+ (new Automake::Condition ("A_TRUE", "B_FALSE"),
+ new Automake::Condition ("A_FALSE", "B_TRUE"));
+
+=cut
+
+sub invert($ )
+{
+ my ($self) = @_;
+
+ return $self->{'invert'} if defined $self->{'invert'};
+
+ # The invert of an empty DisjConditions is TRUE.
+ my $res = new Automake::DisjConditions TRUE;
+
+ # !((a.b)+(c.d)+(e.f))
+ # = (!a+!b).(!c+!d).(!e+!f)
+ # We develop this into a sum of product iteratively, starting from TRUE:
+ # 1) TRUE
+ # 2) TRUE.!a + TRUE.!b
+ # 3) TRUE.!a.!c + TRUE.!b.!c + TRUE.!a.!d + TRUE.!b.!d
+ # 4) TRUE.!a.!c.!e + TRUE.!b.!c.!e + TRUE.!a.!d.!e + TRUE.!b.!d.!e
+ # + TRUE.!a.!c.!f + TRUE.!b.!c.!f + TRUE.!a.!d.!f + TRUE.!b.!d.!f
+ foreach my $cond ($self->conds)
+ {
+ $res = $res->_multiply ($cond->not);
+ }
+
+ # Cache result.
+ $self->{'invert'} = $res;
+ # It's tempting to also set $res->{'invert'} to $self, but that
+ # is a bad idea as $self hasn't been normalized in any way.
+ # (Different inputs can produce the same inverted set.)
+ return $res;
+}
+
+=item C<$simp = $set->simplify>
+
+Find prime implicants and return a simplified C<DisjConditions>.
+
+=cut
+
+sub _simplify ($) # Based on Quine-McCluskey's algorithm.
+{
+ my ($self) = @_;
+
+ # If we know this DisjConditions is always true, we have nothing to do.
+ # Use the cached value if true if available. Never call true()
+ # as this would call invert() which can be slow.
+ return new Automake::DisjConditions TRUE
+ if $self->{'hash'}{&TRUE} || $self->{'true'};
+
+ my $nvars = 0;
+ my %var_rank;
+ my @rank_var;
+
+ # Initialization.
+ # Translate and-terms into bit string pairs: [$true, $false].
+ #
+ # Each variable is given a bit position in the strings.
+ #
+ # The first string in the pair tells wether a variable is
+ # uncomplemented in the term.
+ # The second string tells whether a variable is complemented.
+ # If a variable does not appear in the term, then its
+ # corresponding bit is unset in both strings.
+
+ # Order the resulting bit string pairs by the number of
+ # variables involved:
+ # @{$subcubes[2]} is the list of string pairs involving two variables.
+ # (Level 0 is used for "TRUE".)
+ my @subcubes;
+ for my $and_conds ($self->conds)
+ {
+ my $true = 0; # Bit string for uncomplemented variables.
+ my $false = 0; # Bit string for complemented variables.
+
+ my @conds = $and_conds->conds;
+ for my $cond (@conds)
+ {
+ # Which variable is this conditional about?
+ confess "can't parse `$cond'"
+ unless $cond =~ /^(.*_)(FALSE|TRUE)$/;
+
+ # Get the variabe's rank, or assign it a new one.
+ my $rank = $var_rank{$1};
+ if (! defined $rank)
+ {
+ $rank = $nvars++;
+
+ # FIXME: simplify() cannot work with more that 31 variables.
+ # We need a bitset implementation to allow more variables.
+ # For now we just return the input, as is, not simplified.
+ return $self if $rank >= 31;
+
+ $var_rank{$1} = $rank;
+ $rank_var[$rank] = $1;
+ }
+
+ # Fire the relevant bit in the strings.
+ if ($2 eq 'FALSE')
+ {
+ $false |= 1 << $rank;
+ }
+ else
+ {
+ $true |= 1 << $rank;
+ }
+ }
+
+ # Register this term.
+ push @{$subcubes[1 + $#conds]}, [$true, $false];
+ }
+
+ # Real work. Let's combine terms.
+
+ # Process terms in diminishing size order. Those
+ # involving the maximum number of variables first.
+ for (my $m = $#subcubes; $m > 0; --$m)
+ {
+ my $m_subcubes = $#{$subcubes[$m]};
+
+ # Consider all terms with $m variables.
+ for (my $j = 0; $j <= $m_subcubes; ++$j)
+ {
+ my $tj = $subcubes[$m][$j];
+ my $jtrue = $tj->[0];
+ my $jfalse = $tj->[1];
+
+ # Compare them with all other terms with $m variables.
+ COMBINATION:
+ for (my $k = $j + 1; $k <= $m_subcubes; ++$k)
+ {
+ my $tk = $subcubes[$m][$k];
+ my $ktrue = $tk->[0];
+ my $kfalse = $tk->[1];
+
+ # Two terms can combine if they differ only by one variable
+ # (i.e., a bit here), which is complemented in one term
+ # and uncomplemented in the other.
+ my $true = $jtrue ^ $ktrue;
+ my $false = $jfalse ^ $kfalse;
+ next COMBINATION if $true != $false;
+ # There should be exactly one bit set.
+ # (`$true & ($true - 1)' unsets the rightmost 1 bit in $true.)
+ next COMBINATION if $true == 0 || $true & ($true - 1);
+
+ # At this point we know we can combine the two terms.
+
+ # Mark these two terms as "combined", so they will be
+ # deleted after we have processed all other combinations.
+ $tj->[2] = 1;
+ $tk->[2] = 1;
+
+ # Actually combine the two terms.
+ my $ctrue = $jtrue & $ktrue;
+ my $cfalse = $jfalse & $kfalse;
+
+ # Don't add the combined term if it already exists.
+ DUP_SEARCH:
+ for my $c (@{$subcubes[$m - 1]})
+ {
+ next DUP_SEARCH if $ctrue != $c->[0];
+ next COMBINATION if $cfalse == $c->[1];
+ }
+ push @{$subcubes[$m - 1]}, [$ctrue, $cfalse];
+ }
+ }
+
+ # Delete all covered terms.
+ for (my $j = 0; $j <= $m_subcubes; ++$j)
+ {
+ delete $subcubes[$m][$j] if $subcubes[$m][$j][2];
+ }
+ }
+
+ # Finally merge bit strings back into a Automake::DisjConditions.
+
+ # If level 0 has been filled, we've found `TRUE'. No need to translate
+ # anything.
+ return new Automake::DisjConditions TRUE if $#{$subcubes[0]} >= 0;
+
+ # Otherwise, translate uncombined terms in other levels.
+
+ my @or_conds = ();
+ # Process terms in diminishing size order. Those
+ # involving the maximum number of variables first.
+ for (my $m = 1; $m <= $#subcubes; ++$m)
+ {
+ my $m_subcubes = $#{$subcubes[$m]};
+ # Consider all terms with $m variables.
+ for (my $j = 0; $j <= $m_subcubes; ++$j)
+ {
+ my $tj = $subcubes[$m][$j];
+ next unless $tj; # Skip deleted terms.
+ my $jtrue = $tj->[0];
+ my $jfalse = $tj->[1];
+
+ # Filter-out implied terms.
+ #
+ # An and-term at level N might cover and-terms at level M>N.
+ # We need to mark all these covered terms so that they are
+ # not output in the result formula.
+ #
+ # If $tj was generated by combining two terms at level N+1,
+ # there two terms are already marked. However there might be
+ # implied terms deeper.
+ #
+ # For instance consider this input: "A_TRUE | A_TRUE C_FALSE".
+ #
+ # This can also occur with and-term generated by the
+ # combining algorith. E.g., consider
+ # "A_TRUE B_TRUE" | "A_TRUE B_FALSE" | "A_TRUE C_FALSE D_FALSE"
+ # - at level 3 we can't combine "A_TRUE C_FALSE D_FALSE"
+ # - at level 2 we can combine "A_TRUE B_TRUE" | "A_TRUE B_FALSE"
+ # into "A_TRUE
+ # - at level 1 we an't combine "A_TRUE"
+ # so without more simplification we would output
+ # "A_TRUE | A_TRUE C_FALSE D_FALSE"
+ #
+ # So let's filter-out and-terms which are implied by other
+ # and-terms. An and-term $tk is implied by an and-term $tj if $k
+ # involves more variables than $tj (i.e., N>M) and if
+ # all variables occurring in $tk also occur in A in the
+ # same state (complemented or uncomplemented.)
+ for (my $n = $m + 1; $n <= $#subcubes; ++$n)
+ {
+ my $n_subcubes = $#{$subcubes[$n]};
+ for (my $k = 0; $k <= $n_subcubes; ++$k)
+ {
+ my $tk = $subcubes[$n][$k];
+ next unless $tk; # Skip deleted terms.
+ my $ktrue = $tk->[0];
+ my $kfalse = $tk->[1];
+
+ next unless $ktrue == ($ktrue | $jtrue);
+ next unless $kfalse == ($kfalse | $jfalse);
+
+ delete $subcubes[$n][$k];
+ }
+ }
+
+ # Translate $tj.
+ my @and_conds = ();
+ my $rank = 0;
+ while ($jtrue > 0)
+ {
+ if ($jtrue & 1)
+ {
+ push @and_conds, $rank_var[$rank] . 'TRUE';
+ }
+ $jtrue >>= 1;
+ ++$rank;
+ }
+ $rank = 0;
+ while ($jfalse > 0)
+ {
+ if ($jfalse & 1)
+ {
+ push @and_conds, $rank_var[$rank] . 'FALSE';
+ }
+ $jfalse >>= 1;
+ ++$rank;
+ }
+
+ push @or_conds, new Automake::Condition @and_conds if @and_conds;
+ }
+ }
+
+ return new Automake::DisjConditions @or_conds;
+}
+
+sub simplify ($)
+{
+ my ($self) = @_;
+ return $self->{'simplify'} if defined $self->{'simplify'};
+ my $res = $self->_simplify ;
+ $self->{'simplify'} = $res;
+ return $res;
+}
+
+=item C<$self-E<gt>sub_conditions ($cond)>
+
+Return the subconditions of C<$self> that contains C<$cond>, with
+C<$cond> stripped.
+
+For instance, consider:
+
+ my $a = new Automake::DisjConditions
+ (new Automake::Condition ("A_TRUE", "B_TRUE"),
+ new Automake::Condition ("A_TRUE", "C_FALSE"),
+ new Automake::Condition ("A_TRUE", "B_FALSE", "C_TRUE"),
+ new Automake::Condition ("A_FALSE"));
+ my $b = new Automake::DisjConditions
+ (new Automake::Condition ("A_TRUE", "B_FALSE"));
+
+Calling C<$a-E<gt>sub_conditions ($b)> will return the following
+C<DisjConditions>.
+
+ new Automake::DisjConditions
+ (new Automake::Condition ("C_FALSE"), # From A_TRUE C_FALSE
+ new Automake::Condition ("C_TRUE")); # From A_TRUE B_FALSE C_TRUE"
+
+=cut
+
+sub sub_conditions ($$)
+{
+ my ($self, $subcond) = @_;
+
+ # Make $subcond blindingly apparent in the DisjConditions.
+ # For instance `$a->_multiply($b)' (from the POD example) is:
+ # new Automake::DisjConditions
+ # (new Automake::Condition ("FALSE"),
+ # new Automake::Condition ("A_TRUE", "B_FALSE", "C_FALSE"),
+ # new Automake::Condition ("A_TRUE", "B_FALSE", "C_TRUE"),
+ # new Automake::Condition ("FALSE"));
+ my $prod = $self->_multiply ($subcond);
+
+ # Now, strip $subcond from the remaining (i.e., non-false) Conditions.
+ my @res;
+ foreach my $c ($prod->conds)
+ {
+ push @res, $c->strip ($subcond) unless $c->false;
+ }
+ return new Automake::DisjConditions @res;
+}
+
+=head1 SEE ALSO
+
+L<Automake::Condition>.
+
+=head1 HISTORY
+
+C<AM_CONDITIONAL>s and supporting code were added to Automake 1.1o by
+Ian Lance Taylor <address@hidden> in 1997. Since then it has been
+improved by Tom Tromey <address@hidden>, Richard Boulton
+<address@hidden>, Raja R Harinath <address@hidden>, Akim
+Demaille <address@hidden>, Pavel Roskin <address@hidden>, and
+Alexandre Duret-Lutz <address@hidden>.
+
+=cut
+
+1;
+
+### Setup "GNU" style for perl-mode and cperl-mode.
+## Local Variables:
+## perl-indent-level: 2
+## perl-continued-statement-offset: 2
+## perl-continued-brace-offset: 0
+## perl-brace-offset: 0
+## perl-brace-imaginary-offset: 0
+## perl-label-offset: -2
+## cperl-indent-level: 2
+## cperl-brace-offset: 0
+## cperl-continued-brace-offset: 0
+## cperl-label-offset: -2
+## cperl-extra-newline-before-brace: t
+## cperl-merge-trailing-else: nil
+## cperl-continued-statement-offset: 2
+## End:
Index: lib/Automake/Makefile.am
===================================================================
RCS file: /cvs/automake/automake/lib/Automake/Makefile.am,v
retrieving revision 1.9
diff -u -r1.9 Makefile.am
--- lib/Automake/Makefile.am 31 Dec 2002 21:31:51 -0000 1.9
+++ lib/Automake/Makefile.am 19 Jan 2003 22:53:20 -0000
@@ -1,13 +1,30 @@
## Process this file with automake to create Makefile.in
+## Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc.
+
+## This program is free software; you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 2, or (at your option)
+## any later version.
+
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+## GNU General Public License for more details.
+
+## You should have received a copy of the GNU General Public License
+## along with this program; if not, write to the Free Software
+## Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+## 02111-1307, USA.
+
SUBDIRS = tests
perllibdir = $(pkgvdatadir)/Automake
dist_perllib_DATA = \
ChannelDefs.pm \
Channels.pm \
- Conditional.pm \
- ConditionalSet.pm \
+ Condition.pm \
+ DisjConditions.pm \
General.pm \
Location.pm \
Struct.pm \
Index: lib/Automake/Makefile.in
===================================================================
RCS file: /cvs/automake/automake/lib/Automake/Makefile.in,v
retrieving revision 1.57
diff -u -r1.57 Makefile.in
--- lib/Automake/Makefile.in 9 Jan 2003 12:43:36 -0000 1.57
+++ lib/Automake/Makefile.in 19 Jan 2003 22:53:22 -0000
@@ -99,8 +99,8 @@
dist_perllib_DATA = \
ChannelDefs.pm \
Channels.pm \
- Conditional.pm \
- ConditionalSet.pm \
+ Condition.pm \
+ DisjConditions.pm \
General.pm \
Location.pm \
Struct.pm \
Index: lib/Automake/tests/Condition.pl
===================================================================
RCS file: lib/Automake/tests/Condition.pl
diff -N lib/Automake/tests/Condition.pl
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ lib/Automake/tests/Condition.pl 19 Jan 2003 22:53:22 -0000
@@ -0,0 +1,184 @@
+# Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc.
+#
+# This file is part of GNU Automake.
+#
+# GNU Automake is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#
+# GNU Automake is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with autoconf; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+
+use Automake::Condition qw/TRUE FALSE/;
+
+sub test_basics ()
+{
+ my @tests = (# [[Conditions], is_true?, is_false?, string, subst-string]
+ [[], 1, 0, 'TRUE', ''],
+ [['TRUE'], 1, 0, 'TRUE', ''],
+ [['FALSE'], 0, 1, 'FALSE', '#'],
+ [['A_TRUE'], 0, 0, 'A_TRUE', '@A_TRUE@'],
+ [['A_TRUE', 'B_FALSE'],
+ 0, 0, 'A_TRUE B_FALSE', '@A_TRUE@@B_FALSE@'],
+ [['B_TRUE', 'FALSE'], 0, 1, 'FALSE', '#'],
+ [['B_TRUE', 'B_FALSE'], 0, 1, 'FALSE', '#']);
+
+ for (@tests)
+ {
+ my $a = new Automake::Condition @{$_->[0]};
+ return 1 if $_->[1] != $a->true;
+ return 1 if $_->[1] != ($a == TRUE);
+ return 1 if $_->[2] != $a->false;
+ return 1 if $_->[2] != ($a == FALSE);
+ return 1 if $_->[3] ne $a->string;
+ return 1 if $_->[4] ne $a->subst_string;
+ }
+ return 0;
+}
+
+sub test_true_when ()
+{
+ my $failed = 0;
+
+ my @tests = (# [When,
+ # [Implied-Conditions],
+ # [Not-Implied-Conditions]]
+ [['TRUE'],
+ [['TRUE']],
+ [['A_TRUE'], ['A_TRUE', 'B_FALSE'], ['FALSE']]],
+ [['A_TRUE'],
+ [['TRUE'], ['A_TRUE']],
+ [['A_TRUE', 'B_FALSE'], ['FALSE']]],
+ [['A_TRUE', 'B_FALSE'],
+ [['TRUE'], ['A_TRUE'], ['B_FALSE'], ['A_TRUE', 'B_FALSE']],
+ [['FALSE'], ['C_FALSE'], ['C_FALSE', 'A_TRUE']]]);
+
+ for my $t (@tests)
+ {
+ my $a = new Automake::Condition @{$t->[0]};
+ for my $u (@{$t->[1]})
+ {
+ my $b = new Automake::Condition @$u;
+ if (! $b->true_when ($a))
+ {
+ print "`" . $b->string .
+ "' not implied by `" . $a->string . "'?\n";
+ $failed = 1;
+ }
+ }
+ for my $u (@{$t->[2]})
+ {
+ my $b = new Automake::Condition @$u;
+ if ($b->true_when ($a))
+ {
+ print "`" . $b->string .
+ "' implied by `" . $a->string . "'?\n";
+ $failed = 1;
+ }
+
+ return 1 if $b->true_when ($a);
+ }
+ }
+ return $failed;
+}
+
+sub test_reduce ()
+{
+ my @tests = (# If no conditions are given, TRUE should be returned
+ [[""], ["TRUE"]],
+ # A single condition should be passed through unchanged
+ [["FOO"], ["FOO"]],
+ [["FALSE"], ["FALSE"]],
+ [["TRUE"], ["TRUE"]],
+ # TRUE and false should be discarded and overwhelm
+ # the result, respectively
+ [["FOO", "TRUE"], ["FOO"]],
+ [["FOO", "FALSE"], ["FALSE"]],
+ # Repetitions should be removed
+ [["FOO", "FOO"], ["FOO"]],
+ [["TRUE", "FOO", "FOO"], ["FOO"]],
+ [["FOO", "TRUE", "FOO"], ["FOO"]],
+ [["FOO", "FOO", "TRUE"], ["FOO"]],
+ # Two different conditions should be preserved,
+ # but TRUEs should be removed
+ [["FOO", "BAR"], ["BAR,FOO"]],
+ [["TRUE", "FOO", "BAR"], ["BAR,FOO"]],
+ [["FOO", "TRUE", "BAR"], ["BAR,FOO"]],
+ [["FOO", "BAR", "TRUE"], ["BAR,FOO"]],
+ # A condition implied by another condition should be removed.
+ [["FOO BAR", "BAR"], ["FOO BAR"]],
+ [["BAR", "FOO BAR"], ["FOO BAR"]],
+ [["TRUE", "FOO BAR", "BAR"], ["FOO BAR"]],
+ [["FOO BAR", "TRUE", "BAR"], ["FOO BAR"]],
+ [["FOO BAR", "BAR", "TRUE"], ["FOO BAR"]],
+
+ [["BAR FOO", "BAR"], ["BAR FOO"]],
+ [["BAR", "BAR FOO"], ["BAR FOO"]],
+ [["TRUE", "BAR FOO", "BAR"], ["BAR FOO"]],
+ [["BAR FOO", "TRUE", "BAR"], ["BAR FOO"]],
+ [["BAR FOO", "BAR", "TRUE"], ["BAR FOO"]],
+
+ # Check that reduction happens even when there are
+ # two conditions to remove.
+ [["FOO", "FOO BAR", "BAR"], ["FOO BAR"]],
+ [["FOO", "FOO BAR", "BAZ", "FOO BAZ"], ["FOO BAR", "FOO BAZ"]],
+ [["FOO", "FOO BAR", "BAZ", "FOO BAZ", "FOO BAZ BAR"],
+ ["FOO BAZ BAR"]],
+
+ # Duplicated condionals should be removed
+ [["FOO", "BAR", "BAR"], ["BAR,FOO"]],
+
+ # Equivalent conditions in different forms should be
+ # reduced: which one is left is unfortunately order
+ # dependent.
+ [["BAR FOO", "FOO BAR"], ["FOO BAR"]],
+ [["FOO BAR", "BAR FOO"], ["BAR FOO"]]);
+
+ my $failed = 0;
+ foreach (@tests)
+ {
+ my ($inref, $outref) = @$_;
+ my @inconds = map { new Automake::Condition $_ } @$inref;
+ my @outconds = map { (new Automake::Condition $_)->string } @$outref;
+ my @res =
+ map { $_->string } (Automake::Condition::reduce (@inconds));
+ my $result = join (",", sort @res);
+ my $exresult = join (",", @outconds);
+
+ if ($result ne $exresult)
+ {
+ print '"'.join(",", @$inref) . '" => "' .
+ $result . '" expected "' .
+ $exresult . '"' . "\n";
+ $failed = 1;
+ }
+ }
+ return $failed;
+}
+
+exit (test_basics || test_true_when || test_reduce);
+
+### Setup "GNU" style for perl-mode and cperl-mode.
+## Local Variables:
+## perl-indent-level: 2
+## perl-continued-statement-offset: 2
+## perl-continued-brace-offset: 0
+## perl-brace-offset: 0
+## perl-brace-imaginary-offset: 0
+## perl-label-offset: -2
+## cperl-indent-level: 2
+## cperl-brace-offset: 0
+## cperl-continued-brace-offset: 0
+## cperl-label-offset: -2
+## cperl-extra-newline-before-brace: t
+## cperl-merge-trailing-else: nil
+## cperl-continued-statement-offset: 2
+## End:
Index: lib/Automake/tests/Conditional.pl
===================================================================
RCS file: lib/Automake/tests/Conditional.pl
diff -N lib/Automake/tests/Conditional.pl
--- lib/Automake/tests/Conditional.pl 18 Nov 2002 18:43:27 -0000 1.1
+++ /dev/null 1 Jan 1970 00:00:00 -0000
@@ -1,184 +0,0 @@
-# Copyright (C) 2001, 2002 Free Software Foundation, Inc.
-#
-# This file is part of GNU Automake.
-#
-# GNU Automake is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2, or (at your option)
-# any later version.
-#
-# GNU Automake is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with autoconf; see the file COPYING. If not, write to
-# the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-# Boston, MA 02111-1307, USA.
-
-use Automake::Conditional qw/TRUE FALSE/;
-
-sub test_basics ()
-{
- my @tests = (# [[Conditions], is_true?, is_false?, string, subst-string]
- [[], 1, 0, 'TRUE', ''],
- [['TRUE'], 1, 0, 'TRUE', ''],
- [['FALSE'], 0, 1, 'FALSE', '#'],
- [['A_TRUE'], 0, 0, 'A_TRUE', '@A_TRUE@'],
- [['A_TRUE', 'B_FALSE'],
- 0, 0, 'A_TRUE B_FALSE', '@A_TRUE@@B_FALSE@'],
- [['B_TRUE', 'FALSE'], 0, 1, 'FALSE', '#'],
- [['B_TRUE', 'B_FALSE'], 0, 1, 'FALSE', '#']);
-
- for (@tests)
- {
- my $a = new Automake::Conditional @{$_->[0]};
- return 1 if $_->[1] != $a->true;
- return 1 if $_->[1] != ($a == TRUE);
- return 1 if $_->[2] != $a->false;
- return 1 if $_->[2] != ($a == FALSE);
- return 1 if $_->[3] ne $a->string;
- return 1 if $_->[4] ne $a->subst_string;
- }
- return 0;
-}
-
-sub test_true_when ()
-{
- my $failed = 0;
-
- my @tests = (# [When,
- # [Implied-Conditionals],
- # [Not-Implied-Conditionals]]
- [['TRUE'],
- [['TRUE']],
- [['A_TRUE'], ['A_TRUE', 'B_FALSE'], ['FALSE']]],
- [['A_TRUE'],
- [['TRUE'], ['A_TRUE']],
- [['A_TRUE', 'B_FALSE'], ['FALSE']]],
- [['A_TRUE', 'B_FALSE'],
- [['TRUE'], ['A_TRUE'], ['B_FALSE'], ['A_TRUE', 'B_FALSE']],
- [['FALSE'], ['C_FALSE'], ['C_FALSE', 'A_TRUE']]]);
-
- for my $t (@tests)
- {
- my $a = new Automake::Conditional @{$t->[0]};
- for my $u (@{$t->[1]})
- {
- my $b = new Automake::Conditional @$u;
- if (! $b->true_when ($a))
- {
- print "`" . $b->string .
- "' not implied by `" . $a->string . "'?\n";
- $failed = 1;
- }
- }
- for my $u (@{$t->[2]})
- {
- my $b = new Automake::Conditional @$u;
- if ($b->true_when ($a))
- {
- print "`" . $b->string .
- "' implied by `" . $a->string . "'?\n";
- $failed = 1;
- }
-
- return 1 if $b->true_when ($a);
- }
- }
- return $failed;
-}
-
-sub test_reduce ()
-{
- my @tests = (# If no conditions are given, TRUE should be returned
- [[""], ["TRUE"]],
- # A single condition should be passed through unchanged
- [["FOO"], ["FOO"]],
- [["FALSE"], ["FALSE"]],
- [["TRUE"], ["TRUE"]],
- # TRUE and false should be discarded and overwhelm
- # the result, respectively
- [["FOO", "TRUE"], ["FOO"]],
- [["FOO", "FALSE"], ["FALSE"]],
- # Repetitions should be removed
- [["FOO", "FOO"], ["FOO"]],
- [["TRUE", "FOO", "FOO"], ["FOO"]],
- [["FOO", "TRUE", "FOO"], ["FOO"]],
- [["FOO", "FOO", "TRUE"], ["FOO"]],
- # Two different conditions should be preserved,
- # but TRUEs should be removed
- [["FOO", "BAR"], ["BAR,FOO"]],
- [["TRUE", "FOO", "BAR"], ["BAR,FOO"]],
- [["FOO", "TRUE", "BAR"], ["BAR,FOO"]],
- [["FOO", "BAR", "TRUE"], ["BAR,FOO"]],
- # A condition implied by another condition should be removed.
- [["FOO BAR", "BAR"], ["FOO BAR"]],
- [["BAR", "FOO BAR"], ["FOO BAR"]],
- [["TRUE", "FOO BAR", "BAR"], ["FOO BAR"]],
- [["FOO BAR", "TRUE", "BAR"], ["FOO BAR"]],
- [["FOO BAR", "BAR", "TRUE"], ["FOO BAR"]],
-
- [["BAR FOO", "BAR"], ["BAR FOO"]],
- [["BAR", "BAR FOO"], ["BAR FOO"]],
- [["TRUE", "BAR FOO", "BAR"], ["BAR FOO"]],
- [["BAR FOO", "TRUE", "BAR"], ["BAR FOO"]],
- [["BAR FOO", "BAR", "TRUE"], ["BAR FOO"]],
-
- # Check that reduction happens even when there are
- # two conditionals to remove.
- [["FOO", "FOO BAR", "BAR"], ["FOO BAR"]],
- [["FOO", "FOO BAR", "BAZ", "FOO BAZ"], ["FOO BAR", "FOO BAZ"]],
- [["FOO", "FOO BAR", "BAZ", "FOO BAZ", "FOO BAZ BAR"],
- ["FOO BAZ BAR"]],
-
- # Duplicated condionals should be removed
- [["FOO", "BAR", "BAR"], ["BAR,FOO"]],
-
- # Equivalent conditionals in different forms should be
- # reduced: which one is left is unfortunately order
- # dependent.
- [["BAR FOO", "FOO BAR"], ["FOO BAR"]],
- [["FOO BAR", "BAR FOO"], ["BAR FOO"]]);
-
- my $failed = 0;
- foreach (@tests)
- {
- my ($inref, $outref) = @$_;
- my @inconds = map { new Automake::Conditional $_ } @$inref;
- my @outconds = map { (new Automake::Conditional $_)->string } @$outref;
- my @res =
- map { $_->string } (Automake::Conditional::reduce (@inconds));
- my $result = join (",", sort @res);
- my $exresult = join (",", @outconds);
-
- if ($result ne $exresult)
- {
- print '"'.join(",", @$inref) . '" => "' .
- $result . '" expected "' .
- $exresult . '"' . "\n";
- $failed = 1;
- }
- }
- return $failed;
-}
-
-exit (test_basics || test_true_when || test_reduce);
-
-### Setup "GNU" style for perl-mode and cperl-mode.
-## Local Variables:
-## perl-indent-level: 2
-## perl-continued-statement-offset: 2
-## perl-continued-brace-offset: 0
-## perl-brace-offset: 0
-## perl-brace-imaginary-offset: 0
-## perl-label-offset: -2
-## cperl-indent-level: 2
-## cperl-brace-offset: 0
-## cperl-continued-brace-offset: 0
-## cperl-label-offset: -2
-## cperl-extra-newline-before-brace: t
-## cperl-merge-trailing-else: nil
-## cperl-continued-statement-offset: 2
-## End:
Index: lib/Automake/tests/ConditionalSet.pl
===================================================================
RCS file: lib/Automake/tests/ConditionalSet.pl
diff -N lib/Automake/tests/ConditionalSet.pl
--- lib/Automake/tests/ConditionalSet.pl 20 Nov 2002 20:12:50 -0000
1.4
+++ /dev/null 1 Jan 1970 00:00:00 -0000
@@ -1,404 +0,0 @@
-# Copyright (C) 2001, 2002 Free Software Foundation, Inc.
-#
-# This file is part of GNU Automake.
-#
-# GNU Automake is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2, or (at your option)
-# any later version.
-#
-# GNU Automake is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with autoconf; see the file COPYING. If not, write to
-# the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-# Boston, MA 02111-1307, USA.
-
-use Automake::Conditional qw/TRUE FALSE/;
-use Automake::ConditionalSet;
-
-sub test_basics ()
-{
- my $cond = new Automake::Conditional "COND1_TRUE", "COND2_FALSE";
- my $other = new Automake::Conditional "COND3_FALSE";
- my $set1 = new Automake::ConditionalSet $cond, $other;
- my $set2 = new Automake::ConditionalSet $other, $cond;
- return 1 unless $set1 == $set2;
- return 1 if $set1->false;
- return 1 if $set1->true;
- return 1 unless (new Automake::ConditionalSet)->false;
- return 1 if (new Automake::ConditionalSet)->true;
-}
-
-sub build_set (@)
-{
- my @conds = @_;
- my @set = ();
- for my $cond (@conds)
- {
- push @set, new Automake::Conditional @$cond;
- }
- return new Automake::ConditionalSet @set;
-}
-
-sub test_permutations ()
-{
- my @tests = ([[["FALSE"]],
- [["TRUE"]]],
-
- [[["TRUE"]],
- [["TRUE"]]],
-
- [[["COND1_TRUE", "COND2_TRUE"],
- ["COND3_FALSE", "COND2_TRUE"]],
- [["COND1_FALSE","COND2_FALSE","COND3_FALSE"],
- ["COND1_TRUE", "COND2_FALSE","COND3_FALSE"],
- ["COND1_FALSE","COND2_TRUE", "COND3_FALSE"],
- ["COND1_TRUE", "COND2_TRUE", "COND3_FALSE"],
- ["COND1_FALSE","COND2_FALSE","COND3_TRUE"],
- ["COND1_TRUE", "COND2_FALSE","COND3_TRUE"],
- ["COND1_FALSE","COND2_TRUE", "COND3_TRUE"],
- ["COND1_TRUE", "COND2_TRUE", "COND3_TRUE"]]],
-
- [[["COND1_TRUE", "COND2_TRUE"],
- ["TRUE"]],
- [["COND1_TRUE", "COND2_TRUE"],
- ["COND1_FALSE", "COND2_TRUE"],
- ["COND1_FALSE", "COND2_FALSE"],
- ["COND1_TRUE", "COND2_FALSE"]]],
-
- [[["COND1_TRUE", "COND2_TRUE"],
- ["FALSE"]],
- [["COND1_TRUE", "COND2_TRUE"],
- ["COND1_FALSE", "COND2_TRUE"],
- ["COND1_FALSE", "COND2_FALSE"],
- ["COND1_TRUE", "COND2_FALSE"]]],
-
- [[["COND1_TRUE"],
- ["COND2_FALSE"]],
- [["COND1_TRUE", "COND2_TRUE"],
- ["COND1_FALSE", "COND2_TRUE"],
- ["COND1_FALSE", "COND2_FALSE"],
- ["COND1_TRUE", "COND2_FALSE"]]]
- );
-
- for my $t (@tests)
- {
- my $set = build_set @{$t->[0]};
- my $res = build_set @{$t->[1]};
- my $per = $set->permutations;
- if ($per != $res)
- {
- print " (P) " . $per->string . ' != ' . $res->string . "\n";
- return 1;
- }
- }
- return 0;
-}
-
-sub test_invert ()
-{
- my @tests = ([[["FALSE"]],
- [["TRUE"]]],
-
- [[["TRUE"]],
- [["FALSE"]]],
-
- [[["COND1_TRUE", "COND2_TRUE"],
- ["COND3_FALSE", "COND2_TRUE"]],
- [["COND2_FALSE"],
- ["COND2_FALSE", "COND3_TRUE"],
- ["COND1_FALSE", "COND2_FALSE"],
- ["COND1_FALSE", "COND3_TRUE"]]],
-
- [[["COND1_TRUE", "COND2_TRUE"],
- ["TRUE"]],
- [["FALSE"]]],
-
- [[["COND1_TRUE", "COND2_TRUE"],
- ["FALSE"]],
- [["COND1_FALSE"],
- ["COND2_FALSE"]]],
-
- [[["COND1_TRUE"],
- ["COND2_FALSE"]],
- [["COND1_FALSE", "COND2_TRUE"]]]
- );
-
- for my $t (@tests)
- {
- my $set = build_set @{$t->[0]};
- my $res = build_set @{$t->[1]};
- my $inv = $set->invert;
- if ($inv != $res)
- {
- print " (I) " . $set->string . "\n\t"
- . $inv->string . ' != ' . $res->string . "\n";
- return 1;
- }
- }
- return 0;
-}
-
-sub test_simplify ()
-{
- my @tests = ([[["FOO_TRUE", "BAR_FALSE", "BAZ_FALSE"],
- ["FOO_TRUE", "BAR_FALSE", "BAZ_TRUE"]],
- [["FOO_TRUE", "BAR_FALSE"]]],
-
- [[["FOO_TRUE", "BAR_FALSE", "BAZ_FALSE"],
- ["FOO_TRUE", "BAR_FALSE", "BAZ_TRUE"],
- ["FOO_TRUE", "BAR_TRUE"]],
- [["FOO_TRUE"]]],
-
- [[["FOO_TRUE", "BAR_FALSE", "BAZ_FALSE"],
- ["FOO_TRUE", "BAR_FALSE", "BAZ_TRUE"],
- ["FOO_TRUE", "BAR_TRUE"],
- ["FOO_FALSE"]],
- [["TRUE"]]],
-
- [[["FOO_TRUE", "BAR_FALSE", "BAZ_FALSE"],
- ["FOO_TRUE", "BAR_FALSE", "BAZ_TRUE"],
- ["BAR_TRUE", "BAZ_TRUE"],
- ["BAR_FALSE", "BAZ_TRUE"]],
- [["BAZ_TRUE"], ["FOO_TRUE", "BAR_FALSE"]]],
-
- [[["FOO_TRUE", "BAR_FALSE", "BAZ_FALSE"],
- ["FOO_TRUE", "BAR_FALSE", "BAZ_TRUE"],
- ["BAR_TRUE", "BAZ_TRUE"],
- ["BAR_FALSE", "BAZ_TRUE"],
- ["FOO_FALSE"]],
- # Note that this could be further simplified to
- # [["FOO_FALSE"], ["BAZ_TRUE"], ["BAR_FALSE"]]
- # but simplify isn't able to detect this.
- [["FOO_FALSE"], ["BAZ_TRUE"], ["BAR_FALSE", "FOO_TRUE"]]],
-
- [[["B_TRUE"],
- ["A_FALSE", "B_TRUE"]],
- [["B_TRUE"]]],
-
- [[["B_TRUE"],
- ["A_FALSE", "B_FALSE", "C_TRUE"],
- ["A_FALSE", "B_FALSE", "C_FALSE"]],
- # Note that this could be further simplified to
- # [["A_FALSE"], ["B_TRUE"]]
- # but simplify isn't able to detect this.
- [["A_FALSE", "B_FALSE"], ["B_TRUE"]]],
-
- [[["B_TRUE"],
- ["A_FALSE", "B_FALSE", "C_TRUE"],
- ["A_FALSE", "B_FALSE", "C_FALSE"],
- ["A_TRUE", "B_FALSE"]],
- [["TRUE"]]],
-
- [[["A_TRUE", "B_TRUE"],
- ["A_TRUE", "B_FALSE"],
- ["A_TRUE", "C_FALSE", "D_FALSE"]],
- [["A_TRUE"]]],
-
- [[["A_FALSE", "B_FALSE", "C_FALSE", "D_TRUE", "E_FALSE"],
- ["A_FALSE", "B_FALSE", "C_TRUE", "D_TRUE", "E_TRUE"],
- ["A_FALSE", "B_TRUE", "C_TRUE", "D_FALSE", "E_TRUE"],
- ["A_FALSE", "B_TRUE", "C_FALSE", "D_FALSE", "E_FALSE"],
- ["A_TRUE", "B_TRUE", "C_FALSE", "D_FALSE", "E_FALSE"],
- ["A_TRUE", "B_TRUE", "C_TRUE", "D_FALSE", "E_TRUE"],
- ["A_TRUE", "B_FALSE", "C_TRUE", "D_TRUE", "E_TRUE"],
- ["A_TRUE", "B_FALSE", "C_FALSE", "D_TRUE", "E_FALSE"]],
- [ ["B_FALSE", "C_FALSE", "D_TRUE", "E_FALSE"],
- ["B_FALSE", "C_TRUE", "D_TRUE", "E_TRUE"],
- ["B_TRUE", "C_TRUE", "D_FALSE", "E_TRUE"],
- ["B_TRUE", "C_FALSE", "D_FALSE", "E_FALSE"]]],
-
- [[["A_FALSE", "B_FALSE", "C_FALSE", "D_TRUE", "E_FALSE"],
- ["A_FALSE", "B_FALSE", "C_TRUE", "D_TRUE", "E_TRUE"],
- ["A_FALSE", "B_TRUE", "C_TRUE", "D_FALSE", "E_TRUE"],
- ["A_FALSE", "B_TRUE", "C_FALSE", "D_FALSE", "E_FALSE"],
- ["A_TRUE", "B_TRUE", "C_FALSE", "D_FALSE", "E_FALSE"],
- ["A_TRUE", "B_TRUE", "C_TRUE", "D_FALSE", "E_TRUE"],
- ["A_TRUE", "B_FALSE", "C_TRUE", "D_TRUE", "E_TRUE"],
- ["A_TRUE", "B_FALSE", "C_FALSE", "D_TRUE", "E_FALSE"],
- ["A_FALSE", "B_FALSE", "C_FALSE", "D_FALSE", "E_FALSE"],
- ["A_FALSE", "B_FALSE", "C_TRUE", "D_FALSE", "E_TRUE"],
- ["A_FALSE", "B_TRUE", "C_TRUE", "D_TRUE", "E_TRUE"],
- ["A_FALSE", "B_TRUE", "C_FALSE", "D_TRUE", "E_FALSE"],
- ["A_TRUE", "B_TRUE", "C_FALSE", "D_TRUE", "E_FALSE"],
- ["A_TRUE", "B_TRUE", "C_TRUE", "D_TRUE", "E_TRUE"],
- ["A_TRUE", "B_FALSE", "C_TRUE", "D_FALSE", "E_TRUE"],
- ["A_TRUE", "B_FALSE", "C_FALSE", "D_FALSE", "E_FALSE"]],
- [["C_FALSE", "E_FALSE"],
- ["C_TRUE", "E_TRUE"]]],
-
- [[["A_FALSE"],
- ["A_TRUE", "B_FALSE"],
- ["A_TRUE", "B_TRUE", "C_FALSE"],
- ["A_TRUE", "B_TRUE", "C_TRUE", "D_FALSE"],
- ["A_TRUE", "B_TRUE", "C_TRUE", "D_TRUE", "E_FALSE"],
- ["A_TRUE", "B_TRUE", "C_TRUE", "D_TRUE", "E_TRUE", "F_FALSE"],
- ["A_TRUE", "B_TRUE", "C_TRUE", "D_TRUE", "E_TRUE"]],
- [["TRUE"]]],
-
- # Simplify should work with up to 31 variables.
- [[["V01_TRUE", "V02_TRUE", "V03_TRUE", "V04_TRUE", "V05_TRUE",
- "V06_TRUE", "V07_TRUE", "V08_TRUE", "V09_TRUE", "V10_TRUE",
- "V11_TRUE", "V12_TRUE", "V13_TRUE", "V14_TRUE", "V15_TRUE",
- "V16_TRUE", "V17_TRUE", "V18_TRUE", "V19_TRUE", "V20_TRUE",
- "V21_TRUE", "V22_TRUE", "V23_TRUE", "V24_TRUE", "V25_TRUE",
- "V26_TRUE", "V27_TRUE", "V28_TRUE", "V29_TRUE", "V30_TRUE",
- "V31_TRUE"],
- ["V01_TRUE", "V02_TRUE", "V03_TRUE", "V04_TRUE", "V05_TRUE",
- "V06_TRUE", "V07_TRUE", "V08_TRUE", "V09_TRUE", "V10_TRUE",
- "V11_TRUE", "V12_TRUE", "V13_TRUE", "V14_TRUE", "V15_TRUE",
- "V16_TRUE", "V17_TRUE", "V18_TRUE", "V19_TRUE", "V20_TRUE",
- "V21_TRUE", "V22_TRUE", "V23_TRUE", "V24_TRUE", "V25_TRUE",
- "V26_TRUE", "V27_TRUE", "V28_TRUE", "V29_TRUE", "V30_TRUE",
- "V31_FALSE"],
- ["V01_FALSE","V02_TRUE", "V03_TRUE", "V04_TRUE", "V05_TRUE",
- "V06_TRUE", "V07_TRUE", "V08_TRUE", "V09_TRUE", "V10_TRUE",
- "V11_TRUE", "V12_TRUE", "V13_TRUE", "V14_TRUE", "V15_TRUE",
- "V16_TRUE", "V17_TRUE", "V18_TRUE", "V19_TRUE", "V20_TRUE",
- "V21_TRUE", "V22_TRUE", "V23_TRUE", "V24_TRUE", "V25_TRUE",
- "V26_TRUE", "V27_TRUE", "V28_TRUE", "V29_TRUE", "V30_TRUE",
- "V31_TRUE"],
- ["V01_FALSE","V02_TRUE", "V03_TRUE", "V04_TRUE", "V05_TRUE",
- "V06_TRUE", "V07_TRUE", "V08_TRUE", "V09_TRUE", "V10_TRUE",
- "V11_TRUE", "V12_TRUE", "V13_TRUE", "V14_TRUE", "V15_TRUE",
- "V16_TRUE", "V17_TRUE", "V18_TRUE", "V19_TRUE", "V20_TRUE",
- "V21_TRUE", "V22_TRUE", "V23_TRUE", "V24_TRUE", "V25_TRUE",
- "V26_TRUE", "V27_TRUE", "V28_TRUE", "V29_TRUE", "V30_TRUE",
- "V31_FALSE"]],
- [[ "V02_TRUE", "V03_TRUE", "V04_TRUE", "V05_TRUE",
- "V06_TRUE", "V07_TRUE", "V08_TRUE", "V09_TRUE", "V10_TRUE",
- "V11_TRUE", "V12_TRUE", "V13_TRUE", "V14_TRUE", "V15_TRUE",
- "V16_TRUE", "V17_TRUE", "V18_TRUE", "V19_TRUE", "V20_TRUE",
- "V21_TRUE", "V22_TRUE", "V23_TRUE", "V24_TRUE", "V25_TRUE",
- "V26_TRUE", "V27_TRUE", "V28_TRUE", "V29_TRUE", "V30_TRUE"
- ]]]);
-
- for my $t (@tests)
- {
- my $set = build_set @{$t->[0]};
- my $res = build_set @{$t->[1]};
-
- # Make sure simplify() yields the expected result.
- my $sim = $set->simplify;
- if ($sim != $res)
- {
- print " (S1) " . $set->string . "\n\t"
- . $sim->string . ' != ' . $res->string . "\n";
- return 1;
- }
-
- # Make sure simplify() is idempotent.
- my $sim2 = $sim->simplify;
- if ($sim2 != $sim)
- {
- print " (S2) " . $sim->string . "\n\t"
- . $sim2->string . ' != ' . $sim->string . "\n";
- return 1;
- }
-
- # Also exercize invert() while we are at it.
-
- # FIXME: Don't run invert() with too much conditionals, this is too slow.
- next if $#{$t->[0][0]} > 8;
-
- my $inv1 = $set->invert->simplify;
- my $inv2 = $sim->invert->simplify;
- if ($inv1 != $inv2)
- {
- print " (S3) " . $set->string . ", " . $sim->string . "\n\t"
- . $inv1->string . ' != ' . $inv2->string . "\n";
- return 1;
- }
- }
-
- return 0;
-}
-
-sub test_sub_conditions ()
-{
- my @tests = ([[["FOO_TRUE", "BAR_FALSE", "BAZ_FALSE"],
- ["FOO_TRUE", "BAR_FALSE", "BAZ_TRUE"],
- ["FOO_FALSE"]],
- ["FOO_TRUE"],
- [["BAR_FALSE", "BAZ_FALSE"],
- ["BAR_FALSE", "BAZ_TRUE"]]],
-
- [[["FOO_TRUE", "BAR_FALSE", "BAZ_FALSE"],
- ["FOO_TRUE", "BAR_FALSE", "BAZ_TRUE"],
- ["FOO_FALSE"]],
- ["FOO_TRUE", "BAR_FALSE"],
- [["BAZ_FALSE"],
- ["BAZ_TRUE"]]],
-
- [[["FOO_TRUE", "BAR_FALSE", "BAZ_FALSE"],
- ["FOO_TRUE", "BAR_FALSE", "BAZ_TRUE"],
- ["FOO_FALSE"]],
- ["FOO_TRUE", "BAR_TRUE"],
- [["FALSE"]]],
-
- [[["FOO_TRUE", "BAR_FALSE", "BAZ_FALSE"],
- ["FOO_TRUE", "BAZ_TRUE"],
- ["FOO_FALSE"]],
- ["FOO_TRUE", "BAR_TRUE"],
- [["BAZ_TRUE"]]],
-
- [[["FOO_TRUE", "BAR_FALSE"],
- ["FOO_TRUE", "BAR_TRUE"]],
- ["FOO_TRUE", "BAR_TRUE"],
- [["TRUE"]]],
-
- [[["TRUE"]],
- ["TRUE"],
- [["TRUE"]]],
-
- [[["FALSE"]],
- ["TRUE"],
- [["FALSE"]]],
-
- [[["FALSE"]],
- ["FALSE"],
- [["FALSE"]]]);
-
- for my $t (@tests)
- {
- my $t1 = build_set @{$t->[0]};
- my $t2 = new Automake::Conditional @{$t->[1]};
- my $t3 = build_set @{$t->[2]};
-
- # Make sure simplify() yields the expected result.
- my $s = $t1->sub_conditions ($t2);
- if ($s != $t3)
- {
- print " (SC) " . $t1->string . "\n\t"
- . $s->string . ' != ' . $t3->string . "\n";
- return 1;
- }
- }
-}
-
-exit (test_basics
- || test_permutations
- || test_invert
- || test_simplify
- || test_sub_conditions);
-
-### Setup "GNU" style for perl-mode and cperl-mode.
-## Local Variables:
-## perl-indent-level: 2
-## perl-continued-statement-offset: 2
-## perl-continued-brace-offset: 0
-## perl-brace-offset: 0
-## perl-brace-imaginary-offset: 0
-## perl-label-offset: -2
-## cperl-indent-level: 2
-## cperl-brace-offset: 0
-## cperl-continued-brace-offset: 0
-## cperl-label-offset: -2
-## cperl-extra-newline-before-brace: t
-## cperl-merge-trailing-else: nil
-## cperl-continued-statement-offset: 2
-## End:
Index: lib/Automake/tests/DisjConditions.pl
===================================================================
RCS file: lib/Automake/tests/DisjConditions.pl
diff -N lib/Automake/tests/DisjConditions.pl
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ lib/Automake/tests/DisjConditions.pl 19 Jan 2003 22:53:22 -0000
@@ -0,0 +1,404 @@
+# Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc.
+#
+# This file is part of GNU Automake.
+#
+# GNU Automake is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#
+# GNU Automake is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with autoconf; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+
+use Automake::Condition qw/TRUE FALSE/;
+use Automake::DisjConditions;
+
+sub test_basics ()
+{
+ my $cond = new Automake::Condition "COND1_TRUE", "COND2_FALSE";
+ my $other = new Automake::Condition "COND3_FALSE";
+ my $set1 = new Automake::DisjConditions $cond, $other;
+ my $set2 = new Automake::DisjConditions $other, $cond;
+ return 1 unless $set1 == $set2;
+ return 1 if $set1->false;
+ return 1 if $set1->true;
+ return 1 unless (new Automake::DisjConditions)->false;
+ return 1 if (new Automake::DisjConditions)->true;
+}
+
+sub build_set (@)
+{
+ my @conds = @_;
+ my @set = ();
+ for my $cond (@conds)
+ {
+ push @set, new Automake::Condition @$cond;
+ }
+ return new Automake::DisjConditions @set;
+}
+
+sub test_permutations ()
+{
+ my @tests = ([[["FALSE"]],
+ [["TRUE"]]],
+
+ [[["TRUE"]],
+ [["TRUE"]]],
+
+ [[["COND1_TRUE", "COND2_TRUE"],
+ ["COND3_FALSE", "COND2_TRUE"]],
+ [["COND1_FALSE","COND2_FALSE","COND3_FALSE"],
+ ["COND1_TRUE", "COND2_FALSE","COND3_FALSE"],
+ ["COND1_FALSE","COND2_TRUE", "COND3_FALSE"],
+ ["COND1_TRUE", "COND2_TRUE", "COND3_FALSE"],
+ ["COND1_FALSE","COND2_FALSE","COND3_TRUE"],
+ ["COND1_TRUE", "COND2_FALSE","COND3_TRUE"],
+ ["COND1_FALSE","COND2_TRUE", "COND3_TRUE"],
+ ["COND1_TRUE", "COND2_TRUE", "COND3_TRUE"]]],
+
+ [[["COND1_TRUE", "COND2_TRUE"],
+ ["TRUE"]],
+ [["COND1_TRUE", "COND2_TRUE"],
+ ["COND1_FALSE", "COND2_TRUE"],
+ ["COND1_FALSE", "COND2_FALSE"],
+ ["COND1_TRUE", "COND2_FALSE"]]],
+
+ [[["COND1_TRUE", "COND2_TRUE"],
+ ["FALSE"]],
+ [["COND1_TRUE", "COND2_TRUE"],
+ ["COND1_FALSE", "COND2_TRUE"],
+ ["COND1_FALSE", "COND2_FALSE"],
+ ["COND1_TRUE", "COND2_FALSE"]]],
+
+ [[["COND1_TRUE"],
+ ["COND2_FALSE"]],
+ [["COND1_TRUE", "COND2_TRUE"],
+ ["COND1_FALSE", "COND2_TRUE"],
+ ["COND1_FALSE", "COND2_FALSE"],
+ ["COND1_TRUE", "COND2_FALSE"]]]
+ );
+
+ for my $t (@tests)
+ {
+ my $set = build_set @{$t->[0]};
+ my $res = build_set @{$t->[1]};
+ my $per = $set->permutations;
+ if ($per != $res)
+ {
+ print " (P) " . $per->string . ' != ' . $res->string . "\n";
+ return 1;
+ }
+ }
+ return 0;
+}
+
+sub test_invert ()
+{
+ my @tests = ([[["FALSE"]],
+ [["TRUE"]]],
+
+ [[["TRUE"]],
+ [["FALSE"]]],
+
+ [[["COND1_TRUE", "COND2_TRUE"],
+ ["COND3_FALSE", "COND2_TRUE"]],
+ [["COND2_FALSE"],
+ ["COND2_FALSE", "COND3_TRUE"],
+ ["COND1_FALSE", "COND2_FALSE"],
+ ["COND1_FALSE", "COND3_TRUE"]]],
+
+ [[["COND1_TRUE", "COND2_TRUE"],
+ ["TRUE"]],
+ [["FALSE"]]],
+
+ [[["COND1_TRUE", "COND2_TRUE"],
+ ["FALSE"]],
+ [["COND1_FALSE"],
+ ["COND2_FALSE"]]],
+
+ [[["COND1_TRUE"],
+ ["COND2_FALSE"]],
+ [["COND1_FALSE", "COND2_TRUE"]]]
+ );
+
+ for my $t (@tests)
+ {
+ my $set = build_set @{$t->[0]};
+ my $res = build_set @{$t->[1]};
+ my $inv = $set->invert;
+ if ($inv != $res)
+ {
+ print " (I) " . $set->string . "\n\t"
+ . $inv->string . ' != ' . $res->string . "\n";
+ return 1;
+ }
+ }
+ return 0;
+}
+
+sub test_simplify ()
+{
+ my @tests = ([[["FOO_TRUE", "BAR_FALSE", "BAZ_FALSE"],
+ ["FOO_TRUE", "BAR_FALSE", "BAZ_TRUE"]],
+ [["FOO_TRUE", "BAR_FALSE"]]],
+
+ [[["FOO_TRUE", "BAR_FALSE", "BAZ_FALSE"],
+ ["FOO_TRUE", "BAR_FALSE", "BAZ_TRUE"],
+ ["FOO_TRUE", "BAR_TRUE"]],
+ [["FOO_TRUE"]]],
+
+ [[["FOO_TRUE", "BAR_FALSE", "BAZ_FALSE"],
+ ["FOO_TRUE", "BAR_FALSE", "BAZ_TRUE"],
+ ["FOO_TRUE", "BAR_TRUE"],
+ ["FOO_FALSE"]],
+ [["TRUE"]]],
+
+ [[["FOO_TRUE", "BAR_FALSE", "BAZ_FALSE"],
+ ["FOO_TRUE", "BAR_FALSE", "BAZ_TRUE"],
+ ["BAR_TRUE", "BAZ_TRUE"],
+ ["BAR_FALSE", "BAZ_TRUE"]],
+ [["BAZ_TRUE"], ["FOO_TRUE", "BAR_FALSE"]]],
+
+ [[["FOO_TRUE", "BAR_FALSE", "BAZ_FALSE"],
+ ["FOO_TRUE", "BAR_FALSE", "BAZ_TRUE"],
+ ["BAR_TRUE", "BAZ_TRUE"],
+ ["BAR_FALSE", "BAZ_TRUE"],
+ ["FOO_FALSE"]],
+ # Note that this could be further simplified to
+ # [["FOO_FALSE"], ["BAZ_TRUE"], ["BAR_FALSE"]]
+ # but simplify isn't able to detect this.
+ [["FOO_FALSE"], ["BAZ_TRUE"], ["BAR_FALSE", "FOO_TRUE"]]],
+
+ [[["B_TRUE"],
+ ["A_FALSE", "B_TRUE"]],
+ [["B_TRUE"]]],
+
+ [[["B_TRUE"],
+ ["A_FALSE", "B_FALSE", "C_TRUE"],
+ ["A_FALSE", "B_FALSE", "C_FALSE"]],
+ # Note that this could be further simplified to
+ # [["A_FALSE"], ["B_TRUE"]]
+ # but simplify isn't able to detect this.
+ [["A_FALSE", "B_FALSE"], ["B_TRUE"]]],
+
+ [[["B_TRUE"],
+ ["A_FALSE", "B_FALSE", "C_TRUE"],
+ ["A_FALSE", "B_FALSE", "C_FALSE"],
+ ["A_TRUE", "B_FALSE"]],
+ [["TRUE"]]],
+
+ [[["A_TRUE", "B_TRUE"],
+ ["A_TRUE", "B_FALSE"],
+ ["A_TRUE", "C_FALSE", "D_FALSE"]],
+ [["A_TRUE"]]],
+
+ [[["A_FALSE", "B_FALSE", "C_FALSE", "D_TRUE", "E_FALSE"],
+ ["A_FALSE", "B_FALSE", "C_TRUE", "D_TRUE", "E_TRUE"],
+ ["A_FALSE", "B_TRUE", "C_TRUE", "D_FALSE", "E_TRUE"],
+ ["A_FALSE", "B_TRUE", "C_FALSE", "D_FALSE", "E_FALSE"],
+ ["A_TRUE", "B_TRUE", "C_FALSE", "D_FALSE", "E_FALSE"],
+ ["A_TRUE", "B_TRUE", "C_TRUE", "D_FALSE", "E_TRUE"],
+ ["A_TRUE", "B_FALSE", "C_TRUE", "D_TRUE", "E_TRUE"],
+ ["A_TRUE", "B_FALSE", "C_FALSE", "D_TRUE", "E_FALSE"]],
+ [ ["B_FALSE", "C_FALSE", "D_TRUE", "E_FALSE"],
+ ["B_FALSE", "C_TRUE", "D_TRUE", "E_TRUE"],
+ ["B_TRUE", "C_TRUE", "D_FALSE", "E_TRUE"],
+ ["B_TRUE", "C_FALSE", "D_FALSE", "E_FALSE"]]],
+
+ [[["A_FALSE", "B_FALSE", "C_FALSE", "D_TRUE", "E_FALSE"],
+ ["A_FALSE", "B_FALSE", "C_TRUE", "D_TRUE", "E_TRUE"],
+ ["A_FALSE", "B_TRUE", "C_TRUE", "D_FALSE", "E_TRUE"],
+ ["A_FALSE", "B_TRUE", "C_FALSE", "D_FALSE", "E_FALSE"],
+ ["A_TRUE", "B_TRUE", "C_FALSE", "D_FALSE", "E_FALSE"],
+ ["A_TRUE", "B_TRUE", "C_TRUE", "D_FALSE", "E_TRUE"],
+ ["A_TRUE", "B_FALSE", "C_TRUE", "D_TRUE", "E_TRUE"],
+ ["A_TRUE", "B_FALSE", "C_FALSE", "D_TRUE", "E_FALSE"],
+ ["A_FALSE", "B_FALSE", "C_FALSE", "D_FALSE", "E_FALSE"],
+ ["A_FALSE", "B_FALSE", "C_TRUE", "D_FALSE", "E_TRUE"],
+ ["A_FALSE", "B_TRUE", "C_TRUE", "D_TRUE", "E_TRUE"],
+ ["A_FALSE", "B_TRUE", "C_FALSE", "D_TRUE", "E_FALSE"],
+ ["A_TRUE", "B_TRUE", "C_FALSE", "D_TRUE", "E_FALSE"],
+ ["A_TRUE", "B_TRUE", "C_TRUE", "D_TRUE", "E_TRUE"],
+ ["A_TRUE", "B_FALSE", "C_TRUE", "D_FALSE", "E_TRUE"],
+ ["A_TRUE", "B_FALSE", "C_FALSE", "D_FALSE", "E_FALSE"]],
+ [["C_FALSE", "E_FALSE"],
+ ["C_TRUE", "E_TRUE"]]],
+
+ [[["A_FALSE"],
+ ["A_TRUE", "B_FALSE"],
+ ["A_TRUE", "B_TRUE", "C_FALSE"],
+ ["A_TRUE", "B_TRUE", "C_TRUE", "D_FALSE"],
+ ["A_TRUE", "B_TRUE", "C_TRUE", "D_TRUE", "E_FALSE"],
+ ["A_TRUE", "B_TRUE", "C_TRUE", "D_TRUE", "E_TRUE", "F_FALSE"],
+ ["A_TRUE", "B_TRUE", "C_TRUE", "D_TRUE", "E_TRUE"]],
+ [["TRUE"]]],
+
+ # Simplify should work with up to 31 variables.
+ [[["V01_TRUE", "V02_TRUE", "V03_TRUE", "V04_TRUE", "V05_TRUE",
+ "V06_TRUE", "V07_TRUE", "V08_TRUE", "V09_TRUE", "V10_TRUE",
+ "V11_TRUE", "V12_TRUE", "V13_TRUE", "V14_TRUE", "V15_TRUE",
+ "V16_TRUE", "V17_TRUE", "V18_TRUE", "V19_TRUE", "V20_TRUE",
+ "V21_TRUE", "V22_TRUE", "V23_TRUE", "V24_TRUE", "V25_TRUE",
+ "V26_TRUE", "V27_TRUE", "V28_TRUE", "V29_TRUE", "V30_TRUE",
+ "V31_TRUE"],
+ ["V01_TRUE", "V02_TRUE", "V03_TRUE", "V04_TRUE", "V05_TRUE",
+ "V06_TRUE", "V07_TRUE", "V08_TRUE", "V09_TRUE", "V10_TRUE",
+ "V11_TRUE", "V12_TRUE", "V13_TRUE", "V14_TRUE", "V15_TRUE",
+ "V16_TRUE", "V17_TRUE", "V18_TRUE", "V19_TRUE", "V20_TRUE",
+ "V21_TRUE", "V22_TRUE", "V23_TRUE", "V24_TRUE", "V25_TRUE",
+ "V26_TRUE", "V27_TRUE", "V28_TRUE", "V29_TRUE", "V30_TRUE",
+ "V31_FALSE"],
+ ["V01_FALSE","V02_TRUE", "V03_TRUE", "V04_TRUE", "V05_TRUE",
+ "V06_TRUE", "V07_TRUE", "V08_TRUE", "V09_TRUE", "V10_TRUE",
+ "V11_TRUE", "V12_TRUE", "V13_TRUE", "V14_TRUE", "V15_TRUE",
+ "V16_TRUE", "V17_TRUE", "V18_TRUE", "V19_TRUE", "V20_TRUE",
+ "V21_TRUE", "V22_TRUE", "V23_TRUE", "V24_TRUE", "V25_TRUE",
+ "V26_TRUE", "V27_TRUE", "V28_TRUE", "V29_TRUE", "V30_TRUE",
+ "V31_TRUE"],
+ ["V01_FALSE","V02_TRUE", "V03_TRUE", "V04_TRUE", "V05_TRUE",
+ "V06_TRUE", "V07_TRUE", "V08_TRUE", "V09_TRUE", "V10_TRUE",
+ "V11_TRUE", "V12_TRUE", "V13_TRUE", "V14_TRUE", "V15_TRUE",
+ "V16_TRUE", "V17_TRUE", "V18_TRUE", "V19_TRUE", "V20_TRUE",
+ "V21_TRUE", "V22_TRUE", "V23_TRUE", "V24_TRUE", "V25_TRUE",
+ "V26_TRUE", "V27_TRUE", "V28_TRUE", "V29_TRUE", "V30_TRUE",
+ "V31_FALSE"]],
+ [[ "V02_TRUE", "V03_TRUE", "V04_TRUE", "V05_TRUE",
+ "V06_TRUE", "V07_TRUE", "V08_TRUE", "V09_TRUE", "V10_TRUE",
+ "V11_TRUE", "V12_TRUE", "V13_TRUE", "V14_TRUE", "V15_TRUE",
+ "V16_TRUE", "V17_TRUE", "V18_TRUE", "V19_TRUE", "V20_TRUE",
+ "V21_TRUE", "V22_TRUE", "V23_TRUE", "V24_TRUE", "V25_TRUE",
+ "V26_TRUE", "V27_TRUE", "V28_TRUE", "V29_TRUE", "V30_TRUE"
+ ]]]);
+
+ for my $t (@tests)
+ {
+ my $set = build_set @{$t->[0]};
+ my $res = build_set @{$t->[1]};
+
+ # Make sure simplify() yields the expected result.
+ my $sim = $set->simplify;
+ if ($sim != $res)
+ {
+ print " (S1) " . $set->string . "\n\t"
+ . $sim->string . ' != ' . $res->string . "\n";
+ return 1;
+ }
+
+ # Make sure simplify() is idempotent.
+ my $sim2 = $sim->simplify;
+ if ($sim2 != $sim)
+ {
+ print " (S2) " . $sim->string . "\n\t"
+ . $sim2->string . ' != ' . $sim->string . "\n";
+ return 1;
+ }
+
+ # Also exercize invert() while we are at it.
+
+ # FIXME: Don't run invert() with too much conditions, this is too slow.
+ next if $#{$t->[0][0]} > 8;
+
+ my $inv1 = $set->invert->simplify;
+ my $inv2 = $sim->invert->simplify;
+ if ($inv1 != $inv2)
+ {
+ print " (S3) " . $set->string . ", " . $sim->string . "\n\t"
+ . $inv1->string . ' != ' . $inv2->string . "\n";
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+sub test_sub_conditions ()
+{
+ my @tests = ([[["FOO_TRUE", "BAR_FALSE", "BAZ_FALSE"],
+ ["FOO_TRUE", "BAR_FALSE", "BAZ_TRUE"],
+ ["FOO_FALSE"]],
+ ["FOO_TRUE"],
+ [["BAR_FALSE", "BAZ_FALSE"],
+ ["BAR_FALSE", "BAZ_TRUE"]]],
+
+ [[["FOO_TRUE", "BAR_FALSE", "BAZ_FALSE"],
+ ["FOO_TRUE", "BAR_FALSE", "BAZ_TRUE"],
+ ["FOO_FALSE"]],
+ ["FOO_TRUE", "BAR_FALSE"],
+ [["BAZ_FALSE"],
+ ["BAZ_TRUE"]]],
+
+ [[["FOO_TRUE", "BAR_FALSE", "BAZ_FALSE"],
+ ["FOO_TRUE", "BAR_FALSE", "BAZ_TRUE"],
+ ["FOO_FALSE"]],
+ ["FOO_TRUE", "BAR_TRUE"],
+ [["FALSE"]]],
+
+ [[["FOO_TRUE", "BAR_FALSE", "BAZ_FALSE"],
+ ["FOO_TRUE", "BAZ_TRUE"],
+ ["FOO_FALSE"]],
+ ["FOO_TRUE", "BAR_TRUE"],
+ [["BAZ_TRUE"]]],
+
+ [[["FOO_TRUE", "BAR_FALSE"],
+ ["FOO_TRUE", "BAR_TRUE"]],
+ ["FOO_TRUE", "BAR_TRUE"],
+ [["TRUE"]]],
+
+ [[["TRUE"]],
+ ["TRUE"],
+ [["TRUE"]]],
+
+ [[["FALSE"]],
+ ["TRUE"],
+ [["FALSE"]]],
+
+ [[["FALSE"]],
+ ["FALSE"],
+ [["FALSE"]]]);
+
+ for my $t (@tests)
+ {
+ my $t1 = build_set @{$t->[0]};
+ my $t2 = new Automake::Condition @{$t->[1]};
+ my $t3 = build_set @{$t->[2]};
+
+ # Make sure simplify() yields the expected result.
+ my $s = $t1->sub_conditions ($t2);
+ if ($s != $t3)
+ {
+ print " (SC) " . $t1->string . "\n\t"
+ . $s->string . ' != ' . $t3->string . "\n";
+ return 1;
+ }
+ }
+}
+
+exit (test_basics
+ || test_permutations
+ || test_invert
+ || test_simplify
+ || test_sub_conditions);
+
+### Setup "GNU" style for perl-mode and cperl-mode.
+## Local Variables:
+## perl-indent-level: 2
+## perl-continued-statement-offset: 2
+## perl-continued-brace-offset: 0
+## perl-brace-offset: 0
+## perl-brace-imaginary-offset: 0
+## perl-label-offset: -2
+## cperl-indent-level: 2
+## cperl-brace-offset: 0
+## cperl-continued-brace-offset: 0
+## cperl-label-offset: -2
+## cperl-extra-newline-before-brace: t
+## cperl-merge-trailing-else: nil
+## cperl-continued-statement-offset: 2
+## End:
Index: lib/Automake/tests/Makefile.am
===================================================================
RCS file: /cvs/automake/automake/lib/Automake/tests/Makefile.am,v
retrieving revision 1.1
diff -u -r1.1 Makefile.am
--- lib/Automake/tests/Makefile.am 18 Nov 2002 18:43:28 -0000 1.1
+++ lib/Automake/tests/Makefile.am 19 Jan 2003 22:53:22 -0000
@@ -1,6 +1,6 @@
## Process this file with automake to create Makefile.in
-## Copyright (C) 2002 Free Software Foundation, Inc.
+## Copyright (C) 2002, 2003 Free Software Foundation, Inc.
## This program is free software; you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published by
@@ -19,7 +19,7 @@
TESTS_ENVIRONMENT = $(PERL) -Mstrict -I $(top_srcdir)/lib -w
TESTS = \
-Conditional.pl \
-ConditionalSet.pl
+Condition.pl \
+DisjConditions.pl
EXTRA_DIST = $(TESTS)
Index: lib/Automake/tests/Makefile.in
===================================================================
RCS file: /cvs/automake/automake/lib/Automake/tests/Makefile.in,v
retrieving revision 1.1
diff -u -r1.1 Makefile.in
--- lib/Automake/tests/Makefile.in 9 Jan 2003 12:43:38 -0000 1.1
+++ lib/Automake/tests/Makefile.in 19 Jan 2003 22:53:23 -0000
@@ -95,8 +95,8 @@
TESTS_ENVIRONMENT = $(PERL) -Mstrict -I $(top_srcdir)/lib -w
TESTS = \
-Conditional.pl \
-ConditionalSet.pl
+Condition.pl \
+DisjConditions.pl
EXTRA_DIST = $(TESTS)
--
Alexandre Duret-Lutz