automake-patches
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

FYI: more locations (PR/360) + question


From: Alexandre Duret-Lutz
Subject: FYI: more locations (PR/360) + question
Date: 29 Sep 2002 14:48:15 +0200
User-agent: Gnus/5.0808 (Gnus v5.8.8) Emacs/20.7

I'm installing this (on HEAD).

The main change is that errors occuring during &handle_programs, 
&handle_libraries, or &handle_ltlibaries will display context
such as
   Makefile.am:4:   while processing program `foo'

with `Makefile.am:4:' being the location of the *_PROGRAMS variable
that contains foo.

This is possible because am_install_var now returns a list of
[$location, $value] pairs.  (I have resisted the temptation to
have a global %value_to_location hash and continue to return a
list of values.  Enventually I'd like the 
`[$location, $value]' pair to be an object, so it's better to
not introduce globals.)

This change to am_install_var also allow us to point to the
ligne in Makefile.am that cause programs like elisp-comp or
py-compile to be installed.


location.test is a good example to illustrate the changes.  Makefile.am
contains the following horror:

  bin_PROGRAMS = libfoo.a
  if COND2
    lib_LIBRARIES = libfoo.a
  endif
  if COND1
    bin_PROGRAMS += ctags
  endif

automake-1.7 says
----------
automake-1.7: libfoo_a_OBJECTS should not be defined
automake-1.7: use `libfoo_a_LDADD', not `libfoo_a_LIBADD'
libfoo.a: deprecated feature: `libfoo.a' overrides `libfoo.a$(EXEEXT)'
libfoo.a: change your target to read `libfoo.a$(EXEEXT)'
/home/adl/usr/share/automake-1.7/am/tags.am: redefinition of `ctags'...
/home/adl/usr/share/automake-1.7/am/program.am: ... `ctags' previously defined 
here.
----------

After the patch you get some context (plus a warning about the 
redefinition of libfoo.a).
----------
internal: libfoo_a_OBJECTS should not be defined
Makefile.am:3:   while processing library `libfoo.a'
internal: use `libfoo_a_LDADD', not `libfoo_a_LIBADD'
Makefile.am:3:   while processing library `libfoo.a'
/home/adl/projs/cvs/automake/HEAD2/tests/../lib/am/library.am: deprecated 
feature: target `libfoo.a' overrides `libfoo.a$(EXEEXT)'
/home/adl/projs/cvs/automake/HEAD2/tests/../lib/am/library.am: change your 
target to read `libfoo.a$(EXEEXT)'
Makefile.am:3:   while processing library `libfoo.a'
/home/adl/projs/cvs/automake/HEAD2/tests/../lib/am/program.am: target 
`libfoo.a$(EXEEXT)' was defined here
Makefile.am:1:   while processing program `libfoo.a'
/home/adl/projs/cvs/automake/HEAD2/tests/../lib/am/program.am: redefinition of 
`libfoo.a'...
Makefile.am:1:   while processing program `libfoo.a'
/home/adl/projs/cvs/automake/HEAD2/tests/../lib/am/library.am: ... `libfoo.a' 
previously defined here
Makefile.am:3:   while processing library `libfoo.a'
/home/adl/projs/cvs/automake/HEAD2/tests/../lib/am/tags.am: redefinition of 
`ctags'...
/home/adl/projs/cvs/automake/HEAD2/tests/../lib/am/program.am: ... `ctags' 
previously defined here
Makefile.am:6:   while processing program `ctags'
----------

Now I'm open to suggestions about how these diagnostics could be
output in a way which is more readable.  Would it be better to
add a new line between each diagnostic, as follow?

----------
internal: libfoo_a_OBJECTS should not be defined
Makefile.am:3:   while processing library `libfoo.a'

internal: use `libfoo_a_LDADD', not `libfoo_a_LIBADD'
Makefile.am:3:   while processing library `libfoo.a'

/home/adl/projs/cvs/automake/HEAD2/tests/../lib/am/library.am: deprecated 
feature: target `libfoo.a' overrides `libfoo.a$(EXEEXT)'
/home/adl/projs/cvs/automake/HEAD2/tests/../lib/am/library.am: change your 
target to read `libfoo.a$(EXEEXT)'
Makefile.am:3:   while processing library `libfoo.a'
/home/adl/projs/cvs/automake/HEAD2/tests/../lib/am/program.am: target 
`libfoo.a$(EXEEXT)' was defined here
Makefile.am:1:   while processing program `libfoo.a'

/home/adl/projs/cvs/automake/HEAD2/tests/../lib/am/program.am: redefinition of 
`libfoo.a'...
Makefile.am:1:   while processing program `libfoo.a'
/home/adl/projs/cvs/automake/HEAD2/tests/../lib/am/library.am: ... `libfoo.a' 
previously defined here
Makefile.am:3:   while processing library `libfoo.a'

/home/adl/projs/cvs/automake/HEAD2/tests/../lib/am/tags.am: redefinition of 
`ctags'...
/home/adl/projs/cvs/automake/HEAD2/tests/../lib/am/program.am: ... `ctags' 
previously defined here
Makefile.am:6:   while processing program `ctags'
----------

Note, the patch is in `diff -b' format because I've reindented a
couple of large functions.

2002-09-29  Alexandre Duret-Lutz  <address@hidden>

        For PR automake/360:  Propagate more locations.
        * automake.in (handle_programs): Adjust usage of am_install_var's
        return value.  Pass on locations as context to file_contents.
        (handle_libraries, handle_ltlibraries): Likewise.  Use locations
        in the 'not a standard library name' diagnostic.
        (handle_emacs_lisp, handle_python): Adjust usage of am_install_var's
        return value.  Pass on locations to require_variables and
        require_conf_file.
        (check_ambiguous_conditional): Strip trailing dot in message.
        (value_to_list): Add the $WHERE and $LOC_WANTED arguments.
        (variable_value_as_list_recursive_worker): Add the $LOC_WANTED
        argument.  Adjust calls to value_to_list.
        (variable_value_as_list_recursive): Call
        variable_value_as_list_recursive_worker with $LOC_WANTED = 0.
        (variable_loc_and_value_as_list_recursive): New function,
        variable_value_as_list_recursive_worker with $LOC_WANTED = 1.
        (am_install_var): Use variable_loc_and_value_as_list_recursive,
        and return a list of [$location, $value] pairs.
        (rule_define): Use better locations in EXEEXT diagnostic.
        (handle_source_transform, define_objects_from_sources): Add and use
        a $WHERE argument.  Adjust callers.
        * tests/stdlib.test: Grep the location in error message.
        * tests/location.test: New file.
        * tests/Makefile.am (TESTS): Add location.test.

Index: automake.in
===================================================================
RCS file: /cvs/automake/automake/automake.in,v
retrieving revision 1.1367
diff -u -b -r1.1367 automake.in
--- automake.in 29 Sep 2002 10:35:03 -0000      1.1367
+++ automake.in 29 Sep 2002 12:45:16 -0000
@@ -704,7 +704,7 @@
 ## --------------------------------- ##
 sub register_language (%);
 sub file_contents_internal ($$$%);
-sub define_objects_from_sources ($$$$$$$);
+sub define_objects_from_sources ($$$$$$$$);
 
 
 # &initialize_per_input ()
@@ -2596,7 +2596,7 @@
 
 # ($LINKER, $OBJVAR)
 # define_objects_from_sources ($VAR, $OBJVAR, $NODEFINE, $ONE_FILE,
-#                              $OBJ, $PARENT, $TOPPARENT)
+#                              $OBJ, $PARENT, $TOPPARENT, $WHERE)
 # ---------------------------------------------------------------------
 # Define an _OBJECTS variable for a _SOURCES variable (or subvariable)
 #
@@ -2610,6 +2610,7 @@
 #   $OBJ is the object extension (ie either `.o' or `.lo').
 #   $PARENT is the variable in which $VAR is used, or $VAR if not applicable.
 #   $TOPPARENT is the _SOURCES variable being processed.
+#   $WHERE context into which this definition is done
 #
 # Result is a pair ($LINKER, $OBJVAR):
 #    $LINKER is a boolean, true if a linker is needed to deal with the objects,
@@ -2622,9 +2623,10 @@
 #   @substfroms and @substtos will be used to keep a stack of variable
 #   substitutions to be applied.
 #
-sub define_objects_from_sources ($$$$$$$)
+sub define_objects_from_sources ($$$$$$$$)
 {
-    my ($var, $objvar, $nodefine, $one_file, $obj, $parent, $topparent) = @_;
+    my ($var, $objvar, $nodefine, $one_file, $obj,
+       $parent, $topparent, $where) = @_;
 
     if (defined $vars_scanned{$var})
     {
@@ -2665,7 +2667,8 @@
                my ($temp, $varname)
                    = define_objects_from_sources ($subvar, undef,
                                                   $nodefine, $one_file,
-                                                  $obj, $var, $topparent);
+                                                  $obj, $var, $topparent,
+                                                  $where);
 
                push (@result, '$('. $varname . ')');
                $needlinker ||= $temp;
@@ -2699,7 +2702,7 @@
        foreach my $pair (@allresults)
        {
            my ($cond, @result) = @$pair;
-           define_pretty_variable ($objvar, $cond, INTERNAL, @result);
+           define_pretty_variable ($objvar, $cond, $where, @result);
        }
     }
 
@@ -2771,7 +2774,7 @@
 {
     # one_file is canonical name.  unxformed is given name.  obj is
     # object extension.
-    my ($one_file, $unxformed, $obj) = @_;
+    my ($one_file, $unxformed, $obj, $where) = @_;
 
     my ($linker) = '';
 
@@ -2809,7 +2812,7 @@
            define_objects_from_sources ($var,
                                         $xpfx . $one_file . '_OBJECTS',
                                         $prefix =~ /EXTRA_/,
-                                        $one_file, $obj, $var, $var);
+                                        $one_file, $obj, $var, $var, $where);
        $needlinker ||= $temp;
     }
     if ($needlinker)
