]> git.ipfire.org Git - thirdparty/automake.git/commitdiff
VarAppend: New module
authorMatthias Paulmier <matthias.paulmier@etu.u-bordeaux.fr>
Mon, 18 Jun 2018 15:00:46 +0000 (17:00 +0200)
committerMatthias Paulmier <matthias.paulmier@etu.u-bordeaux.fr>
Fri, 22 Jun 2018 12:19:52 +0000 (14:19 +0200)
This module is used in Automake::Variable::define to append values to
variables.

* VarAppend: New module with helper functions for appending to variables.

lib/Automake/VarAppend.pm [new file with mode: 0644]
lib/Automake/Variable.pm
lib/Automake/local.mk

diff --git a/lib/Automake/VarAppend.pm b/lib/Automake/VarAppend.pm
new file mode 100644 (file)
index 0000000..8f114cf
--- /dev/null
@@ -0,0 +1,124 @@
+# Copyright (C) 2018  Matthias Paulmier
+
+# 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
+# of the License, 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, see <http://www.gnu.org/licenses/>.
+
+package Automake::VarAppend;
+
+use strict;
+use 5.006;
+
+use Automake::Channels;
+use Automake::Condition qw (TRUE FALSE);
+use Automake::Item;
+use Automake::VarDef;
+use Exporter;
+
+use vars '@ISA', '@EXPORT';
+
+@ISA = qw (Automake::Item Exporter);
+
+@EXPORT = qw (append_var_cur_cond first_assign_var am_check_definitions);
+
+=head1 NAME
+
+Automake::VarAppend - Helper methods for appending to variables
+
+=head1 DESCRIPTION
+
+This package provides methods for appending values to variables.
+
+It is used by the C<Automake::Variable> class in its C<define> function.
+
+=head2 Functions
+
+=item C<append_var_cur_cond ($self, $var, $owner, $where, $def, $value,
+$comment)>
+
+Append $value to an existing $var defined for the current condition.  This is
+only used in the define method of this file.
+
+=cut
+
+sub append_var_cur_cond ($$$$$$$)
+{
+  my ($self, $var, $owner, $where, $def, $value, $comment) = @_;
+  $def->append ($value, $comment);
+  $self->{'last-append'} = [];
+
+  # Only increase owners.  A VAR_CONFIGURE variable augmented in a
+  # Makefile.am becomes a VAR_MAKEFILE variable.
+  $def->set_owner ($owner, $where->clone)
+      if $owner > $def->owner;
+}
+
+
+=item C<first_assign_var ($sefl, $var, $cond, $owner, $where, $def, $value, $pretty, $comment, $new_var, $type)>
+
+Method that assign a value to a variable for the first time or for total
+redefinition of an Automake variable or an AC_SUBST variable for an existing
+condition.
+
+=cut
+
+sub first_assign_var ($$$$$$$$$$$)
+{
+  my ($self, $var, $cond, $owner, $where, $def, $value, $pretty, $comment, $new_var, $type) = @_;
+
+  # Never decrease an owner.
+  $owner = $def->owner
+    if ! $new_var && $owner < $def->owner;
+
+  # Assignments to a macro set its location.  We don't adjust
+  # locations for '+='.  Ideally I suppose we would associate
+  # line numbers with random bits of text.
+  $def = new Automake::VarDef ($var, $value, $comment, $where->clone,
+                              $type, $owner, $pretty);
+  $self->set ($cond, $def);
+}
+
+
+=item am_check_definitions ($var, $cond, $def, $type, $where)
+
+Additional checks for Automake definitions
+
+=cut
+
+sub am_check_definitions ($$$$$)
+{
+  my ($var, $cond, $def, $type, $where) = @_;
+  # An Automake variable must be consistently defined with the same
+  # sign by Automake.
+  if ($def->type ne $type && $def->owner == VAR_AUTOMAKE)
+    {
+      error ($def->location,
+             "Automake variable '$var' was set with '"
+             . $def->type . "=' here ...", partial => 1);
+      error ($where, "... and is now set with '$type=' here.");
+      prog_error ("Automake variable assignments should be consistently\n"
+                  . "defined with the same sign");
+    }
+}
+
+
+=back
+
+=head1 SEE ALSO
+
+L<Automake::VarDef>, L<Automake::Variable>,
+L<Automake::Condition>, L<Automake::Item>,
+L<Automake::Channels>.
+
+=cut
+
+1;
index 5dea97e7f6cedde8b628ce00567e81355b67c79f..7dc485dde95241ac0665dc8ef10e672a068e266b 100644 (file)
@@ -30,6 +30,7 @@ use Automake::General 'uniq';
 use Automake::Global;
 use Automake::Item;
 use Automake::Location;
