diff -u -r automake_patch1/ChangeLog automake_patch2/ChangeLog --- automake_patch1/ChangeLog Thu Aug 9 17:55:46 2001 +++ automake_patch2/ChangeLog Thu Aug 9 19:17:51 2001 @@ -1,5 +1,25 @@ 2001-08-09 Richard Boulton + * automake.in (handle_source_transform): Call + source_transform_variable() instead of calling + variable_value_as_list(), handle_single_transform_list() and + define_pretty_variable() directly. + (handle_single_transform_list): Add $topparent parameter, used for + error messages. Improved error message. + (source_transform_variable): New function. + (subobjname): New function. + (variable_conditions_nonrecursive): New function. + (variable_value_as_list_nonrecursive): New function. + (substfroms): New global. + (substtos): New global. + (substnums): New global. + * tests/cond3.test: Update to work with new method of defining _OBJECTS. + * tests/cond4.test: Update to work with new method of defining _OBJECTS. + * tests/sourcesub2.test: New test. + * tests/Makefile.am (TEST): Added sourcesub2.test. + +2001-08-09 Richard Boulton + * automake.in (handle_single_transform_list): Use new global, `%linkers_used', to store the linkers used, rather than an internal variable. Enables correct linker to be calculated across a group diff -u -r automake_patch1/automake.in automake_patch2/automake.in --- automake_patch1/automake.in Thu Aug 9 17:48:33 2001 +++ automake_patch2/automake.in Thu Aug 9 19:19:57 2001 @@ -646,12 +646,25 @@ # FIXME: This is a hack. a better switch should be found. my $get_object_extension_was_run; +# Contains a stack of `from' parts of variable substitutions currently in +# force. +my @substfroms; + +# Contains a stack of `to' parts of variable substitutions currently in +# force. +my @substtos; + +# Associates a variable name, together with a list of substitutions to be +# performed on it, with a number. Used to provide unique names for generated +# variables. +my %substnums = (); ## --------------------------------- ## ## Forward subroutine declarations. ## ## --------------------------------- ## sub register_language (%); sub file_contents_internal ($$%); +sub source_transform_variable ($$$$$$$); # &initialize_per_input () @@ -1736,18 +1749,19 @@ # @OBJECTS -# handle_single_transform_list ($VAR, $DERIVED, $OBJ, @FILES) -# ----------------------------------------------------------- +# handle_single_transform_list ($VAR, $TOPPARENT, $DERIVED, $OBJ, @FILES) +# ----------------------------------------------------------------------- # Does much of the actual work for handle_source_transform. # Arguments are: +# $VAR is the name of the variable that the source filenames come from +# $TOPPARENT is the name of the _SOURCES variable which is being processed # $DERIVED is the name of resulting executable or library # $OBJ is the object extension (e.g., `$U.lo') # @FILES is the list of source files to transform # Result is a list of the names of objects -# %linkers_used will be updated with any linkers needed -sub handle_single_transform_list ($$$@) +sub handle_single_transform_list ($$$$@) { - my ($var, $derived, $obj, @files) = @_; + my ($var, $topparent, $derived, $obj, @files) = @_; my @result = (); my $nonansi_obj = $obj; $nonansi_obj =~ s/\$U//g; @@ -1761,7 +1775,7 @@ # Configure substitutions in _SOURCES variables are errors. if (/address@hidden@$/) { - &am_line_error ($var, "$var includes configure substitution `$_'"); + &am_line_error ($var, "`$var' includes configure substitution `$_', and is referred to from `$topparent': configure substitutions not allowed in _SOURCES variables"); next; } @@ -2014,9 +2028,147 @@ } } - return @result; + return (@result); } +# $BOOL +# source_transform_variable ($VAR, $OBJVAR, $NODEFINE, $ONE_FILE, +# $OBJ, $PARENT, $TOPPARENT) +# --------------------------------------------------------------------- +# Define an _OBJECTS variable for a _SOURCES variable (or subvariable) +# +# Arguments are: +# $VAR is the name of the _SOURCES variable +# $OBJVAR is the name of the _OBJECTS +# $NODEFINE is a boolean: if true, $OBJVAR will not be defined (but +# work done to determine the linker will be). +# $ONE_FILE is the canonical (transformed) name of object to build +# $OBJ is the object extension (ie either `.o' or `$o'. +# $PARENT is the variable in which $VAR is used, or $VAR if not applicable. +# $TOPPARENT is the _SOURCES variable being processed. +# +# Result is a boolean, true if a linker is needed to deal with the objects. +# +# %linkers_used, %vars_scanned, @substfroms and @substtos should be cleared +# before use: +# %linkers_used variable will be set to contain the linkers desired. +# %vars_scanned will be used to check for recursive definitions. +# @substfroms and @substtos will be used to keep a stack of variable +# substitutions to be applied. +# +sub source_transform_variable ($$$$$$$) +{ + my ($var, $objvar, $nodefine, $one_file, $obj, $parent, $topparent) = @_; + + if (defined $vars_scanned{$var}) + { + &am_line_error ($var, "variable `$var' recursively defined"); + return ""; + } + $vars_scanned{$var} = 1; + + my $needlinker = ""; + foreach my $cond (&variable_conditions_nonrecursive ($var)) + { + my @result; + foreach my $val (&variable_value_as_list_nonrecursive ($var, $cond, $parent)) + { + if ($val =~ /^\$\{([^}]*)\}$/ || $val =~ /^\$\(([^)]*)\)$/) + { + # Handle a sub variable + my $subvar = $1; + + # If the user uses a losing variable name, just ignore it. + # This isn't ideal, but people have requested it. + next if ($subvar =~ /address@hidden@/); + + # See if the variable is actually a substitution reference + my ($from, $to); + my @temp_list; + if ($subvar =~ /$SUBST_REF_PATTERN/o) + { + $subvar = $1; + $to = $3; + ($from = $2) =~ s/(\W)/\\$1/g; + } + push @substfroms, $from; + push @substtos, $to; + + my $subobjvar = &subobjname($subvar); + push (@result, '$('. $subobjvar . ')'); + + my $temp = source_transform_variable ($subvar, $subobjvar, + $nodefine, $one_file, + $obj, $var, $topparent); + $needlinker ||= $temp; + + pop @substfroms; + pop @substtos; + } + else + { + my $substnum=$#substfroms; + while ($substnum >= 0) + { + $val =~ s/$substfroms[$substnum]$/$substtos[$substnum]/ + if defined $substfroms[$substnum]; + $substnum -= 1; + } + + my (@transformed) = + &handle_single_transform_list ($var, $topparent, $one_file, $obj, $val); + push (@result, @transformed); + $needlinker = "true" if @transformed; + } + } + + # Define _OBJECTS conditionally. + &define_pretty_variable ($objvar, $cond, (@result)) + unless $nodefine; + } + + delete $vars_scanned{$var}; + return $needlinker; +} + +# $OBJNAME +# subobjname ($VARNAME) +# --------------------------------------------------------------------- +# Return a name for an object variable. +# +# Arguments are: +# $VARNAME is the name of the variable the object variable is being +# generated from. +# +# This function also looks at @substfroms and @substtos to determine any +# substitutions to be performed on the object variable. +# +# The name returned is unique for the combination of $varname and +# substitutions to be performed. +sub subobjname($) +{ + my ($varname) = @_; + my $key = $varname; + my $substnum=$#substfroms; + while ($substnum >= 0) + { + if (defined $substfroms[$substnum] && + ($substfroms[$substnum] || $substtos[$substnum])) + { + $key .= ":" . $substfroms[$substnum] . "=" . $substtos[$substnum]; + } + $substnum -= 1; + } + + my $num = $substnums{$key}; + if (! $num) + { + $num = keys(%substnums) + 1; + $substnums{$key} = $num; + } + + return "am_OBJECTS_$num"; +} # Handle SOURCE->OBJECT transform for one program or library. @@ -2064,20 +2216,15 @@ push (@sources, '$(' . $prefix . $one_file . "_SOURCES)"); push (@dist_sources, '$(' . $prefix . $one_file . "_SOURCES)") unless $prefix =~ /^nodist_/; - foreach my $cond (variable_conditions ($var)) - { - my @files = &variable_value_as_list ($var, $cond); - my (@result) = - &handle_single_transform_list ($var, $one_file, $obj, - @files); - # If there are no files to compile, don't require a linker (yet). - $needlinker ||= "true" if @result; - # Define _OBJECTS conditionally. - &define_pretty_variable ($xpfx . $one_file . '_OBJECTS', - $cond, @result) - unless $prefix =~ /EXTRA_/; - } + @substfroms = (); + @substtos = (); + %vars_scanned = (); + my $temp = source_transform_variable ($var, + $xpfx . $one_file . '_OBJECTS', + $prefix =~ /EXTRA_/, + $one_file, $obj, $var, $var); + $needlinker ||= $temp; } if ($needlinker) { $linker ||= &resolve_linker (%linkers_used); @@ -2093,6 +2240,7 @@ %linkers_used = (); my (@result) = &handle_single_transform_list ($one_file . '_SOURCES', + $one_file . '_SOURCES', $one_file, $obj, "$unxformed.c"); $linker ||= &resolve_linker (%linkers_used); @@ -5849,6 +5997,20 @@ return @uniq_list; } +# @CONDS +# variable_conditions_nonrecursive ($VAR) +# --------------------------------------- +# Get the list of conditions that a variable is defined with, without +# recursing through the conditions of any subvariables. +# Argument is $VAR: the variable to get the conditions of. +# Returns the list of conditions. +sub variable_conditions_nonrecursive ($) +{ + my ($var) = @_; + my @conds = keys %{$var_value{$var}}; + return @conds; +} + # $BOOLEAN # &variable_conditionally_defined ($VAR) @@ -6144,6 +6306,69 @@ else { push (@result, $_); + } + } + + return @result; +} + +# @VALUES +# variable_value_as_list_nonrecursive ($VAR, $COND, $PARENT) +# ---------------------------------------------------------- +# Get the value of a variable given a specified condition. without +# recursing through any subvariables. +# Arguments are: +# $VAR is the variable +# $COND is the condition. If this is not given, the value for the +# "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_nonrecursive +{ + my ($var, $cond, $parent) = @_; + my @result; + + # Check defined + if (! defined $var_value{$var}) + { + if (defined $targets{$var}) + { + &am_line_error ($var, "`$var' is a target; expected a variable"); + } + else + { + &am_line_error ($parent, "variable `$var' not defined"); + } + } + + # Get value for given condition + $cond ||= 'TRUE'; + my $onceflag; + foreach my $vcond (keys %{$var_value{$var}}) + { + my $val = $var_value{$var}{$vcond}; + + if (&conditional_true_when ($vcond, $cond)) + { + # Unless variable is not defined conditionally, there should only + # be one value of $vcond true when $cond. + &check_variable_defined_unconditionally ($var, $parent) + if $onceflag; + $onceflag = 1; + + # Strip backslashes + $val =~ s/\\(\n|$)/ /g; + + foreach (split (' ', $val)) + { + # If a comment seen, just leave. + last if /^#/; + + push (@result, $_); + } } } diff -u -r automake_patch1/tests/Makefile.am automake_patch2/tests/Makefile.am --- automake_patch1/tests/Makefile.am Thu Aug 9 17:22:54 2001 +++ automake_patch2/tests/Makefile.am Thu Aug 9 18:06:38 2001 @@ -257,6 +257,7 @@ seenc.test \ sinclude.test \ sourcesub.test \ +sourcesub2.test \ space.test \ specflags.test \ specflags2.test \ diff -u -r automake_patch1/tests/Makefile.in automake_patch2/tests/Makefile.in --- automake_patch1/tests/Makefile.in Thu Aug 9 17:23:20 2001 +++ automake_patch2/tests/Makefile.in Thu Aug 9 18:06:39 2001 @@ -325,6 +325,7 @@ seenc.test \ sinclude.test \ sourcesub.test \ +sourcesub2.test \ space.test \ specflags.test \ specflags2.test \ diff -u -r automake_patch1/tests/cond3.test automake_patch2/tests/cond3.test --- automake_patch1/tests/cond3.test Mon Apr 9 17:02:40 2001 +++ automake_patch2/tests/cond3.test Wed Aug 8 20:39:13 2001 @@ -43,7 +43,7 @@ # `b top' so that sed -n ' -/am_targ_OBJECTS =/ { +/OBJECT.* =/ { : loop /\\$/ { p @@ -53,20 +53,15 @@ p }' Makefile.in >produced - cat >expected << 'EOF' address@hidden@@THREE_FALSE@@address@hidden = two.$(OBJEXT) address@hidden@@THREE_FALSE@@address@hidden = address@hidden@@THREE_TRUE@@address@hidden = two.$(OBJEXT) \ address@hidden@@THREE_TRUE@@TWO_TRUE@ three.$(OBJEXT) address@hidden@@THREE_TRUE@@address@hidden = three.$(OBJEXT) address@hidden@@THREE_FALSE@@address@hidden = one.$(OBJEXT) \ address@hidden@@THREE_FALSE@@TWO_TRUE@ two.$(OBJEXT) address@hidden@@THREE_FALSE@@address@hidden = one.$(OBJEXT) address@hidden@@THREE_TRUE@@address@hidden = one.$(OBJEXT) \ address@hidden@@THREE_TRUE@@TWO_TRUE@ two.$(OBJEXT) three.$(OBJEXT) address@hidden@@THREE_TRUE@@address@hidden = one.$(OBJEXT) \ address@hidden@@THREE_TRUE@@TWO_FALSE@ three.$(OBJEXT) address@hidden@am_OBJECTS_1 = address@hidden@am_OBJECTS_1 = one.$(OBJEXT) address@hidden@am_OBJECTS_2 = address@hidden@am_OBJECTS_2 = two.$(OBJEXT) address@hidden@am_OBJECTS_3 = three.$(OBJEXT) address@hidden@am_OBJECTS_3 = +am_targ_OBJECTS = $(am_OBJECTS_1) $(am_OBJECTS_2) $(am_OBJECTS_3) +targ_OBJECTS = $(am_targ_OBJECTS) EOF diff expected produced || exit 1 diff -u -r automake_patch1/tests/cond4.test automake_patch2/tests/cond4.test --- automake_patch1/tests/cond4.test Wed Aug 8 18:40:08 2001 +++ automake_patch2/tests/cond4.test Wed Aug 8 19:27:14 2001 @@ -34,7 +34,7 @@ $ACLOCAL || exit 1 $AUTOMAKE || exit 1 -test "`grep TWO_FALSE Makefile.in | wc -l`" -eq 2 || exit 1 +test "`grep TWO_FALSE Makefile.in | wc -l`" -eq 0 || exit 1 $AUTOCONF || exit 1 (gcc -v) > /dev/null 2>&1 || exit 77 diff -u -r automake_patch1/tests/sourcesub2.test automake_patch2/tests/sourcesub2.test --- automake_patch1/tests/sourcesub2.test Thu Jan 1 01:00:00 1970 +++ automake_patch2/tests/sourcesub2.test Thu Aug 9 18:08:52 2001 @@ -0,0 +1,21 @@ +#! /bin/sh + +# Test to make sure config sub in _SOURCES fails. + +. $srcdir/defs || exit 1 + +cat >> configure.in << 'END' +AC_PROG_CC +END + +cat > Makefile.am << 'END' +bin_PROGRAMS = x +bar = @FOO@ +foo = $(bar) +x_SOURCES = x.c $(foo) +EXTRA_x_SOURCES = y.c +END + +$ACLOCAL || exit 1 +$AUTOMAKE && exit 1 +exit 0