@@ -2820,7 +2823,7 @@
     my @keys = sort keys %used_pfx;
     if (scalar @keys == 0)
     {
-       &define_variable ($one_file . "_SOURCES", $unxformed . ".c", INTERNAL);
+       &define_variable ($one_file . "_SOURCES", $unxformed . ".c", $where);
        push (@sources, $unxformed . '.c');
        push (@dist_sources, $unxformed . '.c');
 
@@ -2831,12 +2834,12 @@
                                         $one_file, $obj,
                                         "$unxformed.c");
        $linker ||= &resolve_linker (%linkers_used);
-       define_pretty_variable ($one_file . '_OBJECTS', '', INTERNAL, @result)
+       define_pretty_variable ($one_file . '_OBJECTS', '', $where, @result)
     }
     else
     {
        grep ($_ = '$(' . $_ . $one_file . '_OBJECTS)', @keys);
-       define_pretty_variable ($one_file . '_OBJECTS', '', INTERNAL, @keys);
+       define_pretty_variable ($one_file . '_OBJECTS', '', $where, @keys);
     }
 
     # If we want to use `LINK' we must make sure it is defined.
@@ -3143,8 +3146,10 @@
   my $seen_global_libobjs =
     variable_defined ('LDADD') && &handle_lib_objects ('', 'LDADD');
 
