* lib/Automake/Variable.pm (loc_and_value_as_list_recursive,
authorAlexandre Duret-Lutz <adl@gnu.org>
Sat, 29 Nov 2003 23:47:02 +0000 (23:47 +0000)
committerAlexandre Duret-Lutz <adl@gnu.org>
Sat, 29 Nov 2003 23:47:02 +0000 (23:47 +0000)
_value_as_list_recursive_worker): Merge into ...
(value_as_list_recursive): ... this function.  Pass options
as a hash argument, and use the `location' option to trigger
the behavior of loc_and_value_as_list_recursive.
(traverse_recursively, transform_variable_recursively): Take
options as a %options argument.
(_do_recursive_traversal): Perform expansion of inner variables
(as in `$(FILE).ext') on request.
* automake.in (handle_options, check_libobjs_sources)
(handle_source_transform, handle_LIBOBJS, handle_ltlibraries)
(handle_ltlibraries, handle_man_pages, handle_dist)
(handle_gettext, am_install_var): Adjust usage of
value_as_list_recursive.
(handle_texinfo_helper): Pass inner_expand to
value_as_list_recursive.
* tests/txinfo28.test: New file.
* tests/Makefile.am (TESTS): Add txinfo28.test.
Report from Ralf Corsepius.

ChangeLog
automake.in
lib/Automake/Variable.pm
tests/Makefile.am
tests/Makefile.in
tests/txinfo28.test [new file with mode: 0755]

index 36208e0..e0e1e44 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,25 @@
 2003-11-29  Alexandre Duret-Lutz  <adl@gnu.org>
 
+       * lib/Automake/Variable.pm (loc_and_value_as_list_recursive,
+       _value_as_list_recursive_worker): Merge into ...
+       (value_as_list_recursive): ... this function.  Pass options
+       as a hash argument, and use the `location' option to trigger
+       the behavior of loc_and_value_as_list_recursive.
+       (traverse_recursively, transform_variable_recursively): Take
+       options as a %options argument.
+       (_do_recursive_traversal): Perform expansion of inner variables
+       (as in `$(FILE).ext') on request.
+       * automake.in (handle_options, check_libobjs_sources)
+       (handle_source_transform, handle_LIBOBJS, handle_ltlibraries)
+       (handle_ltlibraries, handle_man_pages, handle_dist)
+       (handle_gettext, am_install_var): Adjust usage of
+       value_as_list_recursive.
+       (handle_texinfo_helper): Pass inner_expand to
+       value_as_list_recursive.
+       * tests/txinfo28.test: New file.
+       * tests/Makefile.am (TESTS): Add txinfo28.test.
+       Report from Ralf Corsepius.
+
        * lib/Automake/Variable.pm (_do_recursive_traversal): Do not
        update @_substfroms and @_substfroms for undefined variables.
        * tests/substre2.test: New file.
index 94d9ed7..cc29348 100755 (executable)
@@ -948,7 +948,8 @@ sub handle_options
     {
       # FIXME: We should disallow conditional definitions of AUTOMAKE_OPTIONS.
       if (process_option_list ($var->rdef (TRUE)->location,
-                              $var->value_as_list_recursive (TRUE)))
+                              $var->value_as_list_recursive (cond_filter =>
+                                                             TRUE)))
        {
          return 1;
        }
