autoconf-commit
[Top][All Lists]
Advanced

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

[SCM] GNU Autoconf source repository branch, master, updated. v2.68-131-


From: Jim Meyering
Subject: [SCM] GNU Autoconf source repository branch, master, updated. v2.68-131-gb035df3
Date: Sat, 21 Jan 2012 15:09:16 +0000

This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "GNU Autoconf source repository".

http://git.sv.gnu.org/gitweb/?p=autoconf.git;a=commitdiff;h=b035df38e0d888bab264245623c8cd72bd05db4d

The branch, master has been updated
       via  b035df38e0d888bab264245623c8cd72bd05db4d (commit)
       via  d9256c2143b35d3ee03b2b2e3be0f70465ac241a (commit)
       via  364bdd3bff8ce411c877f2ef156d5b2ef454d449 (commit)
       via  2ca285bdbc0da7102cb3aa59d697afe3af7e0d06 (commit)
       via  5fdbf57c6aa5468e47dca0d0d0330196517b2e17 (commit)
       via  40c846ea9c223b87f8b7e1428c443bd5a54c4835 (commit)
       via  a7f773305a4db24271e3a00b27a06c6f9640e62b (commit)
      from  7dae44f737b98069d0bb911ab6347e07c7001dc4 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit b035df38e0d888bab264245623c8cd72bd05db4d
Author: Jim Meyering <address@hidden>
Date:   Sat Jan 21 12:05:02 2012 +0100

    maint: fix or disable failing syntax-check rules
    
    * cfg.mk (local-checks-to-skip): List failing tests, so we skip
    them, for now.
    (old_NEWS_hash): Update.
    * doc/autoconf.texi: Per suggestion from Eric Blake, obfuscate
    the first word of "Filesystem Hierarchy Standard" as File@/system
    so it continues to render as one word, yet doesn't trigger the
    syntax-check prohibition.

commit d9256c2143b35d3ee03b2b2e3be0f70465ac241a
Author: Jim Meyering <address@hidden>
Date:   Tue Jan 17 14:22:02 2012 +0100

    maint: also sync maint.mk and useless-if-before-free from gnulib
    
    * cfg.mk (gnulib-update): Add them to the list.
    * maint.mk: Update from gnulib.
    * build-aux/gitlog-to-changelog: Likewise.
    * build-aux/useless-if-before-free: New file, from gnulib.
    * doc/gnu-oids.texi: Update.

commit 364bdd3bff8ce411c877f2ef156d5b2ef454d449
Author: Jim Meyering <address@hidden>
Date:   Tue Jan 17 11:02:03 2012 +0100

    maint.mk: update from gnulib
    
    * maint.mk: Update.

commit 2ca285bdbc0da7102cb3aa59d697afe3af7e0d06
Author: Jim Meyering <address@hidden>
Date:   Tue Jan 17 10:58:54 2012 +0100

    maint: placate syntax-check rules: exempt some false positives
    
    * cfg.mk: Exempt maint.mk from the "undesirable word seq" check.
    Exempt maint.mk and autoconf.texi from the test_minus_ao check.

commit 5fdbf57c6aa5468e47dca0d0d0330196517b2e17
Author: Jim Meyering <address@hidden>
Date:   Tue Jan 17 10:36:42 2012 +0100

    maint: tweak to avoid triggering space-tab-prohibiting syntax-check
    
    * tests/m4sh.at (nargs): Use TAB-SP, not SP-TAB in abusive file name,
    to avoid triggering the space-tab-prohibiting syntax-check.

commit 40c846ea9c223b87f8b7e1428c443bd5a54c4835
Author: Jim Meyering <address@hidden>
Date:   Tue Jan 17 10:33:51 2012 +0100

    maint: remove empty lines at EOF
    
    * man/autoconf.x: Remove empty line at EOF.
    * man/autoheader.x: Likewise.
    * man/autoscan.x: Likewise.
    * man/autoupdate.x: Likewise.
    * man/ifnames.x: Likewise.
    * tests/compile.at: Likewise.
    * doc/fdl.texi: Likewise.

commit a7f773305a4db24271e3a00b27a06c6f9640e62b
Author: Jim Meyering <address@hidden>
Date:   Tue Jan 17 10:31:12 2012 +0100

    doc: fix grammar/doubled-word errors
    
    * doc/autoconf.texi: Remove/fix doubled-word errors.
    Also, s/can not/cannot/.
    * lib/m4sugar/m4sh.m4: Reword "if IF" comment to avoid triggering
    the doubled-word warning.

-----------------------------------------------------------------------

Summary of changes:
 build-aux/gitlog-to-changelog    |   24 +-
 build-aux/useless-if-before-free |  207 +++++
 cfg.mk                           |   21 +-
 doc/autoconf.texi                |   15 +-
 doc/fdl.texi                     |    1 -
 doc/gnu-oids.texi                |    2 +-
 lib/m4sugar/m4sh.m4              |    2 +-
 maint.mk                         | 1526 +++++++++++++++++++++++++++++---------
 man/autoconf.x                   |    1 -
 man/autoheader.x                 |    1 -
 man/autoscan.x                   |    1 -
 man/autoupdate.x                 |    1 -
 man/ifnames.x                    |    1 -
 tests/compile.at                 |    1 -
 tests/m4sh.at                    |    4 +-
 15 files changed, 1427 insertions(+), 381 deletions(-)
 create mode 100755 build-aux/useless-if-before-free

diff --git a/build-aux/gitlog-to-changelog b/build-aux/gitlog-to-changelog
index 0efedb0..38c6f3a 100755
--- a/build-aux/gitlog-to-changelog
+++ b/build-aux/gitlog-to-changelog
@@ -3,7 +3,7 @@ eval '(exit $?0)' && eval 'exec perl -wS "$0" ${1+"$@"}'
     if 0;
 # Convert git log output to ChangeLog format.
 
-my $VERSION = '2012-01-06 07:14'; # UTC
+my $VERSION = '2012-01-18 07:50'; # UTC
 # The definition above must lie within the first 8 lines in order
 # for the Emacs time-stamp write hook (at end) to update it.
 # If you change this file with Emacs, please let the write hook
@@ -64,6 +64,10 @@ OPTIONS:
                   makes a change to SHA1's commit log text or metadata.
    --append-dot append a dot to the first line of each commit message if
                   there is no other punctuation or blank at the end.
+   --no-cluster never cluster commit messages under the same date/author
+                  header; the default is to cluster adjacent commit messages
+                  if their headers are the same and neither commit message
+                  contains multiple paragraphs.
    --since=DATE convert only the logs since DATE;
                   the default is to convert all log entries.
    --format=FMT set format string for commit subject and body;
@@ -190,6 +194,7 @@ sub parse_amend_file($)
   my $format_string = '%s%n%b%n';
   my $amend_file;
   my $append_dot = 0;
+  my $cluster = 1;
   GetOptions
     (
      help => sub { usage 0 },
@@ -198,6 +203,7 @@ sub parse_amend_file($)
      'format=s' => \$format_string,
      'amend=s' => \$amend_file,
      'append-dot' => \$append_dot,
+     'cluster!' => \$cluster,
     ) or usage 1;
 
 
@@ -302,13 +308,15 @@ sub parse_amend_file($)
               . substr ($_, 5) . "\n";
         }
 
-      # If this header would be different from the previous date/name/email/
-      # coauthors header, or if this or the previous entry consists of two
-      # or more paragraphs, then print the header.
-      if ($date_line ne $prev_date_line
-          or "@coauthors" ne "@prev_coauthors"
-          or $multi_paragraph
-          or $prev_multi_paragraph)
+      # If clustering of commit messages has been disabled, if this header
+      # would be different from the previous date/name/email/coauthors header,
+      # or if this or the previous entry consists of two or more paragraphs,
+      # then print the header.
+      if ( ! $cluster
+          || $date_line ne $prev_date_line
+          || "@coauthors" ne "@prev_coauthors"
+          || $multi_paragraph
+          || $prev_multi_paragraph)
         {
           $prev_date_line eq ''
             or print "\n";
diff --git a/build-aux/useless-if-before-free b/build-aux/useless-if-before-free
new file mode 100755
index 0000000..2b64630
--- /dev/null
+++ b/build-aux/useless-if-before-free
@@ -0,0 +1,207 @@
+eval '(exit $?0)' && eval 'exec perl -wST "$0" ${1+"$@"}'
+  & eval 'exec perl -wST "$0" $argv:q'
+    if 0;
+# Detect instances of "if (p) free (p);".
+# Likewise "if (p != 0)", "if (0 != p)", or with NULL; and with braces.
+
+my $VERSION = '2012-01-06 07:23'; # UTC
+# The definition above must lie within the first 8 lines in order
+# for the Emacs time-stamp write hook (at end) to update it.
+# If you change this file with Emacs, please let the write hook
+# do its job.  Otherwise, update this string manually.
+
+# Copyright (C) 2008-2012 Free Software Foundation, Inc.
+
+# This program 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 3 of the License, or
+# (at your option) any later version.
+
+# This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# Written by Jim Meyering
+
+use strict;
+use warnings;
+use Getopt::Long;
+
+(my $ME = $0) =~ s|.*/||;
+
+# use File::Coda; # http://meyering.net/code/Coda/
+END {
+  defined fileno STDOUT or return;
+  close STDOUT and return;
+  warn "$ME: failed to close standard output: $!\n";
+  $? ||= 1;
+}
+
+sub usage ($)
+{
+  my ($exit_code) = @_;
+  my $STREAM = ($exit_code == 0 ? *STDOUT : *STDERR);
+  if ($exit_code != 0)
+    {
+      print $STREAM "Try '$ME --help' for more information.\n";
+    }
+  else
+    {
+      print $STREAM <<EOF;
+Usage: $ME [OPTIONS] FILE...
+
+Detect any instance in FILE of a useless "if" test before a free call, e.g.,
+"if (p) free (p);".  Any such test may be safely removed without affecting
+the semantics of the C code in FILE.  Use --name=FOO --name=BAR to also
+detect free-like functions named FOO and BAR.
+
+OPTIONS:
+
+   --list       print only the name of each matching FILE (\\0-terminated)
+   --name=N     add name N to the list of \'free\'-like functions to detect;
+                  may be repeated
+
+   --help       display this help and exit
+   --version    output version information and exit
+
+Exit status:
+
+  0   one or more matches
+  1   no match
+  2   an error
+
+EXAMPLE:
+
+For example, this command prints all removable "if" tests before "free"
+and "kfree" calls in the linux kernel sources:
+
+    git ls-files -z |xargs -0 $ME --name=kfree
+
+EOF
+    }
+  exit $exit_code;
+}
+
+sub is_NULL ($)
+{
+  my ($expr) = @_;
+  return ($expr eq 'NULL' || $expr eq '0');
+}
+
+{
+  sub EXIT_MATCH {0}
+  sub EXIT_NO_MATCH {1}
+  sub EXIT_ERROR {2}
+  my $err = EXIT_NO_MATCH;
+
+  my $list;
+  my @name = qw(free);
+  GetOptions
+    (
+     help => sub { usage 0 },
+     version => sub { print "$ME version $VERSION\n"; exit },
+     list => \$list,
+     'name=s@' => address@hidden,
+    ) or usage 1;
+
+  # Make sure we have the right number of non-option arguments.
+  # Always tell the user why we fail.
+  @ARGV < 1
+    and (warn "$ME: missing FILE argument\n"), usage EXIT_ERROR;
+
+  my $or = join '|', @name;
+  my $regexp = qr/(?:$or)/;
+
+  # Set the input record separator.
+  # Note: this makes it impractical to print line numbers.
+  $/ = '"';
+
+  my $found_match = 0;
+ FILE:
+  foreach my $file (@ARGV)
+    {
+      open FH, '<', $file
+        or (warn "$ME: can't open '$file' for reading: $!\n"),
+          $err = EXIT_ERROR, next;
+      while (defined (my $line = <FH>))
+        {
+          while ($line =~
+              /\b(if\s*\(\s*([^)]+?)(?:\s*!=\s*([^)]+?))?\s*\)
+              #  1          2                  3
+               (?:   \s*$regexp\s*\((?:\s*\([^)]+\))?\s*([^)]+)\)\s*;|
+                
\s*\{\s*$regexp\s*\((?:\s*\([^)]+\))?\s*([^)]+)\)\s*;\s*\}))/sxg)
+            {
+              my $all = $1;
+              my ($lhs, $rhs) = ($2, $3);
+              my ($free_opnd, $braced_free_opnd) = ($4, $5);
+              my $non_NULL;
+              if (!defined $rhs) { $non_NULL = $lhs }
+              elsif (is_NULL $rhs) { $non_NULL = $lhs }
+              elsif (is_NULL $lhs) { $non_NULL = $rhs }
+              else { next }
+
+              # Compare the non-NULL part of the "if" expression and the
+              # free'd expression, without regard to white space.
+              $non_NULL =~ tr/ \t//d;
+              my $e2 = defined $free_opnd ? $free_opnd : $braced_free_opnd;
+              $e2 =~ tr/ \t//d;
+              if ($non_NULL eq $e2)
+                {
+                  $found_match = 1;
+                  $list
+                    and (print "$file\0"), next FILE;
+                  print "$file: $all\n";
+                }
+            }
+        }
+    }
+  continue
+    {
+      close FH;
+    }
+
+  $found_match && $err == EXIT_NO_MATCH
+    and $err = EXIT_MATCH;
+
+  exit $err;
+}
+
+my $foo = <<'EOF';
+# The above is to *find* them.
+# This adjusts them, removing the unnecessary "if (p)" part.
+
+# FIXME: do something like this as an option (doesn't do braces):
+free=xfree
+git grep -l -z "$free *(" \
+  | xargs -0 useless-if-before-free -l --name="$free" \
+  | xargs -0 perl -0x3b -pi -e \
+   
's/\bif\s*\(\s*(\S+?)(?:\s*!=\s*(?:0|NULL))?\s*\)\s+('"$free"'\s*\((?:\s*\([^)]+\))?\s*\1\s*\)\s*;)/$2/s'
+
+# Use the following to remove redundant uses of kfree inside braces.
+# Note that -0777 puts perl in slurp-whole-file mode;
+# but we have plenty of memory, these days...
+free=kfree
+git grep -l -z "$free *(" \
+  | xargs -0 useless-if-before-free -l --name="$free" \
+  | xargs -0 perl -0777 -pi -e \
+     
's/\bif\s*\(\s*(\S+?)(?:\s*!=\s*(?:0|NULL))?\s*\)\s*\{\s*('"$free"'\s*\((?:\s*\([^)]+\))?\s*\1\s*\);)\s*\}[^\n]*$/$2/gms'
+
+Be careful that the result of the above transformation is valid.
+If the matched string is followed by "else", then obviously, it won't be.
+
+When modifying files, refuse to process anything other than a regular file.
+EOF
+
+## Local Variables:
+## mode: perl
+## indent-tabs-mode: nil
+## eval: (add-hook 'write-file-hooks 'time-stamp)
+## time-stamp-start: "my $VERSION = '"
+## time-stamp-format: "%:y-%02m-%02d %02H:%02M"
+## time-stamp-time-zone: "UTC"
+## time-stamp-end: "'; # UTC"
+## End:
diff --git a/cfg.mk b/cfg.mk
index a66c247..77e0487 100644
--- a/cfg.mk
+++ b/cfg.mk
@@ -65,6 +65,7 @@ gnulib-update:
        cp $(gnulib_dir)/build-aux/move-if-change $(srcdir)/build-aux
        cp $(gnulib_dir)/build-aux/texinfo.tex $(srcdir)/build-aux
        cp $(gnulib_dir)/build-aux/update-copyright $(srcdir)/build-aux
