For PR automake/347:
authorAlexandre Duret-Lutz <adl@gnu.org>
Fri, 23 Aug 2002 13:32:55 +0000 (13:32 +0000)
committerAlexandre Duret-Lutz <adl@gnu.org>
Fri, 23 Aug 2002 13:32:55 +0000 (13:32 +0000)
* automake.in (MACRO_PATTERN): Allow `.' in variable names.
(scan_variable_expansions, check_variable_expansions): New functions.
(macro_define): Call check_variable_expansions.
(read_am_file): Likewise, when outputing rules.
(variable_conditions_recursive_sub): Simplify using
scan_variable_expansions.
* tests/vars3.test: New file.
* tests/Makefile.am (TESTS): Add vars3.test.
* tests/colneq.test: Use -Wno-portability.

ChangeLog
automake.in
tests/Makefile.am
tests/Makefile.in
tests/colneq.test
tests/vars3.test [new file with mode: 0755]

index 0e962ff8b3d87c514156aefa3203331ce817024c..ac54725f43c038d0b5dd3d232dc8a365f8245550 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,16 @@
 2002-08-23  Alexandre Duret-Lutz  <duret_g@epita.fr>
 
+       For PR automake/347:
+       * automake.in (MACRO_PATTERN): Allow `.' in variable names.
+       (scan_variable_expansions, check_variable_expansions): New functions.
+       (macro_define): Call check_variable_expansions.
+       (read_am_file): Likewise, when outputing rules.
+       (variable_conditions_recursive_sub): Simplify using
+       scan_variable_expansions.
+       * tests/vars3.test: New file.
+       * tests/Makefile.am (TESTS): Add vars3.test.
+       * tests/colneq.test: Use -Wno-portability.
+
        * lib/Automake/Channels.pm (buffering, backlog): New variables.
        (buffer_messages, flush_messages): New functions.
        (@EXPORT): Add buffer_messages and flush_messages.
index ddad1e3b1b818dcc4bc12bacb26be8a1c150f237..302a736e47d3241d129252bde24ed43bb271d4e2 100755 (executable)
@@ -156,7 +156,7 @@ my $SUFFIX_RULE_PATTERN =
 # Only recognize leading spaces, not leading tabs.  If we recognize
 # leading tabs here then we need to make the reader smarter, because
 # otherwise it will think rules like `foo=bar; \' are errors.
-my $MACRO_PATTERN = '^[A-Za-z0-9_@]+' . "\$";
+my $MACRO_PATTERN = '^[.A-Za-z0-9_@]+' . "\$";
 my $ASSIGNMENT_PATTERN = '^ *([^ \t=:+]*)\s*([:+]?)=\s*(.*)' . "\$";
 # This pattern recognizes a Gnits version id and sets $1 if the
 # release is an alpha release.  We also allow a suffix which can be
@@ -1337,10 +1337,10 @@ sub accept_extensions (@)
 
 # var_SUFFIXES_trigger ($TYPE, $VALUE)
 # ------------------------------------
-# This is called automagically by define_macro() when SUFFIXES
+# This is called automagically by macro_define() when SUFFIXES
 # is defined ($TYPE eq '') or appended ($TYPE eq '+').
 # The work here needs to be performed as a side-effect of the
-# define_macro() call because SUFFIXES definitions impact
+# macro_define() call because SUFFIXES definitions impact
 # on $KNOWN_EXTENSIONS_PATTERN, and $KNOWN_EXTENSIONS_PATTERN
 # are used when parsing the input am file.
 sub var_SUFFIXES_trigger ($$)
@@ -3402,8 +3402,7 @@ sub handle_ltlibraries
     }
 }
 
-# See if any _SOURCES variable were misspelled.  Also, make sure that
-# EXTRA_ variables don't contain configure substitutions.
+# See if any _SOURCES variable were misspelled.
 sub check_typos ()
 {
   # It is ok if the user sets this particular variable.
@@ -6169,6 +6168,8 @@ sub macro_define ($$$$$$)
        "$var: variable names starting with `_' are not portable")
     if $var =~ /^_/;
 
+  check_variable_expansions ($value, $where);
+
   $cond ||= 'TRUE';
 
   # An Automake variable must be consistently defined with the same
@@ -6573,7 +6574,56 @@ sub variable_conditionally_defined ($)
     return 0;
 }
 