-  foreach my $one_file (@proglist)
+  foreach my $pair (@proglist)
     {
+      my ($where, $one_file) = @$pair;
+
       my $seen_libobjs = 0;
       my $obj = &get_object_extension ($one_file);
 
@@ -3153,7 +3158,10 @@
                                             '_SOURCES', '_OBJECTS',
                                             '_DEPENDENCIES');
 
-      my $linker = &handle_source_transform ($xname, $one_file, $obj);
+      $where->push_context ("while processing program `$one_file'");
+      $where->set (INTERNAL->get);
+
+      my $linker = &handle_source_transform ($xname, $one_file, $obj, $where);
 
       my $xt = '';
       if (variable_defined ($xname . "_LDADD"))
@@ -3164,7 +3172,7 @@
       else
        {
          # User didn't define prog_LDADD override.  So do it.
-         &define_variable ($xname . '_LDADD', '$(LDADD)', INTERNAL);
+         &define_variable ($xname . '_LDADD', '$(LDADD)', $where);
 
          # This does a bit too much work.  But we need it to
          # generate _DEPENDENCIES when appropriate.
@@ -3174,7 +3182,7 @@
            }
          elsif (! variable_defined ($xname . '_DEPENDENCIES'))
            {
-             &define_variable ($xname . '_DEPENDENCIES', '', INTERNAL);
+             &define_variable ($xname . '_DEPENDENCIES', '', $where);
            }
          $xt = '_SOURCES';
        }
@@ -3185,7 +3193,7 @@
       if (! variable_defined ($xname . '_LDFLAGS'))
        {
          # Define the prog_LDFLAGS variable.
-         &define_variable ($xname . '_LDFLAGS', '', INTERNAL);
+         &define_variable ($xname . '_LDFLAGS', '', $where);
        }
 
       # Determine program to use for link.