+       cp $(gnulib_dir)/build-aux/useless-if-before-free $(srcdir)/build-aux
        cp $(gnulib_dir)/build-aux/vc-list-files $(srcdir)/build-aux
        cp $(gnulib_dir)/doc/fdl.texi $(srcdir)/doc
        cp $(gnulib_dir)/doc/gendocs_template $(srcdir)/doc
@@ -73,6 +74,7 @@ gnulib-update:
        cp $(gnulib_dir)/doc/standards.texi $(srcdir)/doc
        cp $(gnulib_dir)/m4/autobuild.m4 $(srcdir)/m4
        cp $(gnulib_dir)/top/GNUmakefile $(srcdir)
+       cp $(gnulib_dir)/top/maint.mk $(srcdir)
 
 WGET = wget
 WGETFLAGS = -C off
@@ -107,7 +109,18 @@ autom4te-update:
 
 # Tests not to run.
 local-checks-to-skip ?= \
-  changelog-check sc_unmarked_diagnostics
+  changelog-check                      \
+  sc_GPL_version                       \
+  sc_cast_of_alloca_return_value       \
+  sc_m4_quote_check                    \
+  sc_makefile_at_at_check              \
+  sc_prohibit_HAVE_MBRTOWC             \
+  sc_prohibit_always-defined_macros    \
+  sc_prohibit_always_true_header_tests \
+  sc_prohibit_magic_number_exit                \
+  sc_prohibit_stat_st_blocks           \
+  sc_unmarked_diagnostics
+
 
 # Always use shorthand copyrights.
 update-copyright-env = \
@@ -115,4 +128,8 @@ update-copyright-env = \
   UPDATE_COPYRIGHT_MAX_LINE_LENGTH=72
 
 # Prevent incorrect NEWS edits.
-old_NEWS_hash = 6a8aa950938fba063f3dc2b0e11e67e8
+old_NEWS_hash = 33207c359dd7db17cc0cd151da6b9567
+
+exclude_file_name_regexp--sc_prohibit_undesirable_word_seq = ^maint\.mk$$
+exclude_file_name_regexp--sc_prohibit_test_minus_ao = \
+  ^(maint\.mk|doc/autoconf\.texi)$$
diff --git a/doc/autoconf.texi b/doc/autoconf.texi
index 5c3feef..247a46c 100644
--- a/doc/autoconf.texi
+++ b/doc/autoconf.texi
@@ -8279,7 +8279,7 @@ successful, and @var{action-if-failure} (defaults to 
failing with an
 error message) if not.
 
 This macro calls @code{AC_FC_PP_SRCEXT([F])} in order to learn how to
-to preprocess a @file{conftest.F} file, but restores a previously used
+preprocess a @file{conftest.F} file, but restores a previously used
 Fortran source file extension afterwards again.
 
 The result of this test is cached in the @code{ac_cv_fc_pp_define}
@@ -19266,7 +19266,7 @@ Unicos 9 @command{sed} loops endlessly on patterns like 
@samp{.*\n.*}.
 Sed scripts should not use branch labels longer than 7 characters and
 should not contain comments; AIX 5.3 @command{sed} rejects indented comments.
 HP-UX sed has a limit of 99 commands (not counting @samp{:} commands) and
-48 labels, which can not be circumvented by using more than one script
+48 labels, which cannot be circumvented by using more than one script
 file.  It can execute up to 19 reads with the @samp{r} command per cycle.
 Solaris @command{/usr/ucb/sed} rejects usages that exceed a limit of
 about 6000 bytes for the internal representation of commands.
@@ -22516,11 +22516,14 @@ if test "$cache_file" = /dev/null; then
 fi
 @end example
 
address@hidden Filesystem Hierarchy Standard
address@hidden Leave this use of ``File system'' rendered as one word, but
address@hidden slightly obfuscated so as not to trigger the syntax-check 
prohibition.
address@hidden File@/system Hierarchy Standard
 @cindex FHS
 
 Another use of @file{config.site} is for priming the directory variables
-in a manner consistent with the Filesystem Hierarchy Standard
address@hidden ``File system'', but slightly obfuscated, as above.
+in a manner consistent with the File@/system Hierarchy Standard
 (FHS).  Once the following file is installed at
 @file{/usr/share/config.site}, a user can execute simply
 @code{./configure --prefix=/usr} to get all the directories chosen in
@@ -24892,7 +24895,7 @@ complete and if no option from @var{options} was used.
 @var{help-text} is added to the end of the list of options shown in
 @command{testsuite --help} (@pxref{AS_HELP_STRING}).
 
-It it recommended that you use a package-specific prefix to @var{options}
+It is recommended that you use a package-specific prefix to @var{options}
 names in order to avoid clashes with future Autotest built-in options.
 @end defmac
 
@@ -24923,7 +24926,7 @@ complete and if no option from @var{options} was used.
 @var{help-text} is added to the end of the list of options shown in
 @command{testsuite --help} (@pxref{AS_HELP_STRING}).
 
-It it recommended that you use a package-specific prefix to @var{options}
+It is recommended that you use a package-specific prefix to @var{options}
 names in order to avoid clashes with future Autotest built-in options.
 @end defmac
 
diff --git a/doc/fdl.texi b/doc/fdl.texi
index 3b83db4..cb71f05 100644
--- a/doc/fdl.texi
+++ b/doc/fdl.texi
@@ -503,4 +503,3 @@ to permit their use in free software.
 @c Local Variables:
 @c ispell-local-pdict: "ispell-dict"
 @c End:
-
diff --git a/doc/gnu-oids.texi b/doc/gnu-oids.texi
index 85386e7..ecbd59b 100644
--- a/doc/gnu-oids.texi
+++ b/doc/gnu-oids.texi
@@ -15,7 +15,7 @@
 
 1.3.6.1.4.1.11591.1 GNU Radius
 
-1.3.6.1.4.1.11591.2 GnuPG 
+1.3.6.1.4.1.11591.2 GnuPG
   1.3.6.1.4.1.11591.2.1   notation
   1.3.6.1.4.1.11591.2.1.1 pkaAddress
 
diff --git a/lib/m4sugar/m4sh.m4 b/lib/m4sugar/m4sh.m4
index 38e0bef..5d01f55 100644
--- a/lib/m4sugar/m4sh.m4
+++ b/lib/m4sugar/m4sh.m4
@@ -623,7 +623,7 @@ done[]_m4_popdef([$1])])
 # | else
 # |   IF-FALSE
 # | fi