+# @LIST
+# &scan_variable_expansions ($TEXT)
+# ---------------------------------
+# Return the list of variable names expanded in $TEXT.
+# Note that unlike some other functions, $TEXT is not split
+# on spaces before we check for subvariables.
+sub scan_variable_expansions ($)
+{
+  my ($text) = @_;
+  my @result = ();
+
+  # Strip comments.
+  $text =~ s/#.*$//;
+
+  # Record each use of ${stuff} or $(stuff) that do not follow a $.
+  while ($text =~ /(?<!\$)\$(?:\{([^\}]*)\}|\(([^\)]*)\))/g)
+    {
+      my $var = $1 || $2;
+      # The occurent may look like $(string1[:subst1=[subst2]]) but
+      # we want only `string1'.
+      $var =~ s/:[^:=]*=[^=]*$//;
+      push @result, $var;
+    }
 
+  return @result;
+}
+
+# &check_variable_expansions ($TEXT, $WHERE)
+# ------------------------------------------
+# Check variable expansions in $TEXT and warn about any name that
+# does not conform to POSIX.  $WHERE is the location of $TEXT for
+# the error message.
+sub check_variable_expansions ($$)
+{
+  my ($text, $where) = @_;
+  # Catch expansion of variables whose name does not conform to POSIX.
+  foreach my $var (scan_variable_expansions ($text))
+    {
+      if ($var !~ /$MACRO_PATTERN/)
+       {
+         # If the variable name contains a space, it's likely
+         # to be a GNU make extension (such as $(addsuffix ...)).
+         # Mention this in the diagnostic.
+         my $gnuext = "";
+         $gnuext = "\n(probably a GNU make extension)" if $var =~ / /;
+         msg ('portability', $where,
+              "$var: non-POSIX variable name$gnuext");
+       }
+    }
+}
 
 # &variable_conditions_recursive_sub ($VAR, $PARENT)
 # -------------------------------------------------------
@@ -6595,50 +6645,41 @@ sub variable_conditions_recursive_sub
     # Examine every condition under which $VAR is defined.
     foreach my $vcond (keys %{$var_value{$var}})
     {
-       push (@this_conds, $vcond);
+      push (@this_conds, $vcond);
 
-       # If $VAR references some other variable, then compute the
-       # conditions for that subvariable.
-       my @subvar_conds = ();
-       foreach (split (' ', $var_value{$var}{$vcond}))
+      # If $VAR references some other variable, then compute the
+      # conditions for that subvariable.
+      my @subvar_conds = ();
+      foreach my $varname (scan_variable_expansions $var_value{$var}{$vcond})
        {
-           # If a comment seen, just leave.
-           last if /^#/;
-
-           # Handle variable substitutions.
-           if (/^\$\{(.*)\}$/ || /^\$\((.*)\)$/)
+         if ($varname =~ /$SUBST_REF_PATTERN/o)
            {
-               my $varname = $1;
-               if ($varname =~ /$SUBST_REF_PATTERN/o)
-               {
-                   $varname = $1;
-               }
-
+             $varname = $1;
+           }
 
-               # Here we compute all the conditions under which the
-               # subvariable is defined.  Then we go through and add
-               # $VCOND to each.
-               my @svc = variable_conditions_recursive_sub ($varname, $var);
-               foreach my $item (@svc)
-               {
-                   my $val = conditional_string ($vcond, split (' ', $item));
-                   $val ||= 'TRUE';
-                   push (@subvar_conds, $val);
-               }
+         # Here we compute all the conditions under which the
+         # subvariable is defined.  Then we go through and add
+         # $VCOND to each.
+         my @svc = variable_conditions_recursive_sub ($varname, $var);
+         foreach my $item (@svc)
+           {
+             my $val = conditional_string ($vcond, split (' ', $item));
+             $val ||= 'TRUE';
+             push (@subvar_conds, $val);
            }
        }
 
-       # If there are no conditional subvariables, then we want to
-       # return this condition.  Otherwise, we want to return the
-       # permutations of the subvariables, taking into account the
-       # conditions of $VAR.
-       if (! @subvar_conds)
+      # If there are no conditional subvariables, then we want to
+      # return this condition.  Otherwise, we want to return the
+      # permutations of the subvariables, taking into account the
+      # conditions of $VAR.
+      if (! @subvar_conds)
        {
-           push (@new_conds, $vcond);
+         push (@new_conds, $vcond);
        }
-       else
+      else
        {
-           push (@new_conds, variable_conditions_reduce (@subvar_conds));
+         push (@new_conds, variable_conditions_reduce (@subvar_conds));
        }
     }
 
@@ -7483,6 +7524,7 @@ sub read_am_file ($)
            $prev_state = IN_RULE_DEF;
 
            rule_define ($1, 0, $cond, $here);