+use Automake::VarAppend;
 use Automake::VarDef;
 use Automake::Wrap 'makefile_wrap';
 require Exporter;
@@ -146,6 +147,8 @@ my $_VARIABLE_PATTERN = '^' . $_VARIABLE_CHARACTERS . "\$";
 my $_VARIABLE_RECURSIVE_PATTERN =
     '^([.A-Za-z0-9_@]|\$[({]' . $_VARIABLE_CHARACTERS . '[})]?)+' . "\$";
 
+# Count of helper variables used to implement conditional '+='.
+my $_appendvar;
 # The order in which variables should be output.  (May contain
 # duplicates -- only the first occurrence matters.)
 my @_var_order;
@@ -180,7 +183,7 @@ my %_am_macro_for_var =
    pyexecdir => 'AM_PATH_PYTHON',
    PYTHON => 'AM_PATH_PYTHON',
    pythondir => 'AM_PATH_PYTHON',
-   );
+  );
 
 # Macros shipped with Autoconf.
 my %_ac_macro_for_var =
@@ -202,7 +205,7 @@ my %_ac_macro_for_var =
    UPC => 'AM_PROG_UPC',
    UPCFLAGS => 'AM_PROG_UPC',
    YACC => 'AC_PROG_YACC',
-   );
+  );
 
 # The name of the configure.ac file.
 my $configure_ac;
@@ -216,9 +219,6 @@ my %_silent_variable_override =
    JAVAC => 1,
    JAVAROOT => 1);
 
-# Count of helper variables used to implement conditional '+='.
-my $_appendvar;
-
 # Each call to C<Automake::Variable::traverse_recursively> gets an
 # unique label. This is used to detect recursively defined variables.
 my $_traversal = 0;
@@ -354,9 +354,9 @@ other internal data.
 
 sub reset ()
 {
+  $_appendvar = 0;
   %_variable_dict = ();
   %_primary_dict = ();
-  $_appendvar = 0;
   @_var_order = ();
   %_gen_varname = ();
   %_gen_varname_n = ();
@@ -804,159 +804,6 @@ sub check_variable_expansions ($$)
 }
 
 