-# with simplifications if IF-TRUE1 and/or IF-FALSE is empty.
+# with simplifications when IF-TRUE1 and/or IF-FALSE are empty.
 #
 m4_define([_AS_IF],
 [elif $1; then :
diff --git a/maint.mk b/maint.mk
index e1a963a..2668655 100644
--- a/maint.mk
+++ b/maint.mk
@@ -1,6 +1,6 @@
 # -*-Makefile-*-
 # This Makefile fragment tries to be general-purpose enough to be
-# used by at least coreutils, idutils, CPPI, Bison, and Autoconf.
+# used by many projects via the gnulib maintainer-makefile module.
 
 ## Copyright (C) 2001-2012 Free Software Foundation, Inc.
 ##
@@ -21,8 +21,12 @@
 # ME := $(word $(words $(MAKEFILE_LIST)),$(MAKEFILE_LIST))
 ME := maint.mk
 
-# Override this in cfg.mk if you use a non-standard build-aux directory.
-build_aux ?= $(srcdir)/build-aux
+# Diagnostic for continued use of deprecated variable.
+# Remove in 2013
+ifneq ($(build_aux),)
+ $(error "$(ME): \
+set $$(_build-aux) relative to $$(srcdir) instead of $$(build_aux)")
+endif
 
 # Do not save the original name or timestamp in the .tar.gz file.
 # Use --rsyncable if available.
@@ -33,16 +37,37 @@ GZIP_ENV = '--no-name --best $(gzip_rsyncable)'
 
 GIT = git
 VC = $(GIT)
-VC-tag = git tag -s -m '$(VERSION)' -u '$(gpg_key_ID)'
 
-VC_LIST = $(build_aux)/vc-list-files -C $(srcdir)
+VC_LIST = $(srcdir)/$(_build-aux)/vc-list-files -C $(srcdir)
+
+# You can override this variable in cfg.mk to set your own regexp
+# matching files to ignore.
+VC_LIST_ALWAYS_EXCLUDE_REGEX ?= ^$$
 
+# This is to preprocess robustly the output of $(VC_LIST), so that even
+# when $(srcdir) is a pathological name like "....", the leading sed command
+# removes only the intended prefix.
+_dot_escaped_srcdir = $(subst .,\.,$(srcdir))
+
+# Post-process $(VC_LIST) output, prepending $(srcdir)/, but only
+# when $(srcdir) is not ".".
+ifeq ($(srcdir),.)
+_prepend_srcdir_prefix =
+else
+_prepend_srcdir_prefix = | sed 's|^|$(srcdir)/|'
+endif
+
+# In order to be able to consistently filter "."-relative names,
+# (i.e., with no $(srcdir) prefix), this definition is careful to
+# remove any $(srcdir) prefix, and to restore what it removes.
+_sc_excl = \
+  $(if $(exclude_file_name_regexp--$@),$(exclude_file_name_regexp--$@),^$$)
 VC_LIST_EXCEPT = \
-  $(VC_LIST) | if test -f $(srcdir)/.x-$@; then        \
-    grep -vEf $(srcdir)/.x-$@;                 \
-  else                                         \
-    grep -v ChangeLog;                         \
-  fi
+  $(VC_LIST) | sed 's|^$(_dot_escaped_srcdir)/||' \
+       | if test -f $(srcdir)/.x-$@; then grep -vEf $(srcdir)/.x-$@; \
+         else grep -Ev -e "$${VC_LIST_EXCEPT_DEFAULT-ChangeLog}"; fi \
+       | grep -Ev -e '($(VC_LIST_ALWAYS_EXCLUDE_REGEX)|$(_sc_excl))' \
+       $(_prepend_srcdir_prefix)
 
 ifeq ($(origin prev_version_file), undefined)
   prev_version_file = $(srcdir)/.prev-version
@@ -52,12 +77,18 @@ PREV_VERSION := $(shell cat $(prev_version_file) 
2>/dev/null)
 VERSION_REGEXP = $(subst .,\.,$(VERSION))
 PREV_VERSION_REGEXP = $(subst .,\.,$(PREV_VERSION))
 
+ifeq ($(VC),$(GIT))
 this-vc-tag = v$(VERSION)
 this-vc-tag-regexp = v$(VERSION_REGEXP)
+else
+tag-package = $(shell echo "$(PACKAGE)" | tr '[:lower:]' '[:upper:]')
+tag-this-version = $(subst .,_,$(VERSION))
+this-vc-tag = $(tag-package)-$(tag-this-version)
+this-vc-tag-regexp = $(this-vc-tag)
+endif
 my_distdir = $(PACKAGE)-$(VERSION)
 
 # Old releases are stored here.
-# Used for diffs.
 release_archive_dir ?= ../release
 
 # Override gnu_rel_host and url_dir_list in cfg.mk if these are not right.
@@ -74,115 +105,307 @@ else
 url_dir_list ?= ftp://$(gnu_rel_host)/gnu/$(PACKAGE)
 endif
 
+# Override this in cfg.mk if you are using a different format in your
+# NEWS file.
+today = $(shell date +%Y-%m-%d)
+
+# Select which lines of NEWS are searched for $(news-check-regexp).
+# This is a sed line number spec.  The default says that we search
+# lines 1..10 of NEWS for $(news-check-regexp).
+# If you want to search only line 3 or only lines 20-22, use "3" or "20,22".
+news-check-lines-spec ?= 1,10
+news-check-regexp ?= '^\*.* $(VERSION_REGEXP) \($(today)\)'
+
 # Prevent programs like 'sort' from considering distinct strings to be equal.
 # Doing it here saves us from having to set LC_ALL elsewhere in this file.
 export LC_ALL = C
 
-
-
 ## --------------- ##
 ## Sanity checks.  ##
 ## --------------- ##
 
-# Collect the names of rules starting with `sc_'.
-syntax-check-rules := $(shell sed -n 's/^\(sc_[a-zA-Z0-9_-]*\):.*/\1/p' \
-                       $(srcdir)/$(ME))
+_cfg_mk := $(shell test -f $(srcdir)/cfg.mk && echo '$(srcdir)/cfg.mk')
+
+# Collect the names of rules starting with 'sc_'.
+syntax-check-rules := $(sort $(shell sed -n 's/^\(sc_[a-zA-Z0-9_-]*\):.*/\1/p' 
\
+                       $(srcdir)/$(ME) $(_cfg_mk)))
 .PHONY: $(syntax-check-rules)
 
-local-checks-available = \
-  po-check copyright-check writable-files m4-check author_mark_check \
-  changelog-check patch-check strftime-check $(syntax-check-rules) \
-  makefile_path_separator_check \
-  makefile-check check-AUTHORS
+ifeq ($(shell $(VC_LIST) >/dev/null 2>&1; echo $$?),0)
+local-checks-available += $(syntax-check-rules)
+else
+local-checks-available += no-vc-detected
+no-vc-detected:
+       @echo "No version control files detected; skipping syntax check"
+endif
 .PHONY: $(local-checks-available)
 
-local-check := $(filter-out $(local-checks-to-skip), $(local-checks-available))
+# Arrange to print the name of each syntax-checking rule just before running 
it.
+$(syntax-check-rules): %: %.m
+sc_m_rules_ = $(patsubst %, %.m, $(syntax-check-rules))
+.PHONY: $(sc_m_rules_)
+$(sc_m_rules_):
+       @echo $(patsubst sc_%.m, %, $@)
+       @date +%s.%N > .sc-start-$(basename $@)
+
+# Compute and print the elapsed time for each syntax-check rule.
+sc_z_rules_ = $(patsubst %, %.z, $(syntax-check-rules))
+.PHONY: $(sc_z_rules_)
+$(sc_z_rules_): %.z: %
+       @end=$$(date +%s.%N);                                           \
+       start=$$(cat .sc-start-$*);                                     \
+       rm -f .sc-start-$*;                                             \
+       awk -v s=$$start -v e=$$end                                     \
+         'END {printf "%.2f $(patsubst sc_%,%,$*)\n", e - s}' < /dev/null
+
+# The patsubst here is to replace each sc_% rule with its sc_%.z wrapper
+# that computes and prints elapsed time.
+local-check :=                                                         \
+  $(patsubst sc_%, sc_%.z,                                             \
+    $(filter-out $(local-checks-to-skip), $(local-checks-available)))
 
 syntax-check: $(local-check)
-#      @shopt -s nullglob;                                             \
-#      grep -nE '#  *include <(limits|std(def|arg|bool))\.h>'          \
-#          $$(find -type f -name '*.[chly]') /dev/null &&              \
-#        { echo '$(ME): found conditional include' 1>&2;               \
-#          exit 1; } || :
-
-#      grep -nE '^#  *include <(string|stdlib)\.h>'                    \
-#          $(srcdir)/{lib,src}/*.[chly] /dev/null &&                   \
-#        { echo '$(ME): FIXME' 1>&2;                                   \
-#          exit 1; } || :
-# FIXME: don't allow `#include .strings\.h' anywhere
 
-sc_cast_of_argument_to_free:
-       @shopt -s nullglob;                                             \
-       grep -nE '\<free \(\('                                          \
-           $(srcdir)/{lib,src}/*.[chly] /dev/null &&                   \
-         { echo '$(ME): don'\''t cast free argument' 1>&2;             \
+# _sc_search_regexp
+#
+# This macro searches for a given construct in the selected files and
+# then takes some action.
+#
+# Parameters (shell variables):
+#
+#  prohibit | require
+#
+#     Regular expression (ERE) denoting either a forbidden construct
+#     or a required construct.  Those arguments are exclusive.
+#
+#  in_vc_files | in_files
+#
+#     grep-E-style regexp denoting the files to check.  If no files
+#     are specified the default are all the files that are under
+#     version control.
+#
+#  containing | non_containing
+#
+#     Select the files (non) containing strings matching this regexp.
+#     If both arguments are specified then CONTAINING takes
+#     precedence.
+#
+#  with_grep_options
+#
+#     Extra options for grep.
+#
+#  ignore_case
+#
+#     Ignore case.
+#
+#  halt
+#
+#     Message to display before to halting execution.
+#
+# Finally, you may exempt files based on an ERE matching file names.
+# For example, to exempt from the sc_space_tab check all files with the
+# .diff suffix, set this Make variable:
+#
+# exclude_file_name_regexp--sc_space_tab = \.diff$
+#
+# Note that while this functionality is mostly inherited via VC_LIST_EXCEPT,
+# when filtering by name via in_files, we explicitly filter out matching
+# names here as well.
+
+# By default, _sc_search_regexp does not ignore case.
+export ignore_case =
+_ignore_case = $$(test -n "$$ignore_case" && printf %s -i || :)
+
+define _sc_say_and_exit
+   dummy=; : so we do not need a semicolon before each use;            \
+   { printf '%s\n' "$(ME): $$msg" 1>&2; exit 1; };
+endef
+
+define _sc_search_regexp
+   dummy=; : so we do not need a semicolon before each use;            \
+                                                                       \
+   : Check arguments;                                                  \
+   test -n "$$prohibit" && test -n "$$require"                         \
+     && { msg='Cannot specify both prohibit and require'               \
+          $(_sc_say_and_exit) } || :;                                  \
+   test -z "$$prohibit" && test -z "$$require"                         \
+     && { msg='Should specify either prohibit or require'              \
+          $(_sc_say_and_exit) } || :;                                  \
+   test -n "$$in_vc_files" && test -n "$$in_files"                     \
+     && { msg='Cannot specify both in_vc_files and in_files'           \
+          $(_sc_say_and_exit) } || :;                                  \
+   test "x$$halt" != x                                                 \
+     || { msg='halt not defined' $(_sc_say_and_exit) };                        
\
+                                                                       \
+   : Filter by file name;                                              \
+   if test -n "$$in_files"; then                                       \
+     files=$$(find $(srcdir) | grep -E "$$in_files"                    \
+              | grep -Ev '$(exclude_file_name_regexp--$@)');           \
+   else                                                                        
\
+     files=$$($(VC_LIST_EXCEPT));                                      \
+     if test -n "$$in_vc_files"; then                                  \
+       files=$$(echo "$$files" | grep -E "$$in_vc_files");             \
+     fi;                                                               \
+   fi;                                                                 \
+                                                                       \
+   : Filter by content;                                                        
\
+   test -n "$$files" && test -n "$$containing"                         \
+     && { files=$$(grep -l "$$containing" $$files); } || :;            \
+   test -n "$$files" && test -n "$$non_containing"                     \
+     && { files=$$(grep -vl "$$non_containing" $$files); } || :;       \
+                                                                       \
+   : Check for the construct;                                          \
+   if test -n "$$files"; then                                          \
+     if test -n "$$prohibit"; then                                     \
+       grep $$with_grep_options $(_ignore_case) -nE "$$prohibit" $$files \
+         && { msg="$$halt" $(_sc_say_and_exit) } || :;                 \
+     else                                                              \
+       grep $$with_grep_options $(_ignore_case) -LE "$$require" $$files \
+           | grep .                                                    \
+         && { msg="$$halt" $(_sc_say_and_exit) } || :;                 \
+     fi                                                                        
\
+   else :;                                                             \
+   fi || :;
+endef
+
+sc_avoid_if_before_free:
+       @$(srcdir)/$(_build-aux)/useless-if-before-free                 \
+               $(useless_free_options)                                 \
+           $$($(VC_LIST_EXCEPT) | grep -v useless-if-before-free) &&   \
+         { echo '$(ME): found useless "if" before "free" above' 1>&2;  \
            exit 1; } || :
 
+sc_cast_of_argument_to_free:
+       @prohibit='\<free *\( *\(' halt='don'\''t cast free argument'   \
+         $(_sc_search_regexp)
+
 sc_cast_of_x_alloc_return_value:
-       @shopt -s nullglob;                                             \
-       grep -nE --exclude=$(srcdir)/lib/regex.c                        \
-           '\*\) *x(m|c|re)alloc\>'                                    \
-           $(srcdir)/{lib,src}/*.[chly] /dev/null &&                   \
-         { echo '$(ME): don'\''t cast x*alloc return value' 1>&2;      \
-           exit 1; } || :
+       @prohibit='\*\) *x(m|c|re)alloc\>'                              \
+       halt='don'\''t cast x*alloc return value'                       \
+         $(_sc_search_regexp)
 
 sc_cast_of_alloca_return_value:
-       @shopt -s nullglob;                                             \
-       grep -nE '\*\) *alloca\>'                                       \
-           $(srcdir)/src/*.[chly] /dev/null &&                         \
-         { echo '$(ME): don'\''t cast alloca return value' 1>&2;       \
-           exit 1; } || :
+       @prohibit='\*\) *alloca\>'                                      \
+       halt='don'\''t cast alloca return value'                        \
+         $(_sc_search_regexp)
 
 sc_space_tab:
-       @grep -n '[ ]   ' $$($(VC_LIST_EXCEPT)) &&                      \
-         { echo '$(ME): found SPACE-TAB sequence; remove the SPACE'    \
-               1>&2; exit 1; } || :
+       @prohibit='[ ]  '                                               \
+       halt='found SPACE-TAB sequence; remove the SPACE'               \
+         $(_sc_search_regexp)
 
-# Don't use *scanf or the old ato* functions in `real' code.
+# Don't use *scanf or the old ato* functions in "real" code.
 # They provide no error checking mechanism.
 # Instead, use strto* functions.
 sc_prohibit_atoi_atof:
-       @grep -nE '\<([fs]?scanf|ato([filq]|ll))\>' $$($(VC_LIST_EXCEPT)) && \
-         { echo '$(ME): do not use *scan''f, ato''f, ato''i, ato''l, ato''ll, 
ato''q, or ss''canf'     \
+       @prohibit='\<([fs]?scanf|ato([filq]|ll)) *\('                           
\
+       halt='do not use *scan''f, ato''f, ato''i, ato''l, ato''ll or ato''q'   
\
+         $(_sc_search_regexp)
+
+# Use STREQ rather than comparing strcmp == 0, or != 0.
+sc_prohibit_strcmp:
+       @grep -nE '! *str''cmp *\(|\<str''cmp *\(.+\) *[!=]='   \
+           $$($(VC_LIST_EXCEPT))                                       \
+         | grep -vE ':# *define STRN?EQ\(' &&                          \
+         { echo '$(ME): replace str''cmp calls above with STREQ/STRNEQ' \
                1>&2; exit 1; } || :
 
+# Pass EXIT_*, not number, to usage, exit, and error (when exiting)
+# Convert all uses automatically, via these two commands:
+# git grep -l '\<exit *(1)' \
+#  | grep -vEf .x-sc_prohibit_magic_number_exit \
+#  | xargs --no-run-if-empty \
+#      perl -pi -e 's/(^|[^.])\b(exit ?)\(1\)/$1$2(EXIT_FAILURE)/'
+# git grep -l '\<exit *(0)' \
+#  | grep -vEf .x-sc_prohibit_magic_number_exit \
+#  | xargs --no-run-if-empty \
+#      perl -pi -e 's/(^|[^.])\b(exit ?)\(0\)/$1$2(EXIT_SUCCESS)/'
+sc_prohibit_magic_number_exit:
+       @prohibit='(^|[^.])\<(usage|exit) ?\([0-9]|\<error ?\([1-9][0-9]*,'     
\
+       halt='use EXIT_* values rather than magic number'                       
\
+         $(_sc_search_regexp)
+
 # Using EXIT_SUCCESS as the first argument to error is misleading,
-# since when that parameter is 0, error does not exit.  Use `0' instead.
+# since when that parameter is 0, error does not exit.  Use '0' instead.
 sc_error_exit_success:
-       @grep -nF 'error (EXIT_SUCCESS,'                                \
-           $$(find -type f -name '*.[chly]') /dev/null &&              \
-         { echo '$(ME): found error (EXIT_SUCCESS' 1>&2;               \
+       @prohibit='error *\(EXIT_SUCCESS,'                              \
+       in_vc_files='\.[chly]$$'                                        \
+       halt='found error (EXIT_SUCCESS'                                \
+        $(_sc_search_regexp)
+
+# "FATAL:" should be fully upper-cased in error messages
+# "WARNING:" should be fully upper-cased, or fully lower-cased
+sc_error_message_warn_fatal:
+       @grep -nEA2 '[^rp]error *\(' $$($(VC_LIST_EXCEPT))              \
+           | grep -E '"Warning|"Fatal|"fatal' &&                       \
+         { echo '$(ME): use FATAL, WARNING or warning' 1>&2;           \
            exit 1; } || :
 
-sc_file_system:
-       @grep -ni 'file''system' $$($(VC_LIST_EXCEPT))                  \
-         | grep -v 'File''system Hierarchy Standard' &&                \
-         { echo '$(ME): found use of "file''system";'                  \
-           'rewrite to use "file system"' 1>&2;                        \
+# Error messages should not start with a capital letter
+sc_error_message_uppercase:
+       @grep -nEA2 '[^rp]error *\(' $$($(VC_LIST_EXCEPT))              \
+           | grep -E '"[A-Z]'                                          \
+           | grep -vE '"FATAL|"WARNING|"Java|"C#|PRIuMAX' &&           \
+         { echo '$(ME): found capitalized error message' 1>&2;         \
            exit 1; } || :
 
-sc_no_have_config_h:
-       @grep -n '^# *if.*HAVE''_CONFIG_H' $$($(VC_LIST_EXCEPT)) &&     \
-         { echo '$(ME): found use of HAVE''_CONFIG_H; remove'          \
-               1>&2; exit 1; } || :
+# Error messages should not end with a period
+sc_error_message_period:
+       @grep -nEA2 '[^rp]error *\(' $$($(VC_LIST_EXCEPT))              \
+           | grep -E '[^."]\."' &&                                     \
+         { echo '$(ME): found error message ending in period' 1>&2;    \
+           exit 1; } || :
 
-# Nearly all .c files must include <config.h>.
+sc_file_system:
+       @prohibit=file''system                                          \
+       ignore_case=1                                                   \
+       halt='found use of "file''system"; spell it "file system"'      \
+         $(_sc_search_regexp)
+
+# Don't use cpp tests of this symbol.  All code assumes config.h is included.
+sc_prohibit_have_config_h:
+       @prohibit='^# *if.*HAVE''_CONFIG_H'                             \
+       halt='found use of HAVE''_CONFIG_H; remove'                     \
+         $(_sc_search_regexp)
+
+# Nearly all .c files must include <config.h>.  However, we also permit this
+# via inclusion of a package-specific header, if cfg.mk specified one.
+# config_h_header must be suitable for grep -E.
+config_h_header ?= <config\.h>
 sc_require_config_h:
-       @if $(VC_LIST_EXCEPT) | grep '\.c$$' > /dev/null; then          \
-         grep -L '^# *include <config\.h>'                             \
-               $$($(VC_LIST_EXCEPT) | grep '\.c$$')                    \
-             | grep . &&                                               \
-         { echo '$(ME): the above files do not include <config.h>'     \
-               1>&2; exit 1; } || :;                                   \
+       @require='^# *include $(config_h_header)'                       \
+       in_vc_files='\.c$$'                                             \
+       halt='the above files do not include <config.h>'                \
+         $(_sc_search_regexp)
+
+# You must include <config.h> before including any other header file.
+# This can possibly be via a package-specific header, if given by cfg.mk.
+sc_require_config_h_first:
+       @if $(VC_LIST_EXCEPT) | grep -l '\.c$$' > /dev/null; then       \
+         fail=0;                                                       \
+         for i in $$($(VC_LIST_EXCEPT) | grep '\.c$$'); do             \
+           grep '^# *include\>' $$i | sed 1q                           \
+               | grep -E '^# *include $(config_h_header)' > /dev/null  \
+             || { echo $$i; fail=1; };                                 \
+         done;                                                         \
+         test $$fail = 1 &&                                            \
+           { echo '$(ME): the above files include some other header'   \
+               'before <config.h>' 1>&2; exit 1; } || :;               \
        else :;                                                         \
        fi
 
+sc_prohibit_HAVE_MBRTOWC:
+       @prohibit='\bHAVE_MBRTOWC\b'                                    \
+       halt="do not use $$prohibit; it is always defined"              \
+         $(_sc_search_regexp)
+
 # To use this "command" macro, you must first define two shell variables:
-# h: the header, enclosed in <> or ""
+# h: the header name, with no enclosing <> or ""
 # re: a regular expression that matches IFF something provided by $h is used.
-define _header_without_use
-  h_esc=`echo "$$h"|sed 's/\./\\./'`;                                  \
-  if $(VC_LIST_EXCEPT) | grep '\.c$$' > /dev/null; then                        
\
+define _sc_header_without_use
+  dummy=; : so we do not need a semicolon before each use;             \
+  h_esc=`echo '[<"]'"$$h"'[">]'|sed 's/\./\\\\./g'`;                   \
+  if $(VC_LIST_EXCEPT) | grep -l '\.c$$' > /dev/null; then             \
     files=$$(grep -l '^# *include '"$$h_esc"                           \
             $$($(VC_LIST_EXCEPT) | grep '\.c$$')) &&                   \
     grep -LE "$$re" $$files | grep . &&                                        
\
@@ -194,194 +417,567 @@ endef
 
 # Prohibit the inclusion of assert.h without an actual use of assert.
 sc_prohibit_assert_without_use:
-       @h='<assert.h>' re='\<assert *\(' $(_header_without_use)
+       @h='assert.h' re='\<assert *\(' $(_sc_header_without_use)
+
+# Prohibit the inclusion of close-stream.h without an actual use.
+sc_prohibit_close_stream_without_use:
+       @h='close-stream.h' re='\<close_stream *\(' $(_sc_header_without_use)
 
 # Prohibit the inclusion of getopt.h without an actual use.
 sc_prohibit_getopt_without_use:
-       @h='<getopt.h>' re='\<getopt(_long)? *\(' $(_header_without_use)
+       @h='getopt.h' re='\<getopt(_long)? *\(' $(_sc_header_without_use)
 
 # Don't include quotearg.h unless you use one of its functions.
 sc_prohibit_quotearg_without_use:
-       @h='"quotearg.h"' re='\<quotearg(_[^ ]+)? *\(' $(_header_without_use)
+       @h='quotearg.h' re='\<quotearg(_[^ ]+)? *\(' $(_sc_header_without_use)
 
 # Don't include quote.h unless you use one of its functions.
 sc_prohibit_quote_without_use:
-       @h='"quote.h"' re='\<quote(_n)? *\(' $(_header_without_use)
+       @h='quote.h' re='\<quote(_n)? *\(' $(_sc_header_without_use)
 
 # Don't include this header unless you use one of its functions.
 sc_prohibit_long_options_without_use:
-       @h='"long-options.h"' re='\<parse_long_options *\(' \
-         $(_header_without_use)
+       @h='long-options.h' re='\<parse_long_options *\(' \
+         $(_sc_header_without_use)
 
 # Don't include this header unless you use one of its functions.
 sc_prohibit_inttostr_without_use:
-       @h='"inttostr.h"' re='\<(off|[iu]max|uint)tostr *\(' \
-         $(_header_without_use)
+       @h='inttostr.h' re='\<(off|[iu]max|uint)tostr *\(' \
+         $(_sc_header_without_use)
+
+# Don't include this header unless you use one of its functions.
+sc_prohibit_ignore_value_without_use:
+       @h='ignore-value.h' re='\<ignore_(value|ptr) *\(' \
+         $(_sc_header_without_use)
 
 # Don't include this header unless you use one of its functions.
 sc_prohibit_error_without_use:
-       @h='"error.h"' \
+       @h='error.h' \
        re='\<error(_at_line|_print_progname|_one_per_line|_message_count)? 
*\('\
-         $(_header_without_use)
+         $(_sc_header_without_use)
+
+# Don't include xalloc.h unless you use one of its functions.
+# Consider these symbols:
+# perl -lne '/^# *define (\w+)\(/ and print $1' lib/xalloc.h|grep -v '^__';
+# perl -lne '/^(?:extern )?(?:void|char) \*?(\w+) *\(/ and print $1' 
lib/xalloc.h
+# Divide into two sets on case, and filter each through this:
+# | sort | perl -MRegexp::Assemble -le \
+#  'print Regexp::Assemble->new(file => "/dev/stdin")->as_string'|sed 
's/\?://g'
+# Note this was produced by the above:
+# _xa1 = \
+#x(((2n?)?re|c(har)?|n(re|m)|z)alloc|alloc_(oversized|die)|m(alloc|emdup)|strdup)
+# But we can do better, in at least two ways:
+# 1) take advantage of two "dup"-suffixed strings:
+# x(((2n?)?re|c(har)?|n(re|m)|[mz])alloc|alloc_(oversized|die)|(mem|str)dup)
+# 2) notice that "c(har)?|[mz]" is equivalent to the shorter and more readable
+# "char|[cmz]"
+# x(((2n?)?re|char|n(re|m)|[cmz])alloc|alloc_(oversized|die)|(mem|str)dup)
+_xa1 = x(((2n?)?re|char|n(re|m)|[cmz])alloc|alloc_(oversized|die)|(mem|str)dup)
+_xa2 = X([CZ]|N?M)ALLOC
+sc_prohibit_xalloc_without_use:
+       @h='xalloc.h' \
+       re='\<($(_xa1)|$(_xa2)) *\('\
+         $(_sc_header_without_use)
+
+# Extract function names:
+# perl -lne '/^(?:extern )?(?:void|char) \*?(\w+) *\(/ and print $1' lib/hash.h
+_hash_re = \
+clear|delete|free|get_(first|next)|insert|lookup|print_statistics|reset_tuning
+_hash_fn = \<($(_hash_re)) *\(
+_hash_struct = (struct )?\<[Hh]ash_(table|tuning)\>
+sc_prohibit_hash_without_use:
+       @h='hash.h' \
+       re='$(_hash_fn)|$(_hash_struct)'\
+         $(_sc_header_without_use)
+
+sc_prohibit_cloexec_without_use:
+       @h='cloexec.h' re='\<(set_cloexec_flag|dup_cloexec) *\(' \
+         $(_sc_header_without_use)
+
+sc_prohibit_posixver_without_use:
+       @h='posixver.h' re='\<posix2_version *\(' $(_sc_header_without_use)
+
+sc_prohibit_same_without_use:
+       @h='same.h' re='\<same_name *\(' $(_sc_header_without_use)
+
+sc_prohibit_hash_pjw_without_use:
+       @h='hash-pjw.h' \
+       re='\<hash_pjw\>' \
+         $(_sc_header_without_use)
 
 sc_prohibit_safe_read_without_use:
-       @h='"safe-read.h"' re='(\<SAFE_READ_ERROR\>|\<safe_read *\()' \
-         $(_header_without_use)
+       @h='safe-read.h' re='(\<SAFE_READ_ERROR\>|\<safe_read *\()' \
+         $(_sc_header_without_use)
 
 sc_prohibit_argmatch_without_use:
-       @h='"argmatch.h"' \
-       
re='(\<(ARRAY_CARDINALITY|X?ARGMATCH(|_TO_ARGUMENT|_VERIFY))\>|\<argmatch(_exit_fn|_(in)?valid)
 *\()' \
-         $(_header_without_use)
+       @h='argmatch.h' \
+       
re='(\<(ARRAY_CARDINALITY|X?ARGMATCH(|_TO_ARGUMENT|_VERIFY))\>|\<(invalid_arg|argmatch(_exit_fn|_(in)?valid)?)
 *\()' \
+         $(_sc_header_without_use)
+
+sc_prohibit_canonicalize_without_use:
+       @h='canonicalize.h' \
+       
re='CAN_(EXISTING|ALL_BUT_LAST|MISSING)|canonicalize_(mode_t|filename_mode)' \
+         $(_sc_header_without_use)
 
 sc_prohibit_root_dev_ino_without_use:
-       @h='"root-dev-ino.h"' \
+       @h='root-dev-ino.h' \
        re='(\<ROOT_DEV_INO_(CHECK|WARN)\>|\<get_root_dev_ino *\()' \
-         $(_header_without_use)
+         $(_sc_header_without_use)
+
+sc_prohibit_openat_without_use:
+       @h='openat.h' \
+       
re='\<(openat_(permissive|needs_fchdir|(save|restore)_fail)|l?(stat|ch(own|mod))at|(euid)?accessat)\>'
 \
+         $(_sc_header_without_use)
+
+# Prohibit the inclusion of c-ctype.h without an actual use.
+ctype_re = isalnum|isalpha|isascii|isblank|iscntrl|isdigit|isgraph|islower\
+|isprint|ispunct|isspace|isupper|isxdigit|tolower|toupper
+sc_prohibit_c_ctype_without_use:
+       @h='c-ctype.h' re='\<c_($(ctype_re)) *\(' \
+         $(_sc_header_without_use)
+
+_empty =
+_sp = $(_empty) $(_empty)
+# The following list was generated by running:
+# man signal.h|col -b|perl -ne '/bsd_signal.*;/.../sigwaitinfo.*;/ and print' \
+#   | perl -lne '/^\s+(?:int|void).*?(\w+).*/ and print $1' | fmt
+_sig_functions = \
+  bsd_signal kill killpg pthread_kill pthread_sigmask raise sigaction \
+  sigaddset sigaltstack sigdelset sigemptyset sigfillset sighold sigignore \
+  siginterrupt sigismember signal sigpause sigpending sigprocmask sigqueue \
+  sigrelse sigset sigsuspend sigtimedwait sigwait sigwaitinfo
+_sig_function_re = $(subst $(_sp),|,$(strip $(_sig_functions)))
+# The following were extracted from "man signal.h" manually.
+_sig_types_and_consts =                                                        
\
+  MINSIGSTKSZ SA_NOCLDSTOP SA_NOCLDWAIT SA_NODEFER SA_ONSTACK          \
+  SA_RESETHAND SA_RESTART SA_SIGINFO SIGEV_NONE SIGEV_SIGNAL           \
+  SIGEV_THREAD SIGSTKSZ SIG_BLOCK SIG_SETMASK SIG_UNBLOCK SS_DISABLE   \
+  SS_ONSTACK mcontext_t pid_t sig_atomic_t sigevent siginfo_t sigset_t \
+  sigstack sigval stack_t ucontext_t
+# generated via this:
+# perl -lne '/^#ifdef (SIG\w+)/ and print $1' lib/sig2str.c|sort -u|fmt -70
+_sig_names =                                                           \
+  SIGABRT SIGALRM SIGALRM1 SIGBUS SIGCANCEL SIGCHLD SIGCLD SIGCONT     \
+  SIGDANGER SIGDIL SIGEMT SIGFPE SIGFREEZE SIGGRANT SIGHUP SIGILL      \
+  SIGINFO SIGINT SIGIO SIGIOT SIGKAP SIGKILL SIGKILLTHR SIGLOST SIGLWP \
+  SIGMIGRATE SIGMSG SIGPHONE SIGPIPE SIGPOLL SIGPRE SIGPROF SIGPWR     \
+  SIGQUIT SIGRETRACT SIGSAK SIGSEGV SIGSOUND SIGSTKFLT SIGSTOP SIGSYS  \
+  SIGTERM SIGTHAW SIGTRAP SIGTSTP SIGTTIN SIGTTOU SIGURG SIGUSR1       \
+  SIGUSR2 SIGVIRT SIGVTALRM SIGWAITING SIGWINCH SIGWIND SIGWINDOW      \
+  SIGXCPU SIGXFSZ
+_sig_syms_re = $(subst $(_sp),|,$(strip $(_sig_names) 
$(_sig_types_and_consts)))
+
+# Prohibit the inclusion of signal.h without an actual use.
+sc_prohibit_signal_without_use:
+       @h='signal.h'                                                   \
+       re='\<($(_sig_function_re)) *\(|\<($(_sig_syms_re))\>'          \
+         $(_sc_header_without_use)
+
+# Don't include stdio--.h unless you use one of its functions.
+sc_prohibit_stdio--_without_use:
+       @h='stdio--.h' re='\<((f(re)?|p)open|tmpfile) *\('              \
+         $(_sc_header_without_use)
+
+# Don't include stdio-safer.h unless you use one of its functions.
+sc_prohibit_stdio-safer_without_use:
+       @h='stdio-safer.h' re='\<((f(re)?|p)open|tmpfile)_safer *\('    \
+         $(_sc_header_without_use)
+
+# Prohibit the inclusion of strings.h without a sensible use.
+# Using the likes of bcmp, bcopy, bzero, index or rindex is not sensible.
+sc_prohibit_strings_without_use:
+       @h='strings.h'                                                  \
+       re='\<(strn?casecmp|ffs(ll)?)\>'                                \
+         $(_sc_header_without_use)
+
+# Get the list of symbol names with this:
+# perl -lne '/^# *define ([A-Z]\w+)\(/ and print $1' lib/intprops.h|fmt
+_intprops_names =                                                      \
+  TYPE_IS_INTEGER TYPE_TWOS_COMPLEMENT TYPE_ONES_COMPLEMENT            \
+  TYPE_SIGNED_MAGNITUDE TYPE_SIGNED TYPE_MINIMUM TYPE_MAXIMUM          \
+  INT_BITS_STRLEN_BOUND INT_STRLEN_BOUND INT_BUFSIZE_BOUND             \
+  INT_ADD_RANGE_OVERFLOW INT_SUBTRACT_RANGE_OVERFLOW                   \
+  INT_NEGATE_RANGE_OVERFLOW INT_MULTIPLY_RANGE_OVERFLOW                        
\
+  INT_DIVIDE_RANGE_OVERFLOW INT_REMAINDER_RANGE_OVERFLOW               \
+  INT_LEFT_SHIFT_RANGE_OVERFLOW INT_ADD_OVERFLOW INT_SUBTRACT_OVERFLOW \
+  INT_NEGATE_OVERFLOW INT_MULTIPLY_OVERFLOW INT_DIVIDE_OVERFLOW                
\
+  INT_REMAINDER_OVERFLOW INT_LEFT_SHIFT_OVERFLOW
+_intprops_syms_re = $(subst $(_sp),|,$(strip $(_intprops_names)))
+# Prohibit the inclusion of intprops.h without an actual use.
+sc_prohibit_intprops_without_use:
+       @h='intprops.h'                                                 \
+       re='\<($(_intprops_syms_re)) *\('                               \
+         $(_sc_header_without_use)
+
+_stddef_syms_re = NULL|offsetof|ptrdiff_t|size_t|wchar_t
+# Prohibit the inclusion of stddef.h without an actual use.
+sc_prohibit_stddef_without_use:
+       @h='stddef.h'                                                   \
+       re='\<($(_stddef_syms_re))\>'                                   \
+         $(_sc_header_without_use)
+
+_de1 = dirfd|(close|(fd)?open|read|rewind|seek|tell)dir(64)?(_r)?
+_de2 = (versionsort|struct dirent|getdirentries|alphasort|scandir(at)?)(64)?
+_de3 = MAXNAMLEN|DIR|ino_t|d_ino|d_fileno|d_namlen
+_dirent_syms_re = $(_de1)|$(_de2)|$(_de3)
+# Prohibit the inclusion of dirent.h without an actual use.
+sc_prohibit_dirent_without_use:
+       @h='dirent.h'                                                   \
+       re='\<($(_dirent_syms_re))\>'                                   \
+         $(_sc_header_without_use)
+
+# Prohibit the inclusion of verify.h without an actual use.
+sc_prohibit_verify_without_use:
+       @h='verify.h'                                                   \
+       re='\<(verify(true|expr)?|static_assert) *\('                   \
+         $(_sc_header_without_use)
+
+# Don't include xfreopen.h unless you use one of its functions.
+sc_prohibit_xfreopen_without_use:
+       @h='xfreopen.h' re='\<xfreopen *\(' $(_sc_header_without_use)
 
 sc_obsolete_symbols:
-       @grep -nE '\<(HAVE''_FCNTL_H|O''_NDELAY)\>'                     \
-            $$($(VC_LIST_EXCEPT)) &&                                   \
-         { echo '$(ME): do not use HAVE''_FCNTL_H or O''_NDELAY'       \
-               1>&2; exit 1; } || :
+       @prohibit='\<(HAVE''_FCNTL_H|O''_NDELAY)\>'                     \
+       halt='do not use HAVE''_FCNTL_H or O'_NDELAY                    \
+         $(_sc_search_regexp)
 
 # FIXME: warn about definitions of EXIT_FAILURE, EXIT_SUCCESS, STREQ
 
-# Each nonempty line must start with a year number, or a TAB.
+# Each nonempty ChangeLog line must start with a year number, or a TAB.
 sc_changelog:
-       @grep -n '^[^12 ]' $$(find $(srcdir) -maxdepth 2 -name ChangeLog) && \
-         { echo '$(ME): found unexpected prefix in a ChangeLog' 1>&2;  \
-           exit 1; } || :
-
-# Ensure that dd's definition of LONGEST_SYMBOL stays in sync
-# with the strings from the two affected variables.
-dd_c = $(srcdir)/src/dd.c
-sc_dd_max_sym_length:
-ifneq ($(wildcard $(dd_c)),)
-       @len=$$( (sed -n '/conversions\[\] =$$/,/^};/p' $(dd_c);\
-                sed -n '/flags\[\] =$$/,/^};/p' $(dd_c) )      \
-               |sed -n '/"/s/^[^"]*"\([^"]*\)".*/\1/p'         \
-             | wc --max-line-length);                          \
-       max=$$(sed -n '/^#define LONGEST_SYMBOL /s///p' $(dd_c) \
-             |tr -d '"' | wc --max-line-length);               \
-       if test "$$len" = "$$max"; then :; else                 \
-         echo 'dd.c: LONGEST_SYMBOL is not longest' 1>&2;      \
-         exit 1;                                               \
-       fi
-endif
-
-# Many m4 macros names once began with `jm_'.
-# On 2004-04-13, they were all changed to start with gl_ instead.
-# Make sure that none are inadvertently reintroduced.
-sc_prohibit_jm_in_m4:
-       @grep -nE 'jm_[A-Z]'                                    \
-               $$($(VC_LIST) m4 |grep '\.m4$$') &&             \
-           { echo '$(ME): do not use jm_ in m4 macro names'    \
-             1>&2; exit 1; } || :
-
-sc_root_tests:
-       @t1=sc-root.expected; t2=sc-root.actual;                        \
-       grep -nl '^PRIV_CHECK_ARG=require-root'                         \
-         $$($(VC_LIST) tests) |sed s/tests/./ |sort > $$t1;            \
-       sed -n 's,      cd \([^ ]*\) .*MAKE..check TESTS=\(.*\),./\1/\2,p' \
-         $(srcdir)/tests/Makefile.am |sort > $$t2;                     \
-       diff -u $$t1 $$t2 || diff=1;                                    \
-       rm -f $$t1 $$t2;                                                \
-       test "$$diff"                                                   \
-         && { echo 'tests/Makefile.am: missing check-root action'>&2;  \
-              exit 1; } || :
-
-# Files in src/ should not include directly any of
-# the headers already included via system.h.
-sc_system_h_headers:
-       @if test -f $(srcdir)/src/system.h; then                        \
-         pat=$$(                                                       \
-           sed -n '/^# *include /s///p' $(srcdir)/src/system.h /dev/null \
-           | grep -Ev 'sys/(param|file)\.h'                            \
-           | sed 's/ .*//;;s/^["<]/^# *include [<"]/;s/\.h[">]$$/\\.h[">]/' \
-         ) &&                                                          \
-         grep -nE -f "$pat"                                            \
-             $$($(VC_LIST) src |                                       \
-                grep -Ev '((copy|system)\.h|parse-gram\.c)$$')         \
-           && { echo '$(ME): the above are already included via system.h'\
-                 1>&2;  exit 1; } || :;                                \
+       @prohibit='^[^12        ]'                                      \
+       in_vc_files='^ChangeLog$$'                                      \
+       halt='found unexpected prefix in a ChangeLog'                   \
+         $(_sc_search_regexp)
+
+# Ensure that each .c file containing a "main" function also
+# calls set_program_name.
+sc_program_name:
+       @require='set_program_name *\(m?argv\[0\]\);'                   \
+       in_vc_files='\.c$$'                                             \
+       containing='\<main *('                                          \
+       halt='the above files do not call set_program_name'             \
+         $(_sc_search_regexp)
+
+# Ensure that each .c file containing a "main" function also
+# calls bindtextdomain.
+sc_bindtextdomain:
+       @require='bindtextdomain *\('                                   \
+       in_vc_files='\.c$$'                                             \
+       containing='\<main *('                                          \
+       halt='the above files do not call bindtextdomain'               \
+         $(_sc_search_regexp)
+
+# Require that the final line of each test-lib.sh-using test be this one:
+# Exit $fail
+# Note: this test requires GNU grep's --label= option.
+Exit_witness_file ?= tests/test-lib.sh
+Exit_base := $(notdir $(Exit_witness_file))
+sc_require_test_exit_idiom:
+       @if test -f $(srcdir)/$(Exit_witness_file); then                \
+         die=0;                                                        \
+         for i in $$(grep -l -F 'srcdir/$(Exit_base)'                  \
+               $$($(VC_LIST) tests)); do                               \
+           tail -n1 $$i | grep '^Exit .' > /dev/null                   \
+             && : || { die=1; echo $$i; }                              \
+         done;                                                         \
+         test $$die = 1 &&                                             \
+           { echo 1>&2 '$(ME): the final line in each of the above is not:'; \
+             echo 1>&2 'Exit something';                               \
+             exit 1; } || :;                                           \
        fi
 
-sc_sun_os_names:
-       @grep -nEi \
-           'solaris[^[:alnum:]]*2\.(7|8|9|[1-9][0-9])|sunos[^[:alnum:]][6-9]' \
-           $$($(VC_LIST_EXCEPT)) &&                                    \
-         { echo '$(ME): found misuse of Sun OS version numbers' 1>&2;  \
-           exit 1; } || :
-
-sc_the_the:
-       @grep -ni '\<the ''the\>' $$($(VC_LIST_EXCEPT)) &&              \
-         { echo '$(ME): found use of "the ''the";' 1>&2;               \
-           exit 1; } || :
-
-sc_tight_scope:
-       test ! -d src || $(MAKE) -C src $@
-
 sc_trailing_blank:
-       @grep -n '[      ]$$' $$($(VC_LIST_EXCEPT)) &&                  \
-         { echo '$(ME): found trailing blank(s)'                       \
-               1>&2; exit 1; } || :
+       @prohibit='[     ]$$'                                           \
+       halt='found trailing blank(s)'                                  \
+         $(_sc_search_regexp)
 
 # Match lines like the following, but where there is only one space
 # between the options and the description:
 #   -D, --all-repeated[=delimit-method]  print all duplicate lines\n
 longopt_re = --[a-z][0-9A-Za-z-]*(\[?=[0-9A-Za-z-]*\]?)?
 sc_two_space_separator_in_usage:
-       @grep -nE '^   *(-[A-Za-z],)? $(longopt_re) [^ ].*\\$$'         \
-           $$($(VC_LIST_EXCEPT)) &&                                    \
-         { echo "$(ME): help2man requires at least two spaces between"; \
-           echo "$(ME): an option and its description"; \
-               1>&2; exit 1; } || :
+       @prohibit='^   *(-[A-Za-z],)? $(longopt_re) [^ ].*\\$$'         \
+       halt='help2man requires at least two spaces between an option and its 
description'\
+         $(_sc_search_regexp)
+
+# A regexp matching function names like "error" that may be used
+# to emit translatable messages.
+_gl_translatable_diag_func_re ?= error
 
 # Look for diagnostics that aren't marked for translation.
 # This won't find any for which error's format string is on a separate line.
 sc_unmarked_diagnostics:
        @grep -nE                                                       \
-           '\<error \([^"]*"[^"]*[a-z]{3}' $$($(VC_LIST_EXCEPT))       \
-         | grep -v '_''(' &&                                           \
+           '\<$(_gl_translatable_diag_func_re) *\([^"]*"[^"]*[a-z]{3}' \
+               $$($(VC_LIST_EXCEPT))                                   \
+         | grep -Ev '(_|ngettext ?)\(' &&                              \
          { echo '$(ME): found unmarked diagnostic(s)' 1>&2;            \
            exit 1; } || :
 
 # Avoid useless parentheses like those in this example:
 # #if defined (SYMBOL) || defined (SYM2)
 sc_useless_cpp_parens:
-       @grep -n '^# *if .*defined *(' $$($(VC_LIST_EXCEPT)) &&         \
-         { echo '$(ME): found useless parentheses in cpp directive'    \
-               1>&2; exit 1; } || :
+       @prohibit='^# *if .*defined *\('                                \
+       halt='found useless parentheses in cpp directive'               \
+         $(_sc_search_regexp)
+
+# List headers for which HAVE_HEADER_H is always true, assuming you are
+# using the appropriate gnulib module.  CAUTION: for each "unnecessary"
+# #if HAVE_HEADER_H that you remove, be sure that your project explicitly
+# requires the gnulib module that guarantees the usability of that header.
+gl_assured_headers_ = \
+  cd $(gnulib_dir)/lib && echo *.in.h|sed 's/\.in\.h//g'
+
+# Convert the list of names to upper case, and replace each space with "|".
+az_ = abcdefghijklmnopqrstuvwxyz
+AZ_ = ABCDEFGHIJKLMNOPQRSTUVWXYZ
+gl_header_upper_case_or_ =                                             \
+  $$($(gl_assured_headers_)                                            \
+    | tr $(az_)/.- $(AZ_)___                                           \
+    | tr -s ' ' '|'                                                    \
+    )
+sc_prohibit_always_true_header_tests:
+       @or=$(gl_header_upper_case_or_);                                \
+       re="HAVE_($$or)_H";                                             \
+       prohibit='\<'"$$re"'\>'                                         \
+       halt=$$(printf '%s\n'                                           \
+       'do not test the above HAVE_<header>_H symbol(s);'              \
+       '  with the corresponding gnulib module, they are always true') \
+         $(_sc_search_regexp)
+
+# ==================================================================
+gl_other_headers_ ?= \
+  intprops.h   \
+  openat.h     \
+  stat-macros.h
+
+# Perl -lne code to extract "significant" cpp-defined symbols from a
+# gnulib header file, eliminating a few common false-positives.
+# The exempted names below are defined only conditionally in gnulib,
+# and hence sometimes must/may be defined in application code.
+gl_extract_significant_defines_ = \
+  /^\# *define ([^_ (][^ (]*)(\s*\(|\s+\w+)/\
+    && $$2 !~ /(?:rpl_|_used_without_)/\
+    && $$1 !~ /^(?:NSIG|ENODATA)$$/\
+    && $$1 !~ /^(?:SA_RESETHAND|SA_RESTART)$$/\
+    and print $$1
+
+# Create a list of regular expressions matching the names
+# of macros that are guaranteed to be defined by parts of gnulib.
+define def_sym_regex
+       gen_h=$(gl_generated_headers_);                                 \
+       (cd $(gnulib_dir)/lib;                                          \
+         for f in *.in.h $(gl_other_headers_); do                      \
+           test -f $$f                                                 \
+             && perl -lne '$(gl_extract_significant_defines_)' $$f;    \
+         done;                                                         \
+       ) | sort -u                                                     \
+         | sed 's/^/^ *# *(define|undef)  */;s/$$/\\>/'
+endef
 
-# Ensure that the c99-to-c89 patch applies cleanly.
-patch-check:
-       if test -f src/c99-to-c89.diff; then                            \
-         rm -rf src-c89 address@hidden address@hidden &&                       
                \
-         cp -a src src-c89 &&                                          \
-         (cd src-c89; patch -V never --fuzz=0) < src/c99-to-c89.diff   \
-           > address@hidden 2>&1 &&                                            
\
-         { grep -v '^patching file ' address@hidden > address@hidden || :; } 
&&                \
-         test -s address@hidden &&                                             
\
-         rm -rf src-c89 address@hidden address@hidden;                         
        \
+# Don't define macros that we already get from gnulib header files.
+sc_prohibit_always-defined_macros:
+       @if test -d $(gnulib_dir); then                                 \
+         case $$(echo all: | grep -l -f - Makefile) in Makefile);; *)  \
+           echo '$(ME): skipping $@: you lack GNU grep' 1>&2; exit 0;; \
+         esac;                                                         \
+         $(def_sym_regex) | grep -E -f - $$($(VC_LIST_EXCEPT))         \
+           && { echo '$(ME): define the above via some gnulib .h file' \
+                 1>&2;  exit 1; } || :;                                \
        fi