@@ -1350,7 +1351,7 @@ sub check_libobjs_sources
       my $var = var ($varname);
       if ($var)
        {
-         @files = $var->value_as_list_recursive ('all');
+         @files = $var->value_as_list_recursive;
        }
       elsif ($prefix eq '')
        {
@@ -1786,8 +1787,7 @@ sub handle_source_transform
            if ($var->has_conditional_contents)
              {
                $distvar = "am__${varname}_DIST";
-               my @files =
-                 uniq ($var->value_as_list_recursive ('all'));
+               my @files = uniq ($var->value_as_list_recursive);
                define_pretty_variable ($distvar, TRUE, $where, @files);
              }
            push @dist_sources, "\$($distvar)"
@@ -1947,8 +1947,7 @@ sub handle_LIBOBJS ($$$)
          $rewrite = "^" . quotemeta ($iter) . "\$";
          # Only require the file if it is not a built source.
          my $bs = var ('BUILT_SOURCES');
-         if (! $bs
-             || ! grep (/$rewrite/, $bs->value_as_list_recursive ('all')))
+         if (! $bs || ! grep (/$rewrite/, $bs->value_as_list_recursive))
            {
              require_file_with_macro ($cond, $var, FOREIGN, $iter);
            }
@@ -2311,7 +2310,7 @@ sub handle_ltlibraries
       # Get the installation directory of each library.
       (my $dir = $key) =~ s/^nobase_//;
       my $var = rvar ($key . '_LTLIBRARIES');
-      for my $pair ($var->loc_and_value_as_list_recursive ('all'))
+      for my $pair ($var->value_as_list_recursive (location => 1))
        {
          my ($where, $lib) = @$pair;
          # We reject libraries which are installed in several places,
@@ -2362,9 +2361,8 @@ sub handle_ltlibraries
       my $libname_rx = "^lib.*\.la";
       my $ldvar = var ("${xlib}_LDFLAGS") || var ('AM_LDFLAGS');
       my $ldvar2 = var ('LDFLAGS');
-      if (($ldvar && grep (/-module/, $ldvar->value_as_list_recursive ('all')))
-         || ($ldvar2
-             && grep (/-module/, $ldvar2->value_as_list_recursive ('all'))))
+      if (($ldvar && grep (/-module/, $ldvar->value_as_list_recursive))
+         || ($ldvar2 && grep (/-module/, $ldvar2->value_as_list_recursive)))
        {
          # Relax name checking for libtool modules.
          $libname_rx = "\.la";
@@ -2702,12 +2700,13 @@ sub handle_texinfo_helper ($)
   my $d = var 'DISTCLEANFILES';
   my $c = var 'CLEANFILES';
   my @f = ();
-  push @f, $d->value_as_list_recursive (TRUE) if $d;
-  push @f, $c->value_as_list_recursive (TRUE) if $c;
+  push @f, $d->value_as_list_recursive (inner_expand => 1) if $d;
+  push @f, $c->value_as_list_recursive (inner_expand => 1) if $c;
   @f = map { s|[^A-Za-z_0-9*\[\]\-]|\\$&|g; s|\*|[^/]*|g; $_; } @f;
   my $user_cleaned_files = '^(?:' . join ('|', @f) . ')$';
 
-  foreach my $texi ($info_texinfos->value_as_list_recursive ('all'))
+  foreach my $texi ($info_texinfos->value_as_list_recursive (inner_expand
+                                                            => 1))
     {
       my $infobase = $texi;
       $infobase =~ s/\.(txi|texinfo|texi)$//;
@@ -3028,7 +3027,7 @@ sub handle_man_pages
       my $var = var ($varname);
       if ($var)
        {
-         foreach ($var->value_as_list_recursive ('all'))
+         foreach ($var->value_as_list_recursive)
            {
              # A page like `foo.1c' goes into man1dir.
              if (/\.([0-9a-z])([a-z]*)$/)
@@ -3259,7 +3258,7 @@ sub handle_dist ()
       # appropriate condition.  This is meaningful if the nature of
       # the distribution should depend upon the configure options
       # used.
-      foreach ($extra_dist->value_as_list_recursive ('all'))
+      foreach ($extra_dist->value_as_list_recursive)
        {
          next if /^\@.*\@$/;
          next unless s,/+[^/]+$,,;
@@ -3271,7 +3270,7 @@ sub handle_dist ()
   # We have to check DIST_COMMON for extra directories in case the
   # user put a source used in AC_OUTPUT into a subdir.
   my $topsrcdir = backname ($relative_dir);
-  foreach (rvar ('DIST_COMMON')->value_as_list_recursive ('all'))
+  foreach (rvar ('DIST_COMMON')->value_as_list_recursive)
     {
       next if /^\@.*\@$/;
       s/\$\(top_srcdir\)/$topsrcdir/;
@@ -3316,7 +3315,7 @@ sub handle_dist ()
          $dist_subdir_name = 'DIST_SUBDIRS';
          define_pretty_variable
            ('DIST_SUBDIRS', TRUE, INTERNAL,
-            uniq ($subdirs->value_as_list_recursive ('all')));
+            uniq ($subdirs->value_as_list_recursive));
        }
       else
        {
@@ -3352,10 +3351,10 @@ sub handle_subdirs ()
   return
     unless $subdirs;
 
-  my @subdirs = $subdirs->value_as_list_recursive ('all');
+  my @subdirs = $subdirs->value_as_list_recursive;
   my @dsubdirs = ();
   my $dsubdirs = var ('DIST_SUBDIRS');
-  @dsubdirs = $dsubdirs->value_as_list_recursive ('all')
+  @dsubdirs = $dsubdirs->value_as_list_recursive
     if $dsubdirs;
 
   # If an `obj/' directory exists, BSD make will enter it before
@@ -3854,7 +3853,7 @@ sub handle_gettext
 
   if (-d 'po')
     {
-      my @subdirs = $subdirs->value_as_list_recursive ('all');
+      my @subdirs = $subdirs->value_as_list_recursive;
 
       msg_var ('syntax', $subdirs,
               "AM_GNU_GETTEXT used but `po' not in SUBDIRS")
@@ -3904,8 +3903,7 @@ sub handle_footer
        # actual suffixes, and not $(SUFFIXES).  Some versions of make
        # do not like variable substitutions on the .SUFFIXES line.
        my @user_suffixes = ($suffixes
-                            ? $suffixes->value_as_list_recursive ('all')
-                            : ());
+                            ? $suffixes->value_as_list_recursive : ());
 
        my %suffixes = map { $_ => 1 } @suffixes;
        delete @suffixes{@user_suffixes};
@@ -6263,7 +6261,7 @@ sub am_install_var
 
       # Append actual contents of where_PRIMARY variable to
       # @result, skipping @substitutions@.
-      foreach my $locvals ($one_var->loc_and_value_as_list_recursive ('all'))
+      foreach my $locvals ($one_var->value_as_list_recursive (location => 1))
        {
          my ($loc, $value) = @$locvals;
          # Skip configure substitutions.
index 0cd72cc..4cf264a 100644 (file)
@@ -586,49 +586,35 @@ sub value_as_list ($$;$$)
   return @result;
 }
 
-=item C<@values = $var-E<gt>value_as_list_recursive ($cond)>
+=item C<@values = $var-E<gt>value_as_list_recursive ([%options])>
 
-Return the list of values of C<$var> and any subvariable in condition
-C<$cond>.
+Return the contents of C<$var> as a list, split on whitespace.  This
+will recursively follow C<$(...)> and C<${...}> inclusions.  It
+preserves C<@...@> substitutions.
 
-=cut
+C<%options> is a list of option for C<Variable::traverse_recursively>
+(see this method).  The most useful is C<cond_filter>:
 
-sub value_as_list_recursive ($$)
-{
-  return &_value_as_list_recursive_worker (@_, 0);
-}
+  $var->value_as_list_recursive (cond_filter => $cond)
 
-=item C<@values = $var-E<gt>loc_and_value_as_list_recursive ($cond)>
+will return the contents of C<$var> and any subvariable in all
+conditions implied by C<$cond>.
 
-Return the values of C<$var> and any subvariable in condition
-C<$cond> as a list of C<[$location, @values]> pairs.
+C<%options> can also carry options specific to C<value_as_list_recursive>.
+Presently, the only such option is C<location =E<gt> 1> which instructs
+C<value_as_list_recursive> to return a list of C<[$location, @values]> pairs.
 
 =cut
 
-sub loc_and_value_as_list_recursive ($$)
+sub value_as_list_recursive ($;%)
 {
-  return &_value_as_list_recursive_worker (@_, 1);
-}
-
-# @VALUE
-# &_value_as_list_recursive_worker ($VAR, $COND, $LOC_WANTED)
-# -----------------------------------------------------------
-# Return contents of VAR as a list, split on whitespace.  This will
-# 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
-# then only the value for that condition should be returned;
-# otherwise, warn if VAR is conditionally defined.  If $LOC_WANTED is set,
-# return a list of [$location, $value] instead of a list of values.
-sub _value_as_list_recursive_worker ($$$)
-{
-  my ($var, $cond_filter, $loc_wanted) = @_;
+  my ($var, %options) = @_;
 
   return $var->traverse_recursively
     (# Construct [$location, $value] pairs if requested.
      sub {
        my ($var, $val, $cond, $full_cond) = @_;
-       return [$var->rdef ($cond)->location, $val] if $loc_wanted;
+       return [$var->rdef ($cond)->location, $val] if $options{'location'};
        return $val;
      },
      # Collect results.
@@ -636,7 +622,7 @@ sub _value_as_list_recursive_worker ($$$)
        my ($var, $parent_cond, @allresults) = @_;
        return map { my ($cond, @vals) = @$_; return @vals } @allresults;
      },
-     $cond_filter);
+     %options);
 }
 
 
@@ -1207,12 +1193,14 @@ sub output_variables ()
   return $res;
 }
 
-=item C<$var-E<gt>traverse_recursively (&fun_item, &fun_collect, [$cond_filter])>
+=item C<$var-E<gt>traverse_recursively (&fun_item, &fun_collect, [cond_filter =E<gt> $cond_filter], [inner_expand =E<gt> 1])>
 
 Split the value of the Automake::Variable C<$var> on space, and
-traverse its components recursively.  If C<$cond_filter> is an
-C<Automake::Condition>, process any conditions which are true when
-C<$cond_filter> is true.  Otherwise, process all conditions.
+traverse its components recursively.
+
+If C<$cond_filter> is an C<Automake::Condition>, process any
+conditions which are true when C<$cond_filter> is true.  Otherwise,
+process all conditions.
 
 We distinguish two kinds of items in the content of C<$var>.
 Terms that look like C<$(foo)> or C<${foo}> are subvariables
@@ -1230,6 +1218,10 @@ following arguments:
                    conditions inherited from parent variables
                    during recursion
 
+If C<inner_expand> is set, variable references occuring in filename
+(as in C<$(BASE).ext>) are expansed before the filename is passed to
+C<&fun_item>.
+
 C<&fun_item> may return a list of items, they will be passed to
 C<&fun_store> later on.  Define C<&fun_item> as C<undef> when it serve
 no purpose, this will speed things up.
@@ -1258,21 +1250,24 @@ recursive calls).
 # substitutions currently in force.
 my @_substfroms;
 my @_substtos;
-sub traverse_recursively ($&&;$)
+sub traverse_recursively ($&&;%)
 {
   ++$_traversal;
   @_substfroms = ();
   @_substtos = ();
-  my ($var, $fun_item, $fun_collect, $cond_filter) = @_;
+  my ($var, $fun_item, $fun_collect, %options) = @_;
+  my $cond_filter = $options{'cond_filter'};
+  my $inner_expand = $options{'inner_expand'};
   return $var->_do_recursive_traversal ($var,
                                        $fun_item, $fun_collect,
-                                       $cond_filter, TRUE)
+                                       $cond_filter, TRUE, $inner_expand)
 }
 
 # The guts of Automake::Variable::traverse_recursively.
-sub _do_recursive_traversal ($$&&$$)
+sub _do_recursive_traversal ($$&&$$$)
 {
-  my ($var, $parent, $fun_item, $fun_collect, $cond_filter, $parent_cond) = @_;
+  my ($var, $parent, $fun_item, $fun_collect, $cond_filter, $parent_cond,
+      $inner_expand) = @_;
 
   $var->set_seen;
 
@@ -1300,8 +1295,11 @@ sub _do_recursive_traversal ($$&&$$)
        }
       my @result = ();
       my $full_cond = $cond->merge ($parent_cond);
-      foreach my $val ($var->value_as_list ($cond, $parent, $parent_cond))
+
+      my @to_process = $var->value_as_list ($cond, $parent, $parent_cond);
+      while (@to_process)
        {
+         my $val = shift @to_process;
          # If $val is a variable (i.e. ${foo} or $(bar), not a filename),
          # handle the sub variable recursively.
          # (Backslashes before `}' and `)' within brackets are here to
@@ -1335,13 +1333,54 @@ sub _do_recursive_traversal ($$&&$$)
                                                          $fun_item,
                                                          $fun_collect,
                                                          $cond_filter,
-                                                         $full_cond);
+                                                         $full_cond,
+                                                         $inner_expand);
              push (@result, @res);
 
              pop @_substfroms;
              pop @_substtos;
+
+             next;
            }