@@ -3209,7 +3217,7 @@
                       : '');
 
       $output_rules .= &file_contents ('program',
-                                      new Automake::Location,
+                                      $where,
                                       PROGRAM  => $one_file,
                                       XPROGRAM => $xname,
                                       XLINK    => $xlink,
@@ -3247,17 +3255,20 @@
                               'library used', 'RANLIB')
     if (@prefix);
 
-  foreach my $onelib (@liblist)
+  foreach my $pair (@liblist)
     {
+      my ($where, $onelib) = @$pair;
+
       my $seen_libobjs = 0;
       # Check that the library fits the standard naming convention.
       if (basename ($onelib) !~ /^lib.*\.a/)
        {
-         # FIXME should put line number here.  That means mapping
-         # from library name back to variable name.
-         err_am "`$onelib' is not a standard library name";
+         err $where, "`$onelib' is not a standard library name";
        }
 
+      $where->push_context ("while processing library `$onelib'");
+      $where->set (INTERNAL->get);
+
       my $obj = &get_object_extension ($onelib);
 
       # Canonicalize names and check for misspellings.
@@ -3267,7 +3278,7 @@
 
       if (! variable_defined ($xlib . '_AR'))
        {
-         &define_variable ($xlib . '_AR', '$(AR) cru', INTERNAL);
+         &define_variable ($xlib . '_AR', '$(AR) cru', $where);
        }
 
       if (variable_defined ($xlib . '_LIBADD'))
@@ -3281,7 +3292,7 @@
        {
          # Generate support for conditional object inclusion in
          # libraries.
-         &define_variable ($xlib . "_LIBADD", '', INTERNAL);
+         &define_variable ($xlib . "_LIBADD", '', $where);
        }
 
       reject_var ($xlib . '_LDADD',
@@ -3290,14 +3301,14 @@
       # Make sure we at look at this.
       &examine_variable ($xlib . '_DEPENDENCIES');
 
-      &handle_source_transform ($xlib, $onelib, $obj);
+      &handle_source_transform ($xlib, $onelib, $obj, $where);
 
       # If the resulting library lies into a subdirectory,
       # make sure this directory will exist.
       my $dirstamp = require_build_directory_maybe ($onelib);
 
       $output_rules .= &file_contents ('library',
-                                      new Automake::Location,
+                                      $where,
                                       LIBRARY  => $onelib,
                                       XLIBRARY => $xlib,
                                       DIRSTAMP => $dirstamp);
@@ -3366,8 +3377,10 @@
        }
     }
 
-  foreach my $onelib (@liblist)
+  foreach my $pair (@liblist)
     {
+      my ($where, $onelib) = @$pair;
+
       my $seen_libobjs = 0;
       my $obj = &get_object_extension ($onelib);
 
@@ -3376,12 +3389,6 @@
                                            '_SOURCES', '_OBJECTS',
                                            '_DEPENDENCIES');
 