+# ==================================================================
+
+# Prohibit checked in backup files.
+sc_prohibit_backup_files:
+       @$(VC_LIST) | grep '~$$' &&                             \
+         { echo '$(ME): found version controlled backup file' 1>&2;    \
+           exit 1; } || :
+
+# Require the latest GPL.
+sc_GPL_version:
+       @prohibit='either ''version [^3]'                               \
+       halt='GPL vN, N!=3'                                             \
+         $(_sc_search_regexp)
+
+# Require the latest GFDL.  Two regexp, since some .texi files end up
+# line wrapping between 'Free Documentation License,' and 'Version'.
+_GFDL_regexp = (Free ''Documentation.*Version 1\.[^3]|Version 1\.[^3] or any)
+sc_GFDL_version:
+       @prohibit='$(_GFDL_regexp)'                                     \
+       halt='GFDL vN, N!=3'                                            \
+         $(_sc_search_regexp)
+
+# Don't use Texinfo's @acronym{}.
+# http://lists.gnu.org/archive/html/bug-gnulib/2010-03/msg00321.html
+texinfo_suffix_re_ ?= \.(txi|texi(nfo)?)$$
+sc_texinfo_acronym:
+       @prohibit='@acronym\{'                                          \
+       in_vc_files='$(texinfo_suffix_re_)'                             \
+       halt='found use of Texinfo @acronym{}'                          \
+         $(_sc_search_regexp)
+
+cvs_keywords = \
+  Author|Date|Header|Id|Name|Locker|Log|RCSfile|Revision|Source|State
+
+sc_prohibit_cvs_keyword:
+       @prohibit='\$$($(cvs_keywords))\$$'                             \
+       halt='do not use CVS keyword expansion'                         \
+         $(_sc_search_regexp)
+
+# This Perl code is slightly obfuscated.  Not only is each "$" doubled
+# because it's in a Makefile, but the $$c's are comments;  we cannot
+# use "#" due to the way the script ends up concatenated onto one line.
+# It would be much more concise, and would produce better output (including
+# counts) if written as:
+#   perl -ln -0777 -e '/\n(\n+)$/ and print "$ARGV: ".length $1' ...
+# but that would be far less efficient, reading the entire contents
+# of each file, rather than just the last two bytes of each.
+# In addition, while the code below detects both blank lines and a missing
+# newline at EOF, the above detects only the former.
+#
+# This is a perl script that is expected to be the single-quoted argument
+# to a command-line "-le".  The remaining arguments are file names.
+# Print the name of each file that does not end in exactly one newline byte.
+# I.e., warn if there are blank lines (2 or more newlines), or if the
+# last byte is not a newline.  However, currently we don't complain
+# about any file that contains exactly one byte.
+# Exit nonzero if at least one such file is found, otherwise, exit 0.
+# Warn about, but otherwise ignore open failure.  Ignore seek/read failure.
+#
+# Use this if you want to remove trailing empty lines from selected files:
+#   perl -pi -0777 -e 's/\n\n+$/\n/' files...
+#
+require_exactly_one_NL_at_EOF_ =                                       \
+  foreach my $$f (@ARGV)                                               \
+    {                                                                  \
+      open F, "<", $$f or (warn "failed to open $$f: $$!\n"), next;    \
+      my $$p = sysseek (F, -2, 2);                                     \
+      my $$c = "seek failure probably means file has < 2 bytes; ignore"; \
+      my $$last_two_bytes;                                             \
+      defined $$p and $$p = sysread F, $$last_two_bytes, 2;            \
+      close F;                                                         \
+      $$c = "ignore read failure";                                     \
+      $$p && ($$last_two_bytes eq "\n\n"                               \
+              || substr ($$last_two_bytes,1) ne "\n")                  \
+          and (print $$f), $$fail=1;                                   \
+    }                                                                  \
+  END { exit defined $$fail }
+sc_prohibit_empty_lines_at_EOF:
+       @perl -le '$(require_exactly_one_NL_at_EOF_)' $$($(VC_LIST_EXCEPT)) \
+         || { echo '$(ME): empty line(s) or no newline at EOF'         \
+               1>&2; exit 1; } || :
 