-         elsif ($fun_item) # $var is a filename we must process
+         # Try to expand variable references inside filenames such as
+         # `$(NAME).txt'.  We do not handle `:.foo=.bar'
+         # substitutions, but it would make little sense to use this
+         # here anyway.
+         elsif ($inner_expand
+                && ($val =~ /\$\{([^\}]*)\}/ || $val =~ /\$\(([^\)]*)\)/))
+           {
+             my $subvarname = $1;
+             my $subvar = var $subvarname;
+             if ($subvar)
+               {
+                 # Replace the reference by its value, and reschedule
+                 # for expansion.
+                 foreach my $c ($subvar->conditions->conds)
+                   {
+                     if (ref $cond_filter)
+                       {
+                         # Ignore conditions that don't match $cond_filter.
+                         next if ! $c->true_when ($cond_filter);
+                         # If we found out several definitions of $var
+                         # match $cond_filter then we are in trouble.
+                         # Tell the user we don't support this.
+                         $subvar->check_defined_unconditionally ($var,
+                                                                 $full_cond)
+                           if $cond_once;
+                         $cond_once = 1;
+                       }
+                     my $subval = $subvar->rdef ($c)->value;
+                     $val =~ s/\$\{$subvarname\}/$subval/g;
+                     $val =~ s/\$\($subvarname\)/$subval/g;
+                     unshift @to_process, split (' ', $val);
+                   }
+                 next;
+               }
+             # We do not know any variable with this name.  Fall through
+             # to filename processing.
+           }
+
+         if ($fun_item) # $var is a filename we must process
            {
              my $substnum=$#_substfroms;
              while ($substnum >= 0)
@@ -1423,9 +1462,9 @@ sub _gen_varname ($@)
   return $name;
 }
 