-      if (! variable_defined ($xlib . '_LDFLAGS'))
-       {
-         # Define the lib_LDFLAGS variable.
-         &define_variable ($xlib . '_LDFLAGS', '', INTERNAL);
-       }
-
       # Check that the library fits the standard naming convention.
       my $libname_rx = "^lib.*\.la";
       if ((variable_defined ($xlib . '_LDFLAGS')
@@ -3397,12 +3404,19 @@
        }
       if (basename ($onelib) !~ /$libname_rx$/)
        {
-         # FIXME should put line number here.  That means mapping
-         # from library name back to variable name.
-         msg_am ('error-gnu/warn',
+         msg ($where, 'error-gnu/warn',
                  "`$onelib' is not a standard libtool library name");
        }
 
+      $where->push_context ("while processing Libtool library `$onelib'");
+      $where->set (INTERNAL->get);
+
+      if (! variable_defined ($xlib . '_LDFLAGS'))
+       {
+         # Define the lib_LDFLAGS variable.
+         &define_variable ($xlib . '_LDFLAGS', '', $where);
+       }
+
       if (variable_defined ($xlib . '_LIBADD'))
        {
          if (&handle_lib_objects ($xlib, $xlib . '_LIBADD'))
@@ -3414,7 +3428,7 @@
        {
          # Generate support for conditional object inclusion in
          # libraries.
-         &define_variable ($xlib . "_LIBADD", '', INTERNAL);
+         &define_variable ($xlib . "_LIBADD", '', $where);
        }
 
       reject_var ("${xlib}_LDADD",
@@ -3423,7 +3437,7 @@
       # Make sure we at look at this.
       &examine_variable ($xlib . '_DEPENDENCIES');
 
-      my $linker = &handle_source_transform ($xlib, $onelib, $obj);
+      my $linker = &handle_source_transform ($xlib, $onelib, $obj, $where);
 
       # Determine program to use for link.
       my $xlink;
@@ -3462,7 +3476,7 @@
       $libtool_clean_directories{$dirname} = 1;
 
       $output_rules .= &file_contents ('ltlibrary',
-                                      new Automake::Location,
+                                      $where,
                                       LTLIBRARY  => $onelib,
                                       XLTLIBRARY => $xlib,
                                       RPATH      => $rpath,
@@ -4605,7 +4619,7 @@
                             'noinst', 'check');
     foreach (@r)
     {
-       next unless /\..*$/;
+      next unless $_->[1] =~ /\..*$/;
        &saw_extension ($&);
     }
 }
@@ -4969,14 +4983,14 @@
   return if ! @elfiles;
 
   # Generate .elc files.
-  my @elcfiles = map { $_ . 'c' } @elfiles;
+  my @elcfiles = map { $_->[1] . 'c' } @elfiles;
   define_pretty_variable ('ELCFILES', '', INTERNAL, @elcfiles);
 
   push (@all, '$(ELCFILES)');
 
-  require_variables ("$am_file.am", "Emacs Lisp sources seen", 'TRUE',
+  require_variables ($elfiles[0][0], "Emacs Lisp sources seen", 'TRUE',
                     'EMACS', 'lispdir');
-  require_conf_file ("$am_file.am", FOREIGN, 'elisp-comp');
+  require_conf_file ($elfiles[0][0], FOREIGN, 'elisp-comp');
   &define_variable ('elisp_comp', $config_aux_dir . '/elisp-comp', INTERNAL);
 }
 
@@ -4987,9 +5001,8 @@
                                 'noinst');
   return if ! @pyfiles;
 
-  require_variables ("$am_file.am", "Python sources seen", 'TRUE',
-                    'PYTHON');
-  require_conf_file ("$am_file.am", FOREIGN, 'py-compile');
+  require_variables ($pyfiles[0][0], "Python sources seen", 'TRUE', 'PYTHON');
+  require_conf_file ($pyfiles[0][0], FOREIGN, 'py-compile');
   &define_variable ('py_compile', $config_aux_dir . '/py-compile', INTERNAL);
 }
 
@@ -6126,7 +6139,7 @@
   if ($message)
     {
       msg 'syntax', $where, "$message ...";
-      msg_var ('syntax', $var, "... `$var' previously defined here.");
+      msg_var ('syntax', $var, "... `$var' previously defined here");
       verb (macro_dump ($var));
     }
 }
@@ -7022,8 +7035,8 @@
 
 
 # @VALUES
-# &value_to_list ($VAR, $VAL, $COND)
-# ----------------------------------
+# &value_to_list ($VAR, $VAL, $COND, $WHERE, $LOC_WANTED)
+# -------------------------------------------------------
 # Convert a variable value to a list, split as whitespace.  This will
 # recursively follow $(...) and ${...} inclusions.  It preserves @...@
 # substitutions.
@@ -7032,23 +7045,25 @@
 # returned; if COND is a particular condition (all conditions are
 # surrounded by @...@) then only the value for that condition should
 # be returned; otherwise, warn if VAR is conditionally defined.
-# SCANNED is a global hash listing whose keys are all the variables
-# already scanned; it is an error to rescan a variable.
-sub value_to_list ($$$)
+# WHERE is the location where VAR=VAL.
+# If LOC_WANTED is set, return a list of [$location, @values] instead
+# of a list of @values.
+sub value_to_list ($$$$$)
 {
-    my ($var, $val, $cond) = @_;
+  my ($var, $val, $cond, $where, $loc_wanted) = @_;
     my @result;
 
     # Strip backslashes
-    $val =~ s/\\(\n|$)/ /g;
+  $val =~ s/\\$/ /gm;
 
     foreach (split (' ', $val))
     {
        # If a comment seen, just leave.
        last if /^#/;
 
-       # Handle variable substitutions.
-       if (/^\$\{([^}]*)\}$/ || /^\$\(([^)]*)\)$/)
+      # Handle variable substitutions. (The backslash in [^\}] and [^\)]
+      # is here to help Emacs indenting correctly.)
+      if (/^\$\{([^\}]*)\}$/ || /^\$\(([^\)]*)\)$/)
        {
            my $varname = $1;
 
@@ -7067,18 +7082,30 @@
 
            # Find the value.
            @temp_list =
-             variable_value_as_list_recursive_worker ($1, $cond, $var);
+           variable_value_as_list_recursive_worker ($1, $cond, $var,
+                                                    $loc_wanted);
 
-           # Now rewrite the value if appropriate.
+         # Now rewrite the values if appropriate.
            if (defined $from)
            {
-               grep (s/$from$/$to/, @temp_list);
+             for my $val (@temp_list)
+               {
+                 if ($loc_wanted)
+                   {
+                     $val->[0] =~ s/$from$/$to/;
+                   }
+                 else
+                   {
+                     $val =~ s/$from$/$to/;
+                   }
+               }
            }
 
            push (@result, @temp_list);
        }
        else
        {
+         $_ = [$where->clone, $_] if $loc_wanted;
            push (@result, $_);
        }
     }