-# Ensure that date's --help output stays in sync with the info
-# documentation for GNU strftime.  The only exception is %N,
-# which date accepts but GNU strftime does not.
-extract_char = sed 's/^[^%][^%]*%\(.\).*/\1/'
-strftime-check:
-       if test -f $(srcdir)/src/date.c; then                           \
-         grep '^  %.  ' $(srcdir)/src/date.c | sort                    \
-           | $(extract_char) > address@hidden;                                 
\
-         { echo N;                                                     \
-           info libc date calendar format | grep '^    `%.'\'          \
-             | $(extract_char); } | sort > address@hidden;                     
\
-         diff -u address@hidden address@hidden || exit 1;                      
        \
-         rm -f address@hidden address@hidden;                                  
        \
+# Make sure we don't use st_blocks.  Use ST_NBLOCKS instead.
+# This is a bit of a kludge, since it prevents use of the string
+# even in comments, but for now it does the job with no false positives.
+sc_prohibit_stat_st_blocks:
+       @prohibit='[.>]st_blocks'                                       \
+       halt='do not use st_blocks; use ST_NBLOCKS'                     \
+         $(_sc_search_regexp)
+
+# Make sure we don't define any S_IS* macros in src/*.c files.
+# They're already defined via gnulib's sys/stat.h replacement.
+sc_prohibit_S_IS_definition:
+       @prohibit='^ *# *define  *S_IS'                                 \
+       halt='do not define S_IS* macros; include <sys/stat.h>'         \
+         $(_sc_search_regexp)
+
+# Perl block to convert a match to FILE_NAME:LINENO:TEST,
+# that is shared by two definitions below.
+perl_filename_lineno_text_ =                                           \
+    -e '  {'                                                           \
+    -e '    $$n = ($$` =~ tr/\n/\n/ + 1);'                             \
+    -e '    ($$v = $$&) =~ s/\n/\\n/g;'                                        
\
+    -e '    print "$$ARGV:$$n:$$v\n";'                                 \
+    -e '  }'
+
+prohibit_doubled_word_RE_ ?= \
+  /\b(then?|[iao]n|i[fst]|but|f?or|at|and|[dt]o)\s+\1\b/gims
+prohibit_doubled_word_ =                                               \
+    -e 'while ($(prohibit_doubled_word_RE_))'                          \
+    $(perl_filename_lineno_text_)
+
+# Define this to a regular expression that matches
+# any filename:dd:match lines you want to ignore.
+# The default is to ignore no matches.
+ignore_doubled_word_match_RE_ ?= ^$$
+
+sc_prohibit_doubled_word:
+       @perl -n -0777 $(prohibit_doubled_word_) $$($(VC_LIST_EXCEPT))  \
+         | grep -vE '$(ignore_doubled_word_match_RE_)'                 \
+         | grep . && { echo '$(ME): doubled words' 1>&2; exit 1; } || :
+
+# A regular expression matching undesirable combinations of words like
+# "can not"; this matches them even when the two words appear on different
+# lines, but not when there is an intervening delimiter like "#" or "*".
+prohibit_undesirable_word_seq_RE_ ?=                                   \
+  /\bcan\s+not\b/gims
+prohibit_undesirable_word_seq_ =                                       \
+    -e 'while ($(prohibit_undesirable_word_seq_RE_))'                  \
+    $(perl_filename_lineno_text_)
+# Define this to a regular expression that matches
+# any filename:dd:match lines you want to ignore.
+# The default is to ignore no matches.
+ignore_undesirable_word_sequence_RE_ ?= ^$$
+
+sc_prohibit_undesirable_word_seq:
+       @perl -n -0777 $(prohibit_undesirable_word_seq_)                \
+            $$($(VC_LIST_EXCEPT))                                      \
+         | grep -vE '$(ignore_undesirable_word_sequence_RE_)' | grep . \
+         && { echo '$(ME): undesirable word sequence' >&2; exit 1; } || :
+
+_ptm1 = use "test C1 && test C2", not "test C1 -''a C2"
+_ptm2 = use "test C1 || test C2", not "test C1 -''o C2"
+# Using test's -a and -o operators is not portable.
+# We prefer test over [, since the latter is spelled [[ in configure.ac.
+sc_prohibit_test_minus_ao:
+       @prohibit='(\<test| \[+) .+ -[ao] '                             \
+       halt='$(_ptm1); $(_ptm2)'                                       \
+         $(_sc_search_regexp)
+
+# Avoid a test bashism.
+sc_prohibit_test_double_equal:
+       @prohibit='(\<test| \[+) .+ == '                                \
+       containing='#! */bin/[a-z]*sh'                                  \
+       halt='use "test x = x", not "test x =''= x"'                    \
+         $(_sc_search_regexp)
+
+# Each program that uses proper_name_utf8 must link with one of the
+# ICONV libraries.  Otherwise, some ICONV library must appear in LDADD.
+# The perl -0777 invocation below extracts the possibly-multi-line
+# definition of LDADD from the appropriate Makefile.am and exits 0
+# when it contains "ICONV".
+sc_proper_name_utf8_requires_ICONV:
+       @progs=$$(grep -l 'proper_name_utf8 ''("' $$($(VC_LIST_EXCEPT)));\
+       if test "x$$progs" != x; then                                   \
+         fail=0;                                                       \
+         for p in $$progs; do                                          \
+           dir=$$(dirname "$$p");                                      \
+           perl -0777                                                  \
+             -ne 'exit !(/^LDADD =(.+?[^\\]\n)/ms && $$1 =~ /ICONV/)'  \
+             $$dir/Makefile.am && continue;                            \
+           base=$$(basename "$$p" .c);                                 \
+           grep "$${base}_LDADD.*ICONV)" $$dir/Makefile.am > /dev/null \
+             || { fail=1; echo 1>&2 "$(ME): $$p uses proper_name_utf8"; }; \
+         done;                                                         \
+         test $$fail = 1 &&                                            \
+           { echo 1>&2 '$(ME): the above do not link with any ICONV library'; \
+             exit 1; } || :;                                           \
        fi
 
-check-AUTHORS:
-       test ! -d src || $(MAKE) -C src $@
+# Warn about "c0nst struct Foo const foo[]",
+# but not about "char const *const foo" or "#define const const".
+sc_redundant_const:
+       @prohibit='\bconst\b[[:space:][:alnum:]]{2,}\bconst\b'          \
+       halt='redundant "const" in declarations'                        \
+         $(_sc_search_regexp)
+
+sc_const_long_option:
+       @grep '^ *static.*struct option ' $$($(VC_LIST_EXCEPT))         \
+         | grep -Ev 'const struct option|struct option const' && {     \
+             echo 1>&2 '$(ME): add "const" to the above declarations'; \
+             exit 1; } || :
 
 NEWS_hash =                                                            \
   $$(sed -n '/^\*.* $(PREV_VERSION_REGEXP) ([0-9-]*)/,$$p'             \
@@ -407,46 +1003,64 @@ update-NEWS-hash: NEWS
 # Ensure that we use only the standard $(VAR) notation,
 # not @...@ in Makefile.am, now that we can rely on automake
 # to emit a definition for each substituted variable.
-makefile-check:
-       grep -nE '@[A-Z_0-9]+@' `find $(srcdir) -name Makefile.am` \
+# However, there is still one case in which @VAR@ use is not just
+# legitimate, but actually required: when augmenting an automake-defined
+# variable with a prefix.  For example, gettext uses this:
+# MAKEINFO = env LANG= LC_MESSAGES= LC_ALL= LANGUAGE= @MAKEINFO@
+# otherwise, makeinfo would put German or French (current locale)
+# navigation hints in the otherwise-English documentation.
+#
+# Allow the package to add exceptions via a hook in cfg.mk;
+# for example, @PRAGMA_SYSTEM_HEADER@ can be permitted by
+# setting this to ' && !/PRAGMA_SYSTEM_HEADER/'.
+_makefile_at_at_check_exceptions ?=
+sc_makefile_at_at_check:
+       @perl -ne '/address@hidden@/'                                   \
+          -e ' && !/([A-Z_0-9]+)address@hidden@$$/'                    \
+          -e ''$(_makefile_at_at_check_exceptions)                     \
+         -e 'and (print "$$ARGV:$$.: $$_"), $$m=1; END {exit !$$m}'    \
+           $$($(VC_LIST_EXCEPT) | grep -E '(^|/)(Makefile\.am|[^/]+\.mk)$$') \
          && { echo '$(ME): use $$(...), not @...@' 1>&2; exit 1; } || :
 
-news-date-check: NEWS
-       today=`date +%Y-%m-%d`;                                         \
-       if head NEWS | grep '^\*.* $(VERSION_REGEXP) ('$$today')'       \
-           >/dev/null; then                                            \
+news-check: NEWS
+       if sed -n $(news-check-lines-spec)p $(srcdir)/NEWS              \
+           | grep -E $(news-check-regexp) >/dev/null; then             \
          :;                                                            \
        else                                                            \
-         echo "version or today's date is not in NEWS" 1>&2;           \
+         echo 'NEWS: $$(news-check-regexp) failed to match' 1>&2;      \
          exit 1;                                                       \
        fi
 
-changelog-check:
-       if head ChangeLog | grep 'Version $(VERSION_REGEXP)\.$$'        \
-           >/dev/null; then                                            \
-         :;                                                            \
-       else                                                            \
-         echo "$(VERSION) not in ChangeLog" 1>&2;                      \
-         exit 1;                                                       \
-       fi
+sc_makefile_TAB_only_indentation:
+       @prohibit='^    [ ]{8}'                                         \
+       in_vc_files='akefile|\.mk$$'                                    \
+       halt='found TAB-8-space indentation'                            \
+         $(_sc_search_regexp)
 
-m4-check:
-       @shopt -s nullglob;                                             \
-       grep 'AC_DEFUN([^[]' m4/*.m4 /dev/null                          \
-         && { echo '$(ME): quote the first arg to AC_DEFUN' 1>&2; \
-              exit 1; } || :
+sc_m4_quote_check:
+       @prohibit='(AC_DEFINE(_UNQUOTED)?|AC_DEFUN)\([^[]'              \
+       in_vc_files='(^configure\.ac|\.m4)$$'                           \
+       halt='quote the first arg to AC_DEF*'                           \
+         $(_sc_search_regexp)
+
+fix_po_file_diag = \
+'you have changed the set of files with translatable diagnostics;\n\
+apply the above patch\n'
 
 # Verify that all source files using _() are listed in po/POTFILES.in.
-# FIXME: don't hard-code file names below; use a more general mechanism.
-po-check:
-       if test -f po/POTFILES.in; then                                 \
-         grep -E -v '^(#|$$)' po/POTFILES.in                           \
+po_file ?= $(srcdir)/po/POTFILES.in
+generated_files ?= $(srcdir)/lib/*.[ch]
+sc_po_check:
+       @if test -f $(po_file); then                                    \
+         grep -E -v '^(#|$$)' $(po_file)                               \
            | grep -v '^src/false\.c$$' | sort > address@hidden;                
        \
          files=;                                                       \
-         for file in $$($(VC_LIST_EXCEPT)) lib/*.[ch]; do              \
+         for file in $$($(VC_LIST_EXCEPT)) $(generated_files); do      \
+           test -r $$file || continue;                                 \
            case $$file in                                              \
-           djgpp/* | man/*) continue;;                                 \
-           */c99-to-c89.diff) continue;;                               \
+             *.m4|*.mk) continue ;;                                    \
+             *.?|*.??) ;;                                              \
+             *) continue;;                                             \
            esac;                                                       \
            case $$file in                                              \
            *.[ch])                                                     \