+           check_variable_expansions ($_, $here);
 
            $output_trailer .= $comment . $spacing;
             $output_trailer .= &make_condition (@cond_stack);
@@ -7545,6 +7587,7 @@ sub read_am_file ($)
            # This isn't an error; it is probably a continued rule.
            # In fact, this is what we assume.
            $prev_state = IN_RULE_DEF;
+           check_variable_expansions ($_, $here);
            $output_trailer .= $comment . $spacing;
            $output_trailer .= &make_condition  (@cond_stack);
            $output_trailer .= $_;
index e6b2f2f9c1ad08896ff1af578572749e7b5172c6..2910477dc38cddde7d6b5e7dbbbb10599dfdf051 100644 (file)
@@ -392,6 +392,7 @@ transform.test \
 unused.test \
 vars.test \
 vars2.test \
+vars3.test \
 vartar.test \
 version.test \
 version2.test \
index b9fe3207fe1a95451aaa579b5576671ebb8af477..d19ac2825dca6867766152c554420aa5d9c33988 100644 (file)
@@ -52,6 +52,7 @@ INSTALL_SCRIPT = @INSTALL_SCRIPT@
 INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
 LIBS = @LIBS@
 LN = @LN@
+LTLIBOBJS = @LTLIBOBJS@
 MAKEINFO = @MAKEINFO@
 PACKAGE = @PACKAGE@
 PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
@@ -479,6 +480,7 @@ transform.test \
 unused.test \
 vars.test \
 vars2.test \
+vars3.test \
 vartar.test \
 version.test \
 version2.test \
index 23ec0d0b7367176f760813cf87492990ed0b1d2c..353154bc4ee22f35ae24c5224a7fd890c4dd1d9a 100755 (executable)
@@ -5,6 +5,7 @@
 . $srcdir/defs || exit 1
 
 cat > Makefile.am << 'END'
+AUTOMAKE_OPTIONS = -Wno-portability
 ICONS := $(wildcard *.xbm)
 data_DATA = $(ICONS)
 END
diff --git a/tests/vars3.test b/tests/vars3.test
new file mode 100755 (executable)
index 0000000..b7463ce
--- /dev/null
@@ -0,0 +1,69 @@
+#! /bin/sh
+
+# Check that Automake warns about variables containing spaces
+# and other non-POSIX characters.
+
+. $srcdir/defs || exit 1
+
+set -e
+
+cat >Makefile.am <<'EOF'
+L01 = $(shell echo *)
+L02 = $$(not an error)
+L03 = $$(this is)$${ok too}
+L04 = $(nextvariableisbad)$(addsuffix .a, $(A))
+L05 = "$(bad boy)"
+L06 = $(this:is= ok)
+L07 = ${three errors}${on this} $(long line)
+L08$(o u c h): $(wildcard *.c)
+       ${another error}
+       echo $${ok-this is}
+L11: $(thisis) $(ok)
+       ${here}
+EOF
+
+$ACLOCAL
+# Make sure this warning is print in the `portability' category.
+$AUTOMAKE --warnings=no-error,none,portability 2>stderr
+cat stderr
+
+# Lines number are printed in error message.
+# Use them to make sure errors are diagnosed against the right lines.
+
+# No error expected for these lines.
+grep 1: stderr
+grep 2: stderr && exit 1
+grep 3: stderr && exit 1
+grep 4: stderr
+grep 5: stderr
+grep 6: stderr && exit 1
+grep 7: stderr
+grep 8: stderr
+grep 9: stderr
+grep 10: stderr && exit 1
+grep 11: stderr && exit 1
+grep 12: stderr && exit 1
+
+# Now check some individual values.
+grep 'shell echo' stderr
+grep 'nextvariableisbad' stderr && exit 1
+grep 'addsuffix' stderr
+grep 'bad boy' stderr
+grep 'ok' stderr && exit 1
+grep 'three errors' stderr
+grep 'on this' stderr
+grep 'long line' stderr
+grep 'o u c h' stderr
+grep 'wildcard' stderr
+grep 'another error' stderr
+grep 'thisis' stderr && exit 1
+grep 'here' stderr && exit 1
+
+# None of these errors be diagnosed with -Wno-portability
+$AUTOMAKE -Wno-portability
+
+# Likewise if we add this in the Makefile.am
+# (although this makes some difference internally: AUTOMAKE_OPTIONS is
+# processed far later).
+echo 'AUTOMAKE_OPTIONS = -Wno-portability' >> Makefile.am
+$AUTOMAKE