-=item C<$resvar = transform_variable_recursively ($var, $resvar, $base, $nodefine, $where, &fun_item)>
+=item C<$resvar = transform_variable_recursively ($var, $resvar, $base, $nodefine, $where, &fun_item, [%options])>
 
-=item C<$resvar = $var-E<gt>transform_variable_recursively ($resvar, $base, $nodefine, $where, &fun_item)>
+=item C<$resvar = $var-E<gt>transform_variable_recursively ($resvar, $base, $nodefine, $where, &fun_item, [%options])>
 
 Traverse C<$var> recursively, and create a C<$resvar> variable in
 which each filename in C<$var> have been transformed using
@@ -1447,11 +1486,14 @@ Arguments are:
 
 This returns the string C<"\$($RESVAR)">.
 
+C<%options> is a list of options to pass to
+C<Variable::traverse_recursively> (see this method).
+
 =cut
 
-sub transform_variable_recursively ($$$$$&)
+sub transform_variable_recursively ($$$$$&;%)
 {
-  my ($var, $resvar, $base, $nodefine, $where, $fun_item) = @_;
+  my ($var, $resvar, $base, $nodefine, $where, $fun_item, %options) = @_;
 
   $var = ref $var ? $var : rvar $var;
 
@@ -1485,7 +1527,8 @@ sub transform_variable_recursively ($$$$$&)
             }
         }
        return "\$($varname)";