@@ -456,57 +1070,123 @@ po-check:
            files="$$files $$file";                                     \
          done;                                                         \
          grep -E -l '\b(N?_|gettext *)\([^)"]*("|$$)' $$files          \
-           | sort -u > address@hidden;                                         
\
-         diff -u address@hidden address@hidden || exit 1;                      
                \
+           | sed 's|^$(_dot_escaped_srcdir)/||' | sort -u > address@hidden;    
\
+         diff -u -L $(po_file) -L $(po_file) address@hidden address@hidden     
                \
+           || { printf '$(ME): '$(fix_po_file_diag) 1>&2; exit 1; };   \
          rm -f address@hidden address@hidden;                                  
        \
        fi
 
-# In a definition of #define AUTHORS "... and ..." where the RHS contains
-# the English word `and', the string must be marked with `N_ (...)' so that
-# gettext recognizes it as a string requiring translation.
-author_mark_check:
-       @shopt -s nullglob;                                             \
-       grep -n '^# *define AUTHORS "[^"]* and ' src/*.c /dev/null      \
-         | grep -v ' N_ (' &&                                          \
-         { echo '$(ME): enclose the above strings in N_ (...)' 1>&2; \
-           exit 1; } || :
-
 # Sometimes it is useful to change the PATH environment variable
 # in Makefiles.  When doing so, it's better not to use the Unix-centric
-# path separator of `:', but rather the automake-provided address@hidden@'.
-# It'd be better to use `find -print0 ...|xargs -0 ...', but less portable,
-# and there probably aren't many projects with so many Makefile.am files
-# that we'd have to worry about limits on command line length.
-msg = '$(ME): Do not use `:'\'' above; use @PATH_SEPARATOR@ instead'
-makefile_path_separator_check:
-       @grep -n 'PATH=.*:' `find $(srcdir) -name Makefile.am` \
-         && { echo $(msg) 1>&2; exit 1; } || :
-
-# Check that `make alpha' will not fail at the end of the process.
+# path separator of ':', but rather the automake-provided '$(PATH_SEPARATOR)'.
+msg = '$(ME): Do not use '\'':'\'' above; use $$(PATH_SEPARATOR) instead'
+sc_makefile_path_separator_check:
+       @prohibit='PATH[=].*:'                                          \
+       in_vc_files='akefile|\.mk$$'                                    \
+       halt=$(msg)                                                     \
+         $(_sc_search_regexp)
+
+# Check that 'make alpha' will not fail at the end of the process,
+# i.e., when pkg-M.N.tar.xz already exists (either in "." or in ../release)
+# and is read-only.
 writable-files:
-       if test -d $(release_archive_dir); then :; else                 \
-         mkdir $(release_archive_dir);                                 \
+       if test -d $(release_archive_dir); then                         \
+         for file in $(DIST_ARCHIVES); do                              \
+           for p in ./ $(release_archive_dir)/; do                     \
+             test -e $$p$$file || continue;                            \
+             test -w $$p$$file                                         \
+               || { echo ERROR: $$p$$file is not writable; fail=1; };  \
+           done;                                                       \
+         done;                                                         \
+         test "$$fail" && exit 1 || : ;                                \
+       else :;                                                         \
        fi
-       for file in $(distdir).tar.gz                                   \
-                   $(release_archive_dir)/$(distdir).tar.gz; do        \
-         test -e $$file || continue;                                   \
-         test -w $$file                                                \
-           || { echo ERROR: $$file is not writable; fail=1; };         \
-       done;                                                           \
-       test "$$fail" && exit 1 || :
 
-v_etc_file = lib/version-etc.c
+v_etc_file = $(gnulib_dir)/lib/version-etc.c
+sample-test = tests/sample-test
+texi = doc/$(PACKAGE).texi
 # Make sure that the copyright date in $(v_etc_file) is up to date.
-copyright-check:
-       @if test -f $(v_etc_file); then \
-         grep 'enum { COPYRIGHT_YEAR = '$$(date +%Y)' };' $(v_etc_file) \
-           >/dev/null \
-         || { echo 'out of date copyright in $(v_etc_file); update it' 1>&2; \
-              exit 1; }; \
+# Do the same for the $(sample-test) and the main doc/.texi file.
+sc_copyright_check:
+       @require='enum { COPYRIGHT_YEAR = '$$(date +%Y)' };'            \
+       in_files=$(v_etc_file)                                          \
+       halt='out of date copyright in $(v_etc_file); update it'        \
+         $(_sc_search_regexp)
+       @require='# Copyright \(C\) '$$(date +%Y)' Free'                \
+       in_vc_files=$(sample-test)                                      \
+       halt='out of date copyright in $(sample-test); update it'       \
+         $(_sc_search_regexp)
+       @require='Copyright @copyright\{\} .*'$$(date +%Y)' Free'       \
+       in_vc_files=$(texi)                                             \
+       halt='out of date copyright in $(texi); update it'              \
+         $(_sc_search_regexp)
+
+# If tests/help-version exists and seems to be new enough, assume that its
+# use of init.sh and path_prepend_ is correct, and ensure that every other
+# use of init.sh is identical.
+# This is useful because help-version cross-checks prog --version
+# with $(VERSION), which verifies that its path_prepend_ invocation
+# sets PATH correctly.  This is an inexpensive way to ensure that
+# the other init.sh-using tests also get it right.
+_hv_file ?= $(srcdir)/tests/help-version
+_hv_regex_weak ?= ^ *\. .*/init\.sh"
+# Fix syntax-highlighters "
+_hv_regex_strong ?= ^ *\. "\$${srcdir=\.}/init\.sh"
+sc_cross_check_PATH_usage_in_tests:
+       @if test -f $(_hv_file); then                                   \
+         grep -l 'VERSION mismatch' $(_hv_file) >/dev/null             \
+           || { echo "$@: skipped: no such file: $(_hv_file)" 1>&2;    \
+                exit 0; };                                             \
+         grep -lE '$(_hv_regex_strong)' $(_hv_file) >/dev/null         \
+           || { echo "$@: $(_hv_file) lacks conforming use of init.sh" 1>&2; \
+                exit 1; };                                             \
+         good=$$(grep -E '$(_hv_regex_strong)' $(_hv_file));           \
+         grep -LFx "$$good"                                            \
+               $$(grep -lE '$(_hv_regex_weak)' $$($(VC_LIST_EXCEPT)))  \
+             | grep . &&                                               \
+           { echo "$(ME): the above files use path_prepend_ inconsistently" \
+               1>&2; exit 1; } || :;                                   \
        fi
 