@@ -7143,8 +7170,8 @@
 
 
 # @VALUE
-# &variable_value_as_list_recursive_worker ($VAR, $COND, $PARENT)
-# ---------------------------------------------------------------
+# &variable_value_as_list_recursive_worker ($VAR, $COND, $PARENT, $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
@@ -7153,9 +7180,11 @@
 # that condition should be returned; otherwise, warn if VAR is
 # conditionally defined.  If PARENT is specified, it is the name of
 # the including variable; this is only used for error reports.
-sub variable_value_as_list_recursive_worker ($$$)
+# If $LOC_WANTED is set, return a list of [$location, @values] instead
+# of a list of @values.
+sub variable_value_as_list_recursive_worker ($$$$)
 {
-    my ($var, $cond, $parent) = @_;
+    my ($var, $cond, $parent, $loc_wanted) = @_;
     my @result = ();
 
     return
@@ -7172,8 +7201,11 @@
        $vars_scanned{$var} = 1;
        foreach my $vcond (keys %{$var_value{$var}})
        {
-           my $val = $var_value{$var}{$vcond};
-           push (@result, &value_to_list ($var, $val, $cond));
+           push (@result, &value_to_list ($var,
+                                          $var_value{$var}{$vcond},
+                                          $cond,
+                                          $var_location{$var}{$vcond},
+                                          $loc_wanted));
        }
     }
     else
@@ -7184,6 +7216,7 @@
        foreach my $vcond (keys %{$var_value{$var}})
        {
            my $val = $var_value{$var}{$vcond};
+           my $where = $var_location{$var}{$vcond};
            if (&conditional_true_when ($vcond, $cond))
            {
                # Warn if we have an ambiguity.  It's hard to know how
@@ -7191,7 +7224,8 @@
                &check_variable_defined_unconditionally ($var, $parent)
                    if $onceflag;
                $onceflag = 1;
-               push (@result, &value_to_list ($var, $val, $cond));
+               push (@result, &value_to_list ($var, $val, $cond, $where,
+                                              $loc_wanted));
            }
        }
     }
@@ -7265,16 +7299,31 @@
 }
 
 
-# &variable_value_as_list_recursive ($VAR, $COND, $PARENT)
-# --------------------------------------------------------
-# This is just a wrapper for variable_value_as_list_recursive_worker that
-# initializes the global hash `vars_scanned'.  This hash is used to
-# avoid infinite recursion.
-sub variable_value_as_list_recursive ($$@)
+# &variable_value_as_list_recursive ($VAR, $COND, [$PARENT])
+# ----------------------------------------------------------
+# Return the list of values of $VAR in condition $COND.
+# $PARENT (if known) is the variable where this variable occurs,
+# in case we need to print an error message.
+sub variable_value_as_list_recursive ($$;$)
+{
+    my ($var, $cond, $parent) = @_;
+    # This global hash is used to avoid infinite recursion in
+    # &variable_value_as_list_recursive_worker.
+    %vars_scanned = ();
+    return &variable_value_as_list_recursive_worker ($var, $cond, $parent, 0);
+}
+
+# &variable_loc_and_value_as_list_recursive ($VAR, $COND, [$PARENT])
+# ----------------------------------------------------------------
+# Return the values of $VAR in condition $COND as a list of
+# [$location, @values] pairs.
+# $PARENT (if known) is the variable where this variable occurs,
+# in case we need to print an error message.
+sub variable_loc_and_value_as_list_recursive ($$;$)
 {
     my ($var, $cond, $parent) = @_;
     %vars_scanned = ();
-    return &variable_value_as_list_recursive_worker ($var, $cond, $parent);
+    return &variable_value_as_list_recursive_worker ($var, $cond, $parent, 1);
 }
 
 