-     });
+     },
+     %options);
   return $res;
 }
 
index 0234298..e466f92 100644 (file)
@@ -489,6 +489,7 @@ txinfo24.test \
 txinfo25.test \
 txinfo26.test \
 txinfo27.test \
+txinfo28.test \
 transform.test \
 unused.test \
 vars.test \
index 955568d..5ab156d 100644 (file)
@@ -603,6 +603,7 @@ txinfo24.test \
 txinfo25.test \
 txinfo26.test \
 txinfo27.test \
+txinfo28.test \
 transform.test \
 unused.test \
 vars.test \
diff --git a/tests/txinfo28.test b/tests/txinfo28.test
new file mode 100755 (executable)
index 0000000..4709ff0
--- /dev/null
@@ -0,0 +1,89 @@
+#! /bin/sh
+# Copyright (C) 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 Automake; see the file COPYING.  If not, write to
+# the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+
+# Check that info files are built in builddir when needed.
+# Similar to txinfo24.test, but obfuscating filenames with variable references.
+# Report from Ralf Corsepius.
+
+required='makeinfo tex'
+. ./defs || exit 1
+
+set -e
+
+echo AC_OUTPUT >> configure.in
+
+cat > Makefile.am << 'END'
+MA = ma
+IN = in
+PROJ = $(MA)$(IN)
+include fragment.mk
+info_TEXINFOS = ma$(IN).texi
+END
+
+echo 'CLEANFILES = $(PROJ).info' > fragment.mk
+
+cat > main.texi << 'END'
+\input texinfo
+@setfilename main.info
+@settitle main
+@node Top
+Hello walls.
+@include version.texi
+@bye
+END
+
+$ACLOCAL
+$AUTOMAKE --add-missing
+$AUTOCONF
+
+mkdir build
+cd build
+../configure
+$MAKE
+test -f main.info
+
+cd ..
+rm -rf build
+./configure
+$MAKE
+test -f main.info
+
+# Make sure stamp-vti is older that version.texi.
+# (A common situation in a real tree.)
+test -f stamp-vti
+test -f version.texi
+$sleep
+touch stamp-vti
+
+$MAKE distclean
+test -f stamp-vti
+test -f version.texi
+
+mkdir build
+cd build
+../configure
+$MAKE
+# main.info should be rebuilt in the current directory
+test -f main.info
+test ! -f ../main.info
+$MAKE dvi
+test -f main.dvi
+
+$MAKE distcheck