+# BRE regex of file contents to identify a test script.
+_test_script_regex ?= \<init\.sh\>
+
+# In tests, use "compare expected actual", not the reverse.
+sc_prohibit_reversed_compare_failure:
+       @prohibit='\<compare [^ ]+ ([^ ]*exp|/dev/null)'                \
+       containing='$(_test_script_regex)'                              \
+       halt='reversed compare arguments'                               \
+         $(_sc_search_regexp)
+
+# #if HAVE_... will evaluate to false for any non numeric string.
+# That would be flagged by using -Wundef, however gnulib currently
+# tests many undefined macros, and so we can't enable that option.
+# So at least preclude common boolean strings as macro values.
+sc_Wundef_boolean:
+       @prohibit='^#define.*(yes|no|true|false)$$'                     \
+       in_files='$(CONFIG_INCLUDE)'                                    \
+       halt='Use 0 or 1 for macro values'                              \
+         $(_sc_search_regexp)
+
+# Even if you use pathmax.h to guarantee that PATH_MAX is defined, it might
+# not be constant, or might overflow a stack.  In general, use PATH_MAX as
+# a limit, not an array or alloca size.
+sc_prohibit_path_max_allocation:
+       @prohibit='(\balloca *\([^)]*|\[[^]]*)PATH_MAX'                 \
+       halt='Avoid stack allocations of size PATH_MAX'                 \
+         $(_sc_search_regexp)
+
+sc_vulnerable_makefile_CVE-2009-4029:
+       @prohibit='perm -777 -exec chmod a\+rwx|chmod 777 \$$\(distdir\)' \
+       in_files=$$(find $(srcdir) -name Makefile.in)                   \
+       halt=$$(printf '%s\n'                                           \
+         'the above files are vulnerable; beware of running'           \
+         '  "make dist*" rules, and upgrade to fixed automake'         \
+         '  see http://bugzilla.redhat.com/542609 for details')        \
+         $(_sc_search_regexp)
+
 vc-diff-check:
-       (CDPATH=; cd $(srcdir) && $(VC) diff) > vc-diffs || :
+       (unset CDPATH; cd $(srcdir) && $(VC) diff) > vc-diffs || :
        if test -s vc-diffs; then                               \
          cat vc-diffs;                                         \
          echo "Some files are locally modified:" 1>&2;         \
@@ -515,57 +1195,6 @@ vc-diff-check:
          rm vc-diffs;                                          \
        fi
 
-cvs-check: vc-diff-check
-
-maintainer-distcheck:
-       $(MAKE) distcheck
-       $(MAKE) -C tests $(AM_MAKEFLAGS) maintainer-check
-       $(MAKE) my-distcheck
-
-# Don't make a distribution if checks fail.
-# Also, make sure the NEWS file is up-to-date.
-vc-dist: $(local-check) cvs-check maintainer-distcheck
-       $(MAKE) dist
-
-# Use this to make sure we don't run these programs when building
-# from a virgin tgz file, below.
-null_AM_MAKEFLAGS = \
-  ACLOCAL=false \
-  AUTOCONF=false \
-  AUTOMAKE=false \
-  AUTOHEADER=false \
-  MAKEINFO=false
-
-# Detect format-string/arg-list mismatches that would normally be obscured
-# by the use of _().  The --disable-nls effectively defines away that macro,
-# and building with CFLAGS='-Wformat -Werror' causes any format warning to be
-# treated as a failure.  Also, check for shadowing problems with -Wshadow,
-# and for pointer arithmetic problems with -Wpointer-arith.
-# These CFLAGS are pretty strict.  If you build this target, you probably
-# have to have a recent version of gcc and glibc headers.
-TMPDIR ?= /tmp
-t=$(TMPDIR)/$(PACKAGE)/test
-my-distcheck: $(local-check) $(release_archive_dir)/$(prev-tgz)
-       -rm -rf $(t)
-       mkdir -p $(t)
-       GZIP=$(GZIP_ENV) $(AMTAR) -C $(t) -zxf $(distdir).tar.gz
-       cd $(t)/$(distdir)                              \
-         && ./configure --disable-nls                  \
-         && $(MAKE) CFLAGS='-Werror -Wall -Wformat -Wshadow -Wpointer-arith' \
-             AM_MAKEFLAGS='$(null_AM_MAKEFLAGS)'       \
-         && $(MAKE) dvi                                \
-         && $(MAKE) check                              \
-         && $(MAKE) distclean
-       (cd $(t) && mv $(distdir) $(distdir).old        \
-         && $(AMTAR) -zxf - ) < $(distdir).tar.gz
-       diff -ur $(t)/$(distdir).old $(t)/$(distdir)
-       -rm -rf $(t)
-       @echo "========================"; \
-       echo "$(distdir).tar.gz is ready for distribution"; \
-       echo "========================"
-
-prev-tgz = $(PACKAGE)-$(PREV_VERSION).tar.gz
-
 rel-files = $(DIST_ARCHIVES)
 
 gnulib_dir ?= $(srcdir)/gnulib
@@ -575,19 +1204,28 @@ bootstrap-tools ?= autoconf,automake,gnulib
 # If it's not already specified, derive the GPG key ID from
 # the signed tag we've just applied to mark this release.
 gpg_key_ID ?= \
-  $$(git cat-file tag v$(VERSION) > .ann-sig \
-     && gpgv .ann-sig - < /dev/null 2>&1 \
-         | sed -n '/.*key ID \([0-9A-F]*\)/s//\1/p'; rm -f .ann-sig)
+  $$(git cat-file tag v$(VERSION) \
+     | gpgv --status-fd 1 --keyring /dev/null - - 2>/dev/null \
+     | sed -n '/^\[GNUPG:\] ERRSIG /{s///;s/ .*//p;q}')
 
 translation_project_ ?= address@hidden
-announcement_Cc_ ?= $(translation_project_), $(PACKAGE_BUGREPORT)
-announcement_mail_headers_ ?=                                          \
-To: address@hidden                                                     \
-Cc: $(announcement_Cc_)                                                        
\
-Mail-Followup-To: $(PACKAGE_BUGREPORT)
+
+# Make info-gnu the default only for a stable release.
+ifeq ($(RELEASE_TYPE),stable)
+  announcement_Cc_ ?= $(translation_project_), $(PACKAGE_BUGREPORT)
+  announcement_mail_headers_ ?=                                                
\
+    To: address@hidden                                         \
+    Cc: $(announcement_Cc_)                                            \
+    Mail-Followup-To: $(PACKAGE_BUGREPORT)
+else
+  announcement_Cc_ ?= $(translation_project_)
+  announcement_mail_headers_ ?=                                                
\
+    To: $(PACKAGE_BUGREPORT)                                           \
+    Cc: $(announcement_Cc_)
+endif
 
 announcement: NEWS ChangeLog $(rel-files)
-       @$(build_aux)/announce-gen                                      \
+       @$(srcdir)/$(_build-aux)/announce-gen                           \
            --mail-headers='$(announcement_mail_headers_)'              \
            --release-type=$(RELEASE_TYPE)                              \
            --package=$(PACKAGE)                                        \
@@ -596,6 +1234,7 @@ announcement: NEWS ChangeLog $(rel-files)
            --gpg-key-id=$(gpg_key_ID)                                  \
            --news=$(srcdir)/NEWS                                       \
            --bootstrap-tools=$(bootstrap-tools)                        \
+           --gnulib-version=$(gnulib-version)                          \
            --no-print-checksums                                        \
            $(addprefix --url-dir=, $(url_dir_list))
 
@@ -606,37 +1245,72 @@ announcement: NEWS ChangeLog $(rel-files)
 ftp-gnu = ftp://ftp.gnu.org/gnu
 www-gnu = http://www.gnu.org
 
-# Use mv, if you don't have/want move-if-change.
-move_if_change ?= move-if-change
-
 upload_dest_dir_ ?= $(PACKAGE)
-
 emit_upload_commands:
        @echo =====================================
        @echo =====================================
-       @echo "$(build_aux)/gnupload $(GNUPLOADFLAGS) \\"
+       @echo "$(srcdir)/$(_build-aux)/gnupload $(GNUPLOADFLAGS) \\"
        @echo "    --to $(gnu_rel_host):$(upload_dest_dir_) \\"
        @echo "  $(rel-files)"
        @echo '# send the ~/announce-$(my_distdir) e-mail'
        @echo =====================================
        @echo =====================================
 
-noteworthy = * Noteworthy changes in release ?.? (????-??-??) [?]
 define emit-commit-log
-  printf '%s\n' 'post-release administrivia' '' \
-    '* NEWS: Add header line for next release.' \
-    '* .prev-version: Record previous version.' \
+  printf '%s\n' 'maint: post-release administrivia' ''                 \
+    '* NEWS: Add header line for next release.'                                
\
+    '* .prev-version: Record previous version.'                                
\
     '* cfg.mk (old_NEWS_hash): Auto-update.'
 endef
 