@@ -7450,7 +7499,7 @@
 # is the filename the rule comes from.  $OWNER is the
 # owener of the rule (TARGET_AUTOMAKE or TARGET_USER).
 # $COND is the condition string under which the rule is defined.
-# $WHERE is where the rule is defined (file name and/or line number).
+# $WHERE is the location where the rule is defined.
 # Returns a (possibly empty) list of conditions where the rule
 # should be defined.
 sub rule_define ($$$$$)
@@ -7474,12 +7523,14 @@
       # The no-exeext option enables this feature.
       if (! defined $options{'no-exeext'})
        {
-         msg ('obsolete', $noexe,
-              "deprecated feature: `$noexe' overrides `$noexe\$(EXEEXT)'\n"
+         msg ('obsolete', $targets{$noexe}{$cond},
+              "deprecated feature: target `$noexe' overrides "
+              . "`$noexe\$(EXEEXT)'\n"
               . "change your target to read `$noexe\$(EXEEXT)'");
+         msg ('obsolete', $where, "target `$target' was defined here");
        }
-      # Don't define.
-      return ();
+      # Don't `return ()' now, as this might hide target clashes
+      # detected below.
     }
 
   # For now on, strip off $(EXEEXT) from $target, so we can diagnose
@@ -7530,7 +7581,7 @@
                  # msg ('syntax', $where,
                  #      "redefinition of `$target'$condmsg...");
                  # msg_cond_target ('syntax', $cond, $target,
-                 #                "... `$target' previously defined here.");
+                 #                "... `$target' previously defined here");
                }
              # Return so we don't redefine the rule in our tables,
              # don't check for ambiguous conditional, etc.  The rule
@@ -7569,7 +7620,7 @@
 
              msg ('syntax', $where, "redefinition of `$target'$condmsg...");
              msg_cond_target ('syntax', $cond, $target,
-                              "... `$target' previously defined here.");
+                              "... `$target' previously defined here");
              return ();
            }
        }
@@ -7590,7 +7641,7 @@
          # For user rules, just diagnose the ambiguity.
          msg 'syntax', $where, "$message ...";
          msg_cond_target ('syntax', $ambig_cond, $target,
-                          "... `$target' previously defined here.");
+                          "... `$target' previously defined here");
          return ();
        }
       else
@@ -7626,7 +7677,7 @@
            {
              msg 'syntax', $where, "$message ...";
              msg_cond_target ('syntax', $ambig_cond, $target,
-                              "... `$target' previously defined here.");
+                              "... `$target' previously defined here");
              return ();
            }
        }
@@ -8510,8 +8561,12 @@
 # install code, and possibly generates code to define the primary
 # variable.  The first argument is the name of the .am file to munge,
 # the second argument is the primary variable (eg HEADERS), and all
-# subsequent arguments are possible installation locations.  Returns
-# list of all values of all _HOW targets.
+# subsequent arguments are possible installation locations.
+#
+# Returns list of [$location, $value] pairs, where
+# $value's are the values in all where_HOW variable, and $location
+# there associated location (the place here their parent variables were
+# defined).
 #
 # FIXME: this should be rewritten to be cleaner.  It should be broken
 # up into multiple functions.
@@ -8591,16 +8646,28 @@
            $nodir_name =~ s/^(dist|nodist)_//;
          }
 
+
+      # Use the location of the currently processed variable.
+      # We are not processing a particular condition, so pick the first
+      # available.
+      my $tmpcond = (keys %{$var_value{$one_name}})[0];
+      my $where = $var_location{$one_name}{$tmpcond}->clone;
+
        # Append actual contents of where_PRIMARY variable to
        # result.
-       foreach my $rcurs (&variable_value_as_list_recursive ($one_name, 'all'))
+      foreach my $locvals (&variable_loc_and_value_as_list_recursive
+                          ($one_name, 'all'))
+       {
+         my ($loc, @values) = @$locvals;
+         my @nosubst = (); # @values without substitutions.
+         for my $rcurs (@values)
          {
            # Skip configure substitutions.  Possibly bogus.
            if ($rcurs =~ /address@hidden@$/)
              {
                if ($nodir_name eq 'EXTRA')
                  {
-                   err_var ($one_name,
+                     err ($where,
                             "`$one_name' contains configure substitution, "
                             . "but shouldn't");
                  }
@@ -8612,11 +8679,11 @@
                    $require_extra = $one_name
                      if $do_require;
                  }
-
                next;
              }
-
-           push (@result, $rcurs);
+             push @nosubst, $rcurs;
+           }
+         push (@result, [$loc, @nosubst]) if @nosubst;
          }
        # A blatant hack: we rewrite each _PROGRAMS primary to include
        # EXEEXT.
