From: Alexandre Duret-Lutz Date: Sat, 29 Nov 2003 23:47:02 +0000 (+0000) Subject: * lib/Automake/Variable.pm (loc_and_value_as_list_recursive, X-Git-Tag: Release-1-7h~5 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=0a1c8dcb1b48fbed5497392df29c2593c141e394;p=thirdparty%2Fautomake.git * 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. --- diff --git a/ChangeLog b/ChangeLog index 36208e046..e0e1e44c8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,25 @@ 2003-11-29 Alexandre Duret-Lutz + * 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. diff --git a/automake.in b/automake.in index 94d9ed70e..cc29348d6 100755 --- a/automake.in +++ b/automake.in @@ -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. diff --git a/lib/Automake/Variable.pm b/lib/Automake/Variable.pm index 0cd72cced..4cf264abd 100644 --- a/lib/Automake/Variable.pm +++ b/lib/Automake/Variable.pm @@ -586,49 +586,35 @@ sub value_as_list ($$;$$) return @result; } -=item C<@values = $var-Evalue_as_list_recursive ($cond)> +=item C<@values = $var-Evalue_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 +(see this method). The most useful is C: -sub value_as_list_recursive ($$) -{ - return &_value_as_list_recursive_worker (@_, 0); -} + $var->value_as_list_recursive (cond_filter => $cond) -=item C<@values = $var-Eloc_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. +Presently, the only such option is C 1> which instructs +C 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-Etraverse_recursively (&fun_item, &fun_collect, [$cond_filter])> +=item C<$var-Etraverse_recursively (&fun_item, &fun_collect, [cond_filter =E $cond_filter], [inner_expand =E 1])> Split the value of the Automake::Variable C<$var> on space, and -traverse its components recursively. If C<$cond_filter> is an -C, 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, 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 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 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-Etransform_variable_recursively ($resvar, $base, $nodefine, $where, &fun_item)> +=item C<$resvar = $var-Etransform_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 (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; } diff --git a/tests/Makefile.am b/tests/Makefile.am index 0234298f6..e466f923a 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -489,6 +489,7 @@ txinfo24.test \ txinfo25.test \ txinfo26.test \ txinfo27.test \ +txinfo28.test \ transform.test \ unused.test \ vars.test \ diff --git a/tests/Makefile.in b/tests/Makefile.in index 955568d13..5ab156d82 100644 --- a/tests/Makefile.in +++ b/tests/Makefile.in @@ -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 index 000000000..4709ff0fd --- /dev/null +++ b/tests/txinfo28.test @@ -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