-# _append_var_cur_cond ($self, $var, $owner, $where, $def, $value, $comment)
-# --------------------------------------------------
-# Append $value to an existing $var defined for the current condition.
-# This is only used in the define method of this file.
-sub _append_var_cur_cond ($$$$$$$)
-{
-  my ($self, $var, $owner, $where, $def, $value, $comment) = @_;
-  $def->append ($value, $comment);
-  $self->{'last-append'} = [];
-
-  # Only increase owners.  A VAR_CONFIGURE variable augmented in a
-  # Makefile.am becomes a VAR_MAKEFILE variable.
-  $def->set_owner ($owner, $where->clone)
-      if $owner > $def->owner;
-}
-
-# _append_var_other_cond ($self, $var, $cond, $owner, $where, $def, $value, $pretty, $comment, $new_var)
-# -----------------------------------------------------------------------------
-# We declare a helper variable conditionally when $cond is not TRUE.
-# Example for:
-#     FOO = foo
-#     if COND
-#       FOO += bar
-#     endif
-# We do:
-#     FOO = foo $(am__append_1)
-#     @COND_TRUE@am__append_1 = bar
-# When $cond is TRUE however, we do not need this variable.
-
-sub _append_var_other_cond ($$$$$$$$$$)
-{
-  my ($self, $var, $cond, $owner, $where, $def, $value, $pretty, $comment, $new_var) = @_;
-  my $lastappend = [];
-  # Do we need an helper variable?
-  if ($cond != TRUE)
-    {
-      # Can we reuse the helper variable created for the previous
-      # append?  (We cannot reuse older helper variables because
-      # we must preserve the order of items appended to the
-      # variable.)
-      my $condstr = $cond->string;
-      my $key = "$var:$condstr";
-      my ($appendvar, $appendvarcond) = @{$self->{'last-append'}};
-      if ($appendvar && $condstr eq $appendvarcond)
-        {
-          $var = $appendvar;
-          $owner = VAR_AUTOMAKE;
-          $self = var ($var);
-          $def = $self->rdef ($cond);
-          $new_var = 0;
-        }
-      else
-        {
-          my $num = ++$_appendvar;
-          my $hvar = "am__append_$num";
-          $lastappend = [$hvar, $condstr];
-          &define ($hvar, VAR_AUTOMAKE, '+',
-                   $cond, $value, $comment, $where, $pretty);
-
-          $comment = '';
-          $value = "\$($hvar)";
-        }
-    }
-
-  foreach my $vcond ($self->conditions->conds)
-    {
-      my $undef_cond = $self->not_always_defined_in_cond ($cond);
-      if (! $undef_cond->false)
-        {
-          error ($where,
-                 "cannot apply '+=' because '$var' is not defined "
-                 . "in\nthe following conditions:\n  "
-                 . join ("\n  ", map { $_->human } $undef_cond->conds)
-                 . "\neither define '$var' in these conditions,"
-                 . " or use\n'+=' in the same conditions as"
-                 . " the definitions.");
-        }
-      else
-        {
-          &define ($var, $owner, '+', $vcond, $value, $comment,
-                   $where, $pretty);
-        }
-    }
-  $self->{'last-append'} = $lastappend;
-  # We return the variables we modified
-  return ($self, $var, $value);
-}
-
-# _first_assign_var ($sefl, $var, $cond, $owner, $where, $def, $value, $pretty, $comment, $new_var, $type)
-# ---------------------------------------------------
-# Method that assign a value to a variable for the first time or for
-# total redefinition of an Automake variable or an AC_SUBST variable for
-# an existing condition.
-
-sub _first_assign_var ($$$$$$$$$$$)
-{
-  my ($self, $var, $cond, $owner, $where, $def, $value, $pretty, $comment, $new_var, $type) = @_;
-  _check_ambiguous_condition ($self, $cond, $where)
-      unless (!$new_var
-              && (($def->owner == VAR_AUTOMAKE && $owner != VAR_AUTOMAKE)
-                  || $def->owner == VAR_CONFIGURE));
-
-  # Never decrease an owner.
-  $owner = $def->owner
-      if ! $new_var && $owner < $def->owner;
-
-  # Assignments to a macro set its location.  We don't adjust
-  # locations for '+='.  Ideally I suppose we would associate
-  # line numbers with random bits of text.
-  $def = new Automake::VarDef ($var, $value, $comment, $where->clone,
-                              $type, $owner, $pretty);
-      $self->set ($cond, $def);
-  push @_var_order, $var;
-}
-
-# _am_check_definitions ($self, $var, $cond, $def, $value, $type, $where)
-# ----------
-# Additional checks for Automake definitions
-sub _am_check_definitions ($$$$$$$)
-{
-  my ($self, $var, $cond, $def, $value, $type, $where) = @_;
-  # An Automake variable must be consistently defined with the same
-  # sign by Automake.
-  if ($def->type ne $type && $def->owner == VAR_AUTOMAKE)
-    {
-      error ($def->location,
-             "Automake variable '$var' was set with '"
-             . $def->type . "=' here ...", partial => 1);
-      error ($where, "... and is now set with '$type=' here.");
-      prog_error ("Automake variable assignments should be consistently\n"
-                  . "defined with the same sign");
-    }
-
-  # If Automake tries to override a value specified by the user,
-  # just don't let it do.
-  if ($def->owner != VAR_AUTOMAKE)
-    {
-      if (! exists $_silent_variable_override{$var})
-        {
-          my $condmsg = ($cond == TRUE
-                         ? '' : (" in condition '" . $cond->human . "'"));
-          msg_cond_var ('override', $cond, $var,
-                        "user variable '$var' defined here$condmsg ...",
-                        partial => 1);
-          msg ('override', $where,
-               "... overrides Automake variable '$var' defined here");
-        }
-      verb ("refusing to override the user definition of:\n"
-            . $self->dump ."with '" . $cond->human . "' => '$value'");
-      return -1;
-    }
-  return 0;
-}
 =item C<Automake::Variable::define($varname, $owner, $type, $cond, $value, $comment, $where, $pretty)>
 
 Define or append to a new variable.
@@ -1039,32 +886,136 @@ sub define ($$$$$$$$)
   # Additional checks for Automake definitions.
   if ($owner == VAR_AUTOMAKE && ! $new_var)
     {
-      return if (-1 == _am_check_definitions ($self, $var, $cond, $def, $value, $type,
-                                              $where));
+      am_check_definitions ($var, $cond, $def, $type, $where);
+      # If Automake tries to override a value specified by the user,
+      # just don't let it do.
+      if ($def->owner != VAR_AUTOMAKE)
+       {
+         if (! exists $_silent_variable_override{$var})
+           {
+             my $condmsg = ($cond == TRUE
+                            ? '' : (" in condition '" . $cond->human . "'"));
+             msg_cond_var ('override', $cond, $var,
+                           "user variable '$var' defined here$condmsg ...",
+                           partial => 1);
+             msg ('override', $where,
+                  "... overrides Automake variable '$var' defined here");
+           }
+         verb ("refusing to override the user definition of:\n"
+               . $self->dump ."with '" . $cond->human . "' => '$value'");
+         return;
+       }
     }