@@ -8647,10 +8714,6 @@
                              && defined $options{'std-options'};
 
        # Use the location of the currently processed variable as context.
-       # We are not processing a particular condition, so pick the first
-       # available.
-       my $cond = (keys %{$var_value{$one_name}})[0];
-       my $where = $var_location{$one_name}{$cond}->clone;
        $where->push_context ("while processing `$one_name'");
 
        # Singular form of $PRIMARY.
@@ -8693,7 +8756,18 @@
     # Make the result unique.  This lets the user use conditionals in
     # a natural way, but still lets us program lazily -- we don't have
     # to worry about handling a particular object more than once.
-    return uniq (sort @result);
+  # We will keep only one location per object.
+  my %result = ();
+  for my $pair (@result)
+    {
+      my ($loc, @values) = @$pair;
+      for my $val (@values)
+       {
+         $result{$val} = $loc;
+       }
+    }
+  my @l = sort keys %result;
+  return map { [$result{$_}->clone, $_] } @l;
 }
 
 
Index: tests/Makefile.am
===================================================================
RCS file: /cvs/automake/automake/tests/Makefile.am,v
retrieving revision 1.444
diff -u -b -r1.444 Makefile.am
--- tests/Makefile.am   29 Sep 2002 10:35:03 -0000      1.444
+++ tests/Makefile.am   29 Sep 2002 12:45:17 -0000
@@ -240,6 +240,7 @@
 lisp.test \
 lisp2.test \
 listval.test \
+location.test \
 ltdeps.test \
 ltlibobjs.test \
 maintclean.test \
Index: tests/location.test
===================================================================
RCS file: tests/location.test
diff -N tests/location.test
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ tests/location.test 29 Sep 2002 12:45:18 -0000
@@ -0,0 +1,51 @@
+#! /bin/sh
+# Copyright (C) 2002  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 autoconf; see the file COPYING.  If not, write to
+# the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+
+# Test for locations in error messages.
+
+. ./defs || exit 1
+
+set -e
+
+cat >> configure.in << 'END'
+AM_CONDITIONAL([COND1], [true])
+AM_CONDITIONAL([COND2], [true])
+AC_PROG_CC
+AC_PROG_RANLIB
+END
+
+cat > Makefile.am << 'END'
+bin_PROGRAMS = libfoo.a
+if COND2
+  lib_LIBRARIES = libfoo.a
+endif
+if COND1
+  bin_PROGRAMS += ctags
+endif
+END
+
+$ACLOCAL
+$AUTOMAKE 2>stderr && exit 1
+cat stderr
+grep 'Makefile\.am:1:.*program.*libfoo\.a' stderr
+grep 'Makefile\.am:3:.*library.*libfoo\.a' stderr
+grep 'Makefile\.am:6:.*program.*ctags' stderr
+grep 'redefinition of.*libfoo\.a' stderr
+grep 'redefinition of.*ctags' stderr
Index: tests/stdlib.test
===================================================================
RCS file: /cvs/automake/automake/tests/stdlib.test,v
retrieving revision 1.3
diff -u -b -r1.3 stdlib.test
--- tests/stdlib.test   8 Sep 2002 13:07:56 -0000       1.3
+++ tests/stdlib.test   29 Sep 2002 12:45:18 -0000
@@ -22,6 +22,8 @@
 
 . ./defs || exit 1
 
+set -e
+
 cat >> configure.in << 'END'
 AC_PROG_CC
 AC_PROG_RANLIB
@@ -31,9 +33,8 @@
 noinst_LIBRARIES = foo
 END
 
-$ACLOCAL || exit 1
+$ACLOCAL
 $AUTOMAKE 2> output.log && exit 1
+cat output.log
 # We're specifically testing for line-number information.
-# Well, when it is implemented.
-# grep 1 output.log
-exit 0
+grep 'Makefile.am:1:.*foo.*standard library name' output.log
-- 
Alexandre Duret-Lutz





reply via email to

[Prev in Thread] Current Thread [Next in Thread]