+.PHONY: no-submodule-changes
+no-submodule-changes:
+       if test -d $(srcdir)/.git; then                                 \
+         diff=$$(cd $(srcdir) && git submodule -q foreach              \
+                 git diff-index --name-only HEAD)                      \
+           || exit 1;                                                  \
+         case $$diff in '') ;;                                         \
+           *) echo '$(ME): submodule files are locally modified:';     \
+               echo "$$diff"; exit 1;; esac;                           \
+       else                                                            \
+         : ;                                                           \
+       fi
+
+submodule-checks ?= no-submodule-changes public-submodule-commit
+
+# Ensure that each sub-module commit we're using is public.
+# Without this, it is too easy to tag and release code that
+# cannot be built from a fresh clone.
+.PHONY: public-submodule-commit
+public-submodule-commit:
+       $(AM_V_GEN)if test -d $(srcdir)/.git; then                      \
+         cd $(srcdir) &&                                               \
+         git submodule --quiet foreach test '$$(git rev-parse $$sha1)' \
+             = '$$(git merge-base origin $$sha1)'                      \
+           || { echo '$(ME): found non-public submodule commit' >&2;   \
+                exit 1; };                                             \
+       else                                                            \
+         : ;                                                           \
+       fi
+# This rule has a high enough utility/cost ratio that it should be a
+# dependent of "check" by default.  However, some of us do occasionally
+# commit a temporary change that deliberately points to a non-public
+# submodule commit, and want to be able to use rules like "make check".
+# In that case, run e.g., "make check gl_public_submodule_commit="
+# to disable this test.
+gl_public_submodule_commit ?= public-submodule-commit
+check: $(gl_public_submodule_commit)
+
 .PHONY: alpha beta stable
 ALL_RECURSIVE_TARGETS += alpha beta stable
-alpha beta stable: news-date-check changelog-check $(local-check)
+alpha beta stable: $(local-check) writable-files $(submodule-checks)
        test $@ = stable                                                \
          && { echo $(VERSION) | grep -E '^[0-9]+(\.[0-9]+)+$$'         \
               || { echo "invalid version string: $(VERSION)" 1>&2; exit 1;};}\
          || :
-       $(MAKE) vc-dist
+       $(MAKE) vc-diff-check
+       $(MAKE) news-check
+       $(MAKE) distcheck
        $(MAKE) dist XZ_OPT=-9ev
        $(MAKE) $(release-prep-hook) RELEASE_TYPE=$@
        $(MAKE) -s emit_upload_commands RELEASE_TYPE=$@
@@ -644,23 +1318,23 @@ alpha beta stable: news-date-check changelog-check 
$(local-check)
 # Override this in cfg.mk if you follow different procedures.
 release-prep-hook ?= release-prep
 
+gl_noteworthy_news_ = * Noteworthy changes in release ?.? (????-??-??) [?]
 .PHONY: release-prep
 release-prep:
        case $$RELEASE_TYPE in alpha|beta|stable) ;; \
          *) echo "invalid RELEASE_TYPE: $$RELEASE_TYPE" 1>&2; exit 1;; esac
-       $(MAKE) -s announcement > ~/announce-$(my_distdir)
+       $(MAKE) --no-print-directory -s announcement > ~/announce-$(my_distdir)
        if test -d $(release_archive_dir); then                 \
          ln $(rel-files) $(release_archive_dir);               \
          chmod a-w $(rel-files);                               \
        fi
        echo $(VERSION) > $(prev_version_file)
        $(MAKE) update-NEWS-hash
-       perl -pi -e '$$. == 3 and print "$(noteworthy)\n\n\n"' NEWS
+       perl -pi -e '$$. == 3 and print "$(gl_noteworthy_news_)\n\n\n"' NEWS
        $(emit-commit-log) > .ci-msg
        $(VC) commit -F .ci-msg -a
        rm .ci-msg
 
-
 # Override this with e.g., -s $(srcdir)/some_other_name.texi
 # if the default $(PACKAGE)-derived name doesn't apply.
 gendocs_options_ ?=
@@ -670,12 +1344,56 @@ web-manual:
        @test -z "$(manual_title)" \
          && { echo define manual_title in cfg.mk 1>&2; exit 1; } || :
        @cd '$(srcdir)/doc'; \
-         $(SHELL) ../build-aux/gendocs.sh $(gendocs_options_) \
+         $(SHELL) ../$(_build-aux)/gendocs.sh $(gendocs_options_) \
             -o '$(abs_builddir)/doc/manual' \
             --email $(PACKAGE_BUGREPORT) $(PACKAGE) \
            "$(PACKAGE_NAME) - $(manual_title)"
        @echo " *** Upload the doc/manual directory to web-cvs."
 
+# Code Coverage
+
+init-coverage:
+       $(MAKE) $(AM_MAKEFLAGS) clean
+       lcov --directory . --zerocounters
+
+COVERAGE_CCOPTS ?= "-g --coverage"
+COVERAGE_OUT ?= doc/coverage
+
+build-coverage:
+       $(MAKE) $(AM_MAKEFLAGS) CFLAGS=$(COVERAGE_CCOPTS) 
CXXFLAGS=$(COVERAGE_CCOPTS)
+       $(MAKE) $(AM_MAKEFLAGS) CFLAGS=$(COVERAGE_CCOPTS) 
CXXFLAGS=$(COVERAGE_CCOPTS) check
+       mkdir -p $(COVERAGE_OUT)
+       lcov --directory . --output-file $(COVERAGE_OUT)/$(PACKAGE).info \
+               --capture
+
+gen-coverage:
+       genhtml --output-directory $(COVERAGE_OUT) \
+               $(COVERAGE_OUT)/$(PACKAGE).info \
+               --highlight --frames --legend \
+               --title "$(PACKAGE_NAME)"
+
+coverage: init-coverage build-coverage gen-coverage
+
+# Update gettext files.
+PACKAGE ?= $(shell basename $(PWD))
+PO_DOMAIN ?= $(PACKAGE)
+POURL = http://translationproject.org/latest/$(PO_DOMAIN)/
+PODIR ?= po
+refresh-po:
+       rm -f $(PODIR)/*.po && \
+       echo "$(ME): getting translations into po (please ignore the robots.txt 
ERROR 404)..." && \
+       wget --no-verbose --directory-prefix $(PODIR) --no-directories 
--recursive --level 1 --accept .po --accept .po.1 $(POURL) && \
+       echo 'address@hidden' > $(PODIR)/LINGUAS && \
+       echo 'address@hidden' >> $(PODIR)/LINGUAS && \
+       ls $(PODIR)/*.po | sed 's/\.po//' | sed 's,$(PODIR)/,,' | sort >> 
$(PODIR)/LINGUAS
+
+ # Running indent once is not idempotent, but running it twice is.
+INDENT_SOURCES ?= $(C_SOURCES)
+.PHONY: indent
+indent:
+       indent $(INDENT_SOURCES)
+       indent $(INDENT_SOURCES)
+
 # If you want to set UPDATE_COPYRIGHT_* environment variables,
 # put the assignments in this variable.
 update-copyright-env ?=
@@ -689,6 +1407,106 @@ update-copyright-env ?=
 # in the file .x-update-copyright.
 .PHONY: update-copyright
 update-copyright:
-       grep -l -w Copyright $$($(VC_LIST_EXCEPT))              \
-               $(srcdir)/ChangeLog | grep -v COPYING           \
-         | $(update-copyright-env) xargs $(build_aux)/$@
+       grep -l -w Copyright                                             \
+         $$(export VC_LIST_EXCEPT_DEFAULT=COPYING && $(VC_LIST_EXCEPT)) \
+         | $(update-copyright-env) xargs $(srcdir)/$(_build-aux)/$@
+
+# This tight_scope test is skipped with a warning if $(_gl_TS_headers) is not
+# overridden and $(_gl_TS_dir)/Makefile.am does not mention noinst_HEADERS.
+
+# NOTE: to override any _gl_TS_* default value, you must
+# define the variable(s) using "export" in cfg.mk.
+_gl_TS_dir ?= src
+
+ALL_RECURSIVE_TARGETS += sc_tight_scope
+sc_tight_scope: tight-scope.mk
+       @fail=0;                                                        \
+       if ! grep '^ *export _gl_TS_headers *=' $(srcdir)/cfg.mk        \
+               > /dev/null                                             \
+          && ! grep -w noinst_HEADERS $(srcdir)/$(_gl_TS_dir)/Makefile.am \
+               > /dev/null 2>&1; then                                  \
+           echo '$(ME): skipping $@';                                  \
+       else                                                            \
+           $(MAKE) -s -C $(_gl_TS_dir)                                 \
+               -f Makefile                                             \
+               -f $(abs_top_srcdir)/cfg.mk                             \
+               -f $(abs_top_builddir)/$<                               \
+             _gl_tight_scope                                           \
+               || fail=1;                                              \
+       fi;                                                             \
+       rm -f $<;                                                       \
+       exit $$fail
+
+tight-scope.mk: $(ME)
+       @rm -f $@ address@hidden
+       @perl -ne '/^# TS-start/.../^# TS-end/ and print' $(srcdir)/$(ME) > 
address@hidden
+       @chmod a=r address@hidden && mv address@hidden $@
+
+ifeq (a,b)
+# TS-start
+
+# Most functions should have static scope.
+# Any that don't must be marked with 'extern', but 'main'
+# and 'usage' are exceptions: they're always extern, but
+# do not need to be marked.  Symbols matching '__.*' are
+# reserved by the compiler, so are automatically excluded below.
+_gl_TS_unmarked_extern_functions ?= main usage
+_gl_TS_function_match ?= /^(?:$(_gl_TS_extern)) +.*?(\S+) *\(/
+
+# If your project uses a macro like "XTERN", then put
+# the following in cfg.mk to override this default:
+# export _gl_TS_extern = extern|XTERN
+_gl_TS_extern ?= extern
+
+# The second nm|grep checks for file-scope variables with 'extern' scope.
+# Without gnulib's progname module, you might put program_name here.
+# Symbols matching '__.*' are reserved by the compiler,
+# so are automatically excluded below.
+_gl_TS_unmarked_extern_vars ?=
+
+# NOTE: the _match variables are perl expressions -- not mere regular
+# expressions -- so that you can extend them to match other patterns
+# and easily extract matched variable names.
+# For example, if your project declares some global variables via
+# a macro like this: GLOBAL(type, var_name, initializer), then you
+# can override this definition to automatically extract those names:
+# export _gl_TS_var_match = \
+#   /^(?:$(_gl_TS_extern)) .*?\**(\w+)(\[.*?\])?;/ || /\bGLOBAL\(.*?,\s*(.*?),/
+_gl_TS_var_match ?= /^(?:$(_gl_TS_extern)) .*?(\w+)(\[.*?\])?;/
+
+# The names of object files in (or relative to) $(_gl_TS_dir).
+_gl_TS_obj_files ?= *.$(OBJEXT)
+
+# Files in which to search for the one-line style extern declarations.
+# $(_gl_TS_dir)-relative.
+_gl_TS_headers ?= $(noinst_HEADERS)
+
+.PHONY: _gl_tight_scope
+_gl_tight_scope: $(bin_PROGRAMS)
+       t=exceptions-$$$$;                                              \
+       trap 's=$$?; rm -f $$t; exit $$s' 0;                            \
+       for sig in 1 2 3 13 15; do                                      \
+         eval "trap 'v=`expr $$sig + 128`; (exit $$v); exit $$v' $$sig"; \
+       done;                                                           \
+       src=`for f in $(SOURCES); do                                    \
+              test -f $$f && d= || d=$(srcdir)/; echo $$d$$f; done`;   \
+       hdr=`for f in $(_gl_TS_headers); do                             \
+              test -f $$f && d= || d=$(srcdir)/; echo $$d$$f; done`;   \
+       ( printf '^%s$$\n' '__.*' $(_gl_TS_unmarked_extern_functions);  \
+         grep -h -A1 '^extern .*[^;]$$' $$src                          \
+           | grep -vE '^(extern |--)' | sed 's/ .*//';                 \
+         perl -lne                                                     \
+            '$(_gl_TS_function_match) and print "^$$1\$$"' $$hdr;      \
+       ) | sort -u > $$t;                                              \
+       nm -e $(_gl_TS_obj_files) | sed -n 's/.* T //p'|grep -Ev -f $$t \
+         && { echo the above functions should have static scope >&2;   \
+              exit 1; } || : ;                                         \
+       ( printf '^%s$$\n' '__.*' $(_gl_TS_unmarked_extern_vars);       \
+         perl -lne '$(_gl_TS_var_match) and print "^$$1\$$"' $$hdr *.h \
+       ) | sort -u > $$t;                                              \
+       nm -e $(_gl_TS_obj_files) | sed -n 's/.* [BCDGRS] //p'          \
+            | sort -u | grep -Ev -f $$t                                        
\
+         && { echo the above variables should have static scope >&2;   \
+              exit 1; } || :
+# TS-end
+endif
diff --git a/man/autoconf.x b/man/autoconf.x
index 615d2e5..333284f 100644
--- a/man/autoconf.x
+++ b/man/autoconf.x
@@ -1,3 +1,2 @@
 [name]
 autoconf \- Generate configuration scripts
-
diff --git a/man/autoheader.x b/man/autoheader.x
index a3e0eba..a5217a7 100644
--- a/man/autoheader.x
+++ b/man/autoheader.x
@@ -1,3 +1,2 @@
 [name]
 autoheader \- Create a template header for configure
-
diff --git a/man/autoscan.x b/man/autoscan.x
index ce120eb..a3b67d9 100644
--- a/man/autoscan.x
+++ b/man/autoscan.x
@@ -1,3 +1,2 @@
 [name]
 autoscan \- Generate a preliminary configure.in
-
diff --git a/man/autoupdate.x b/man/autoupdate.x
index 23aa18c..40d24e2 100644
--- a/man/autoupdate.x
+++ b/man/autoupdate.x
@@ -1,3 +1,2 @@
 [name]
 autoupdate \- Update a configure.in to a newer Autoconf
-
diff --git a/man/ifnames.x b/man/ifnames.x
index 214ccce..a5af55b 100644
--- a/man/ifnames.x
+++ b/man/ifnames.x
@@ -1,3 +1,2 @@
 [name]
 ifnames \- Extract CPP conditionals from a set of files
-
diff --git a/tests/compile.at b/tests/compile.at
index afb69ce..a4ad6e2 100644
--- a/tests/compile.at
+++ b/tests/compile.at
@@ -463,4 +463,3 @@ AT_CHECK_AUTOCONF
 AT_CHECK_CONFIGURE([-q])
 
 AT_CLEANUP
-
diff --git a/tests/m4sh.at b/tests/m4sh.at
index 01b0e72..e9da403 100644
--- a/tests/m4sh.at
+++ b/tests/m4sh.at
@@ -73,13 +73,13 @@ AT_CHECK([test ! -f sentinel], [0])
 test ! -f sentinel || rm -f sentinel # Cleanup for next test.
 
 AT_CHECK(
-[CONFIG_SHELL=`pwd`/fake-shell sh script a 'b  c' '  d         e '],
+[CONFIG_SHELL=`pwd`/fake-shell sh script a 'b  c' '  d    e '],
 [0],
 [Fake shell executed.
 nargs = 3
  :a:
  :b  c:
- :  d          e :
+ :  d     e :
 ], [])
 AT_CHECK([test ! -f sentinel], [0])
 test ! -f sentinel || rm -f sentinel # Cleanup for next test.


hooks/post-receive
-- 
GNU Autoconf source repository



reply via email to

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