automake-patches
[Top][All Lists]
Advanced

[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





reply via email to

[Prev in Thread] Current Thread [Next in Thread]