-
   # Differentiate assignment types.
 
   # 1. append (+=) to a variable defined for current condition
   if ($type eq '+' && ! $new_var)
     {
-      _append_var_cur_cond ($self, $var, $owner, $where, $def, $value,
+      append_var_cur_cond ($self, $var, $owner, $where, $def, $value,
                             $comment);
     }
   # 2. append (+=) to a variable defined for *another* condition
   elsif ($type eq '+' && ! $self->conditions->false)
     {
-      # We get back some variables that will be needed later
-      ($var, $value) = _append_var_other_cond ($self, $var, $cond,
-                                               $owner, $where, $def,
-                                               $value, $pretty,
-                                               $comment, $new_var);
+      # * Generally, $cond is not TRUE.  For instance:
+      #     FOO = foo
+      #     if COND
+      #       FOO += bar
+      #     endif
+      #   In this case, we declare an helper variable conditionally,
+      #   and append it to FOO:
+      #     FOO = foo $(am__append_1)
+      #     @COND_TRUE@am__append_1 = bar
+      #   Of course if FOO is defined under several conditions, we add
+      #   $(am__append_1) to each definitions.
+      #
+      # * If $cond is TRUE, we don't need the helper variable.  E.g., in
+      #     if COND1
+      #       FOO = foo1
+      #     else
+      #       FOO = foo2
+      #     endif
+      #     FOO += bar
+      #   we can add bar directly to all definition of FOO, and output
+      #     @COND_TRUE@FOO = foo1 bar
+      #     @COND_FALSE@FOO = foo2 bar
+
+      my $lastappend = [];
+      # Do we need an helper variable?
+      if ($cond != TRUE)
+        {
+         # Can we reuse the helper variable created for the previous
+         # append?  (We cannot reuse older helper variables because
+         # we must preserve the order of items appended to the
+         # variable.)
+         my $condstr = $cond->string;
+         my $key = "$var:$condstr";
+         my ($appendvar, $appendvarcond) = @{$self->{'last-append'}};
+         if ($appendvar && $condstr eq $appendvarcond)
+           {
+             # Yes, let's simply append to it.
+             $var = $appendvar;
+             $owner = VAR_AUTOMAKE;
+             $self = var ($var);
+             $def = $self->rdef ($cond);
+             $new_var = 0;
+           }
+         else
+           {
+             # No, create it.
+             my $num = ++$_appendvar;
+             my $hvar = "am__append_$num";
+             $lastappend = [$hvar, $condstr];
+             &define ($hvar, VAR_AUTOMAKE, '+',
+                      $cond, $value, $comment, $where, $pretty);
+
+             # Now HVAR is to be added to VAR.
+             $comment = '';
+             $value = "\$($hvar)";
+           }
+       }
+
+      # Add VALUE to all definitions of SELF.
+      foreach my $vcond ($self->conditions->conds)
+        {
+         # We have a bit of error detection to do here.
+         # This:
+         #   if COND1
+         #     X = Y
+         #   endif
+         #   X += Z
+         # should be rejected because X is not defined for all conditions
+         # where '+=' applies.
+         my $undef_cond = $self->not_always_defined_in_cond ($cond);
+         if (! $undef_cond->false)
+           {
+             error ($where,
+                    "cannot apply '+=' because '$var' is not defined "
+                    . "in\nthe following conditions:\n  "
+                    . join ("\n  ", map { $_->human } $undef_cond->conds)
+                    . "\neither define '$var' in these conditions,"
+                    . " or use\n'+=' in the same conditions as"
+                    . " the definitions.");
+           }
+         else
+           {
+             &define ($var, $owner, '+', $vcond, $value, $comment,
+                      $where, $pretty);
+           }
+       }
+      $self->{'last-append'} = $lastappend;
     }
   # 3. first assignment (=, :=, or +=)
   else
     {
-      _first_assign_var ($self, $var, $cond, $owner, $where, $def,
-                         $value, $pretty, $comment, $new_var, $type);
+      _check_ambiguous_condition ($self, $cond, $where)
+       unless (!$new_var
+               && (($def->owner == VAR_AUTOMAKE && $owner != VAR_AUTOMAKE)
+                   || $def->owner == VAR_CONFIGURE));
+
+      first_assign_var ($self, $var, $cond, $owner, $where, $def,
+                        $value, $pretty, $comment, $new_var, $type);
+      push @_var_order, $var;
     }
 
   # Call any defined hook.  This helps to update some internal state
index a0b2ea462faee20dc8ea7365b4b7ba632bbd9295..16c56d819b4511871caaf951d2c931780bf18c57 100644 (file)
@@ -41,6 +41,7 @@ dist_perllib_DATA = \
   %D%/Rule.pm \
   %D%/RuleDef.pm \
   %D%/Utils.pm \
+  %D%/VarAppend.pm \
   %D%/Variable.pm \
   %D%/VarDef.pm \
   %D%/Version.pm \