]> git.ipfire.org Git - thirdparty/libtool.git/commitdiff
Provide an m4sh reimplementation of announce-gen.
authorGary V. Vaughan <gary@gnu.org>
Fri, 4 Jun 2010 17:50:24 +0000 (00:50 +0700)
committerGary V. Vaughan <gary@gnu.org>
Fri, 4 Jun 2010 17:50:24 +0000 (00:50 +0700)
* libltdl/config/getopt.m4sh (M4SH_GETOPTS): New macro that takes
a quoted m4 list of command line options to be parsed, and
generates the shell code to parse those options and collect the
results into appropriately named 'opt_xxx' shell variables.  Also,
add some private supporting macros, and improve the comments
radically.
* libltdl/config/announce-gen.m4sh: New file, to generate and
optionally post (an enhancement over the gnulib perl script of the
same name) a release announcement.
* Makefile.maint (announce-gen): Build a new announce-gen script
in the build directory, from the contents of
libltdl/config/announce-gen.m4sh.
* HACKING (Release Procedure): Update the instructions to use
announce-gen.
(Alpha release note template, Full release note template):
Removed.

Signed-off-by: Gary V. Vaughan <gary@gnu.org>
ChangeLog
HACKING
Makefile.maint
libltdl/config/announce-gen.m4sh [new file with mode: 0644]
libltdl/config/getopt.m4sh

index 0eb77fffb1029530f1daf2b8455cf3b3b3ba49ed..4c01630bfc0a42336f51c96a591dfd920d7d4604 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,23 @@
+2010-06-05  Gary V. Vaughan  <gary@gnu.org>
+
+       Provide an m4sh reimplementation of announce-gen.
+       * libltdl/config/getopt.m4sh (M4SH_GETOPTS): New macro that takes
+       a quoted m4 list of command line options to be parsed, and
+       generates the shell code to parse those options and collect the
+       results into appropriately named 'opt_xxx' shell variables.  Also,
+       add some private supporting macros, and improve the comments
+       radically.
+       * libltdl/config/announce-gen.m4sh: New file, to generate and
+       optionally post (an enhancement over the gnulib perl script of the
+       same name) a release announcement.
+       * Makefile.maint (announce-gen): Build a new announce-gen script
+       in the build directory, from the contents of
+       libltdl/config/announce-gen.m4sh.
+       * HACKING (Release Procedure): Update the instructions to use
+       announce-gen.
+       (Alpha release note template, Full release note template):
+       Removed.
+
 2010-05-22  Gary V. Vaughan  <gary@gnu.org>
 
        Support "git log --oneline" in generated commit messages.
diff --git a/HACKING b/HACKING
index bea81fe223ae99b13b4ce813274e4d55451e5917..fa3e323ac532498fbf3da453c2f4cc5776890798 100644 (file)
--- a/HACKING
+++ b/HACKING
@@ -744,170 +744,38 @@ or obtained by writing to the Free Software Foundation, Inc.,
   <yourusername>@cvs.savannah.gnu.org:/webcvs/libtool
   (generate with `make -f[../]Makefile.maint web-manual').
 
-* Send announcement to libtool@gnu.org and autotools-announce@gnu.org,
-  if not an alpha send to info-gnu@gnu.org as well.
+* In the build directory, run `Make -f[../]Makeflie.maint announce-gen'.
 
-* Post a copy of the release announcement to savannah news:
-  https://savannah.gnu.org/news/submit.php?group=libtool
-  which will automatically propogate to http://planet.gnu.org.
-
-
-13. Alpha release note template
-===============================
-
-To: libtool@gnu.org, autotools-announce@gnu.org
-Reply-To: bug-libtool@gnu.org
-Subject: GNU Libtool @VERSION@ released (alpha release).
-
-The Libtool Team is pleased to announce alpha release @VERSION@ of GNU
-Libtool.
-
-GNU Libtool hides the complexity of using shared libraries behind a
-consistent, portable interface. GNU Libtool ships with GNU libltdl,
-which hides the complexity of loading dynamic runtime libraries
-(modules) behind a consistent, portable interface.
-
-Here are the compressed sources:
-
-  ftp://alpha.gnu.org/gnu/libtool/libtool-@VERSION@.tar.gz
-  ftp://alpha.gnu.org/gnu/libtool/libtool-@VERSION@.tar.bz2
-
-Here are the xdeltas and diffs against libtool-@PREV_RELEASE_VERSION_ON_THIS_BRANCH@:
-
-  ftp://alpha.gnu.org/gnu/libtool/libtool-@PREV_RELEASE_VERSION_ON_THIS_BRANCH@-@VERSION@.diff.gz
-  ftp://alpha.gnu.org/gnu/libtool/libtool-@PREV_RELEASE_VERSION_ON_THIS_BRANCH@-@VERSION@.xdelta
-
-Here are the gpg detached signatures:
-
-  ftp://alpha.gnu.org/gnu/libtool/libtool-@VERSION@.tar.gz.sig
-  ftp://alpha.gnu.org/gnu/libtool/libtool-@VERSION@.tar.bz2.sig
-  ftp://alpha.gnu.org/gnu/libtool/libtool-@PREV_RELEASE_VERSION_ON_THIS_BRANCH@-@VERSION@.diff.gz.sig
-  ftp://alpha.gnu.org/gnu/libtool/libtool-@PREV_RELEASE_VERSION_ON_THIS_BRANCH@-@VERSION@.xdelta.sig
-
-You should download the signature named after any tarball you download,
-and then verify its integrity with, for example:
-
-  gpg --verify libtool-@VERSION@.tar.gz.sig
-
-Here are the MD5 and SHA1 checksums:
-
-  @MD5SUM@ libtool-@VERSION@.tar.gz
-  @MD5SUM@ libtool-@VERSION@.tar.bz2
-  @MD5SUM@ libtool-@PREV_RELEASE_VERSION_ON_THIS_BRANCH@-@VERSION@.diff.gz
-  @MD5SUM@ libtool-@PREV_RELEASE_VERSION_ON_THIS_BRANCH@-@VERSION@.xdelta
-  @SHA1SUM@ libtool-@VERSION@.tar.gz
-  @SHA1SUM@ libtool-@VERSION@.tar.bz2
-  @SHA1SUM@ libtool-@PREV_RELEASE_VERSION_ON_THIS_BRANCH@-@VERSION@.diff.gz
-  @SHA1SUM@ libtool-@PREV_RELEASE_VERSION_ON_THIS_BRANCH@-@VERSION@.xdelta
-
-This release has @SUMMARY_OF_IMPROVEMENTS_SINCE_LAST_RELEASE_ON_THIS_BRANCH@.
-
-This release was bootstrapped with @BOOTSTRAP_TOOLS_WITH_VERSIONS@,
-but is useable with @COMPATIBLE_AUTOTOOL_VERSIONS@ in your own
-projects.
-
-Alternatively, you can fetch the unbootstrapped source code with
-git by using the following command:
-
-  $ git clone git://git.savannah.gnu.org/libtool.git
-  $ cd libtool
-  $ git checkout @GIT_RELEASE_TAG@
-
-You will then need to have recent (possibly as yet unreleased) versions
-of Automake and Autoconf installed to bootstrap the checked out
-sources yourself.
-
-New in @VERSION@: @RELEASE_DATE@
-
-  @EXCERPT_FROM_NEWS_FILE@
+* Make sure the source directory has an appropriate .announcerc, along
+  the lines of:
 
-Please report bugs to <bug-libtool@gnu.org>, along with the verbose
-output of any failed test groups, and the output from `./libtool --config.'
-The README file explains how to capture the verbose test output.
+    --bootstrap-tools='autoconf,automake'
+    --gpg-key-id={the id of the key you signed the tarballs with}
+    --header 'From: {your name} <{your email address}>
+    --header 'To: Libtool List <libtool@gnu.org>'
+    --header 'Cc: Autotools Announce List <autotools-announce@gnu.org>'
+    --header 'Reply-To: Libtool Bugs <bug-libtool@gnu.org>'
+    --message 'GNU Libtool hides the complexity of using shared'
+    --message 'libraries behind a consistent, portable interface.'
+    --message 'GNU Libtool ships with GNU libltdl, which hides the'
+    --message 'complexity of loading dynamic runtime libraries'
+    --message '(modules) behind a consistent, portable interface.'
+    --signature
 
+* Check the release announcement with:
 
+    ./announce-gen -r -o --prev=LASTRELEASE alpha
 
-14. Full release note template
-==============================
+  or for a stable release:
 
-To: info-gnu@gnu.org
-Cc: libtool@gnu.org, autotools-announce@gnu.org
-Reply-To: bug-libtool@gnu.org
-Subject: GNU Libtool @VERSION@ released.
+    ./announce-gen -r -o -h 'Cc: info-gnu@gnu.org' --prev=LASTRELEASE stable
 
-The Libtool Team is pleased to announce the release of GNU Libtool
-@VERSION@.
-
-GNU Libtool hides the complexity of using shared libraries behind a
-consistent, portable interface. GNU Libtool ships with GNU libltdl,
-which hides the complexity of loading dynamic runtime libraries
-(modules) behind a consistent, portable interface.
-
-This release has @SUMMARY_OF_IMPROVEMENTS_SINCE_LAST_RELEASE_ON_THIS_BRANCH@.
-
-New in @VERSION@: @RELEASE_DATE@
-
-  @EXCERPT_FROM_NEWS_FILE@
-
-libtool-@VERSION@ is available now from ftp.gnu.org, along with
-diffs and xdeltas against libtool-@PREV_RELEASE_VERSION_ON_THIS_BRANCH@
-that are also available from ftp.gnu.org.  Please
-use a mirror to reduce stress on the main gnu machine:
-
-  http://www.gnu.org/order/ftp.html
-
-Here are the compressed sources:
-
-  ftp://ftp.gnu.org/gnu/libtool/libtool-@VERSION@.tar.gz
-  ftp://ftp.gnu.org/gnu/libtool/libtool-@VERSION@.tar.bz2
-
-Here are the xdeltas and diffs against libtool-@PREV_RELEASE_VERSION_ON_THIS_BRANCH@:
-
-  ftp://ftp.gnu.org/gnu/libtool/libtool-@PREV_RELEASE_VERSION_ON_THIS_BRANCH@-@VERSION@.diff.gz
-  ftp://ftp.gnu.org/gnu/libtool/libtool-@PREV_RELEASE_VERSION_ON_THIS_BRANCH@-@VERSION@.xdelta
-
-Here are the gpg detached signatures:
-
-  ftp://ftp.gnu.org/gnu/libtool/libtool-@VERSION@.tar.gz.sig
-  ftp://ftp.gnu.org/gnu/libtool/libtool-@VERSION@.tar.bz2.sig
-  ftp://ftp.gnu.org/gnu/libtool/libtool-@PREV_RELEASE_VERSION_ON_THIS_BRANCH@-@VERSION@.diff.gz.sig
-  ftp://ftp.gnu.org/gnu/libtool/libtool-@PREV_RELEASE_VERSION_ON_THIS_BRANCH@-@VERSION@.xdelta.sig
-
-You should download the signature named after any tarball you download,
-and then verify its integrity with, for example:
-
-  gpg --verify libtool-@VERSION@.tar.gz.sig
-
-Here are the MD5 and SHA1 checksums:
-
-  @MD5SUM@ libtool-@VERSION@.tar.gz
-  @MD5SUM@ libtool-@VERSION@.tar.bz2
-  @MD5SUM@ libtool-@PREV_RELEASE_VERSION_ON_THIS_BRANCH@-@VERSION@.diff.gz
-  @MD5SUM@ libtool-@PREV_RELEASE_VERSION_ON_THIS_BRANCH@-@VERSION@.xdelta
-  @SHA1SUM@ libtool-@VERSION@.tar.gz
-  @SHA1SUM@ libtool-@VERSION@.tar.bz2
-  @SHA1SUM@ libtool-@PREV_RELEASE_VERSION_ON_THIS_BRANCH@-@VERSION@.diff.gz
-  @SHA1SUM@ libtool-@PREV_RELEASE_VERSION_ON_THIS_BRANCH@-@VERSION@.xdelta
-
-This release was bootstrapped with @BOOTSTRAP_TOOLS_WITH_VERSIONS@,
-but is useable with @COMPATIBLE_AUTOTOOL_VERSIONS@ in your own
-projects.
-
-Alternatively, you can fetch the unbootstrapped source code with
-git by using the following command:
-
-  $ git clone git://git.savannah.gnu.org/libtool.git
-  $ cd libtool
-  $ git checkout @GIT_RELEASE_TAG@
-
-You will then need to have the latest release versions of Automake
-(@AUTOMAKE_VERSION@) and Autoconf (@AUTOCONF_VERSION@) installed to
-bootstrap the checked out sources yourself.
-
-Please report bugs to <bug-libtool@gnu.org>, along with the verbose
-output of any failed test groups, and the output from `./libtool --config.'
-The README file explains how to capture the verbose test output.
+  When you're happy with the announcement text, post it by rerunning the
+  command with `-p' instead of `-o'.
 
+* Post a copy of the release announcement to savannah news:
+  https://savannah.gnu.org/news/submit.php?group=libtool
+  which will automatically propogate to http://planet.gnu.org.
 
 -- 
   Copyright (C) 2004, 2005, 2006, 2007, 2008 Free Software Foundation,
index b90b31d6c281c73bcd5d78bb418967c0e1b5abb0..70b740517c5034886b00dabecb1ec2828db1d3b3 100644 (file)
@@ -48,6 +48,20 @@ $(srcdir)/commit: $(srcdir)/$(auxdir)/mailnotify clcommit.m4sh
        mv -f commit.tmp commit; \
        rm -f commit.in
 
+announce-gen: $(auxdir)/announce-gen.m4sh $(auxdir)/getopt.m4sh
+       $(timestamp); \
+       rm -f announce-gen announce-gen.in announce-gen.tmp; \
+       $(M4SH) -B $(top_srcdir)/$(auxdir) $(top_srcdir)/$(auxdir)/announce-gen.m4sh > announce-gen.in; \
+       input="announce-gen.m4sh"; \
+       $(edit) -e "s,@TIMESTAMP\@,$$TIMESTAMP,g" \
+               -e "s,@LASTRELEASE\@,$(LASTRELEASE),g" \
+               -e "s,@top_srcdir\@,$(top_srcdir),g" \
+               announce-gen.in > announce-gen.tmp; \
+       chmod a+x announce-gen.tmp; \
+       chmod a-w announce-gen.tmp; \
+       mv -f announce-gen.tmp announce-gen; \
+       rm -f announce-gen.in
+
 $(srcdir)/$(auxdir)/mailnotify: $(auxdir)/mailnotify.m4sh
        $(timestamp); \
        cd $(srcdir)/$(auxdir); \
diff --git a/libltdl/config/announce-gen.m4sh b/libltdl/config/announce-gen.m4sh
new file mode 100644 (file)
index 0000000..6295039
--- /dev/null
@@ -0,0 +1,456 @@
+AS_INIT[]m4_divert_push([HEADER-COPYRIGHT])dnl
+# @configure_input@
+
+# announce-gen (GNU @PACKAGE@) version 1.0
+# Written by Gary V. Vaughan 
+# based on a perl script by Jim Meyering
+
+# Copyright (C) 2010 Free Software Foundation, Inc.
+# This is free software; see the source for copying conditions.  There is NO
+# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+# gen-announce is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# gen-announce 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 clcommit; see the file COPYING.  If not, a copy
+# can be downloaded from http://www.gnu.org/licenses/gpl.html,
+# or obtained by writing to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+# Usage: $progname {-o|-p} [OPTIONS]... [--] RELEASE-TYPE [TO-ADDRESS]...
+
+# -b file   --blurb=FILE            read announcement blurb from FILE
+#           --bootstrap-tools=LIST  a comma-separated list of tools, e.g.
+#                                   autoconf,automake,bison,gnulib
+#           --current-version=VER   override current release version number
+#           --debug                 enable verbose shell tracing
+#           --gpg-key-id=ID         gnupg ID of signature key for release files
+# -h STRING --header=STRING         insert mail header into announcement
+# -m STRING --message=STRING        insert into message blurb for announcement
+# -c        --no-print-checksums    do not emit MD5 and SHA1 checksums
+# -o        --output                output to stdout
+#           --package-name=NAME     override default package name
+# -p        --post                  post the announcement directly
+#           --previous-version=VER  previous release version number
+# -r [FILE] --rcfile[=FILE]         read options from FILE [./.announcerc]
+#           --signature[=FILE]      append FILE to post [~/.signature]
+#           --url-directory=URL     download url directory for released files
+#                                   [ftp://ftp.gnu.org/gnu/<package-name>]
+# -v        --verbose               run in verbose mode
+#           --version               print version information
+# -?        --help                  print short or long help message
+
+# In output mode, selected by `-o', a release note is printed on stdout.
+
+# In post mode, the release note is displayed in $PAGER, (giving you the
+# chance to make changes, and add headers) before posting to any every
+# TO-ADDRESS given on the command line, as well as any addresses added
+# to `To:', `Cc:' and `Bcc:' headers during editing.
+
+# The `--rcfile' option points to a file with other option settings, one
+# on each line.  For example:
+#
+#    --bootstrap-tools='autoconf, automake'
+#    --gpg-key-id=2983D606
+#    --header 'From: "Gary V. Vaughan" <gary@gnu.org>'
+#    --header 'To: Libtool List <libtool@gnu.org>'
+#    --header 'Cc: Autotools Announce List <autotools-announce@gnu.org>'
+#    --header 'Reply-To: Libtool Bugs <bug-libtool@gnu.org>'
+#    --message 'GNU Libtool hides the complexity of using shared'
+#    --message 'libraries behind a consistent, portable interface.'
+#    --message 'GNU Libtool ships with GNU libltdl, which hides the'
+#    --message 'complexity of loading dynamic runtime libraries'
+#    --message '(modules) behind a consistent, portable interface.'
+#    --signature
+#
+# This is the .announcerc for GNU Libtool.  Announce-gen is pretty
+# smart about picking defaults for package-name and current-version
+# and often guesses previous-version correctly too.  So, typically a
+# release note can be posted with:
+#
+#    ./$progname -r -p -h 'Cc: info-gnu@gnu.org' --prev=<LASTRELEASE> stable
+#
+# When that's producing a good announcement, it can be posted by using
+# the same arguments again, but for `-p' instead of `-o'
+
+# Report bugs to <gary@gnu.org>
+
+: ${DU="du"}
+: ${MAILNOTIFY="mailnotify"}
+: ${MD5SUM="md5"}
+: ${SHA1SUM="shasum"}
+
+PROGRAM=announce-gen
+
+m4_divert_pop
+m4_include([getopt.m4sh])
+
+M4SH_VERBATIM([[
+top_srcdir=`cd "@top_srcdir@" && pwd`
+test -d "$top_srcdir" || top_srcdir='@top_srcdir@'
+
+# Initialisation:
+mailnotify_flags=
+package_name="@PACKAGE_NAME@"
+sendmail_to=
+valid_release_types='alpha,beta,release-candidate,stable'
+
+# try to find out whether read supports -r
+if echo bt | tr b '\\' | { read -r line; test "X$line" = 'X\t'; } 2>/dev/null
+then
+  read_r='read -r'
+else
+  read_r=read
+fi
+]])
+
+dnl SHORT      LONG                           DEFAULT                INIT
+dnl ----------------------------------------------------------------------
+M4SH_GETOPTS(
+  [b@],        [--blurb],                              [],                     [],
+  [h;],        [--header],                             [],                     [],
+  [m;],        [--message|--msg],                      [],                     [],
+  [o], [--output],                             [],                     [],
+  [p], [--post],                               [],                     [],
+  [r@?],[--rcfile],                            [$top_srcdir/.announcerc], [
+       # The funny quoting allows keeping one option per line in $opt_rcfile:
+       eval set dummy `echo \`cat $opt_rcfile\` \${1+"\[$]@"}`
+       shift],
+  [v], [--verbose],                            [],                     [
+       mailnotify_flags="${mailnotify_flags+$mailnotify_flags }$opt"],
+  [!], [--bootstrap-tools|--bootstrap|--boots], [],                    [
+       for tool in `echo "$optarg"|$SED 's|,| |g'`; do
+           ($tool --version) >/dev/null 2>&1 || {
+               func_error "$opt \`$optarg' does not respond to --version option."
+               cmd_exit=exit
+           }
+       done],
+  [!], [--current-version|--current|--curr],   [@VERSION@],            [],
+  [!], [--gpg-key-id|--gpg],                   [],                     [],
+  [],  [--no-print-checksums],                 [],                     [],
+  [!], [--previous-version|--previous|--prev], [@LASTRELEASE@],        [],
+  [!], [--release-type],                       [],                     [],
+  [@?],        [--signature],                          [$HOME/.signature],     [],
+  [!], [--url-directory],                      [],                     [],
+ [
+  # validate $opt_gpg_key_id
+  test -n "$opt_gpg_key_id" || {
+      func_error "you must specify a key with --gpg-key-id."
+      exit_cmd=exit
+  }
+
+  # validate $opt_bootstrap_tools
+  test -n "$opt_bootstrap_tools" || {
+      func_error "you must specify some tools with --bootstrap-tools."
+      exit_cmd=exit
+  }
+
+  # validate $opt_blurb and $opt_message
+  test -n "$opt_blurb" && test -n "$opt_message" && {
+      func_error "you can specify only one of --blurb and --message."
+      exit_cmd=exit
+  }
+
+  # validate $opt_output and $opt_post
+  $opt_output && $opt_post && {
+      func_error "you can specify only one of --output and --post."
+      exit_cmd=exit
+  }
+  $opt_output || $opt_post || {
+      func_error "you must specify either --output or --post."
+      exit_cmd=exit
+  }
+
+  # validate $opt_release_type
+  test -n "$opt_release_type" || {
+      test [$]# -gt 0 || { func_error "no release type specified."; exit_cmd=exit; }
+      opt_release_type="[$]1"; shift
+  }
+  case ,$valid_release_types, in *,$opt_release_type,*) ;;
+      *) func_error "\`$opt_release_type': invalid release type."; exit_cmd=exit ;;
+  esac
+
+  # validate $url_directory
+  test -n "$url_directory" || {
+      case $opt_release_type in
+         stable) url_directory="ftp://ftp.gnu.org/gnu/$package_name" ;;
+          *)      url_directory="ftp://alpha.gnu.org/gnu/$package_name" ;;
+      esac
+  }
+
+  # pass trace argument along to mailnotify too
+  $opt_debug &&
+      mailnotify_flags="${mailnotify_flags+$mailnotify_flags }--debug"
+  
+  # validate remaining command line args as destination addresses
+  for address
+  do
+      func_quote_for_eval "$address"
+      sendmail_to="${sendmail_to+$sendmail_to }$func_quote_for_eval_result"
+  done
+])
+
+M4SH_VERBATIM([[
+# Bail out on command errors!
+set -e
+
+# func_print_changelog_deltas
+func_print_changelog_deltas ()
+{
+    # FIXME: Jim's announce-gen does something with ChangeLogs
+    #        and cvs diff.  We don't use CVS, and perl makes
+    #        my eyes bleed... maybe I'll write this function
+    #        one day.
+    :
+}
+
+
+# func_print_checksums title filename...
+func_print_checksums ()
+{
+    my_title="$1"; shift
+
+    test -n "$1" && {
+       echo
+       echo "Here are the $my_title:"
+       echo
+       for my_sum in $MD5SUM $SHA1SUM; do
+           for my_filename in ${1+"$@"}; do
+               my_line=`$my_sum $my_filename`
+               my_hash=`expr "$my_line" : '.*\([0-9a-f]\{40\}\)' || :`
+               test -n "$my_hash" || my_hash=`expr "$my_line" : '.*\([0-9a-f]\{32\}\)'`"        "
+               echo "  $my_hash  $my_filename"
+           done
+       done
+    }
+
+    # To stop bash exiting if test fails
+    :
+}
+
+
+# func_print_locations title url files
+func_print_locations ()
+{
+    test -n "$3" && {
+       echo
+       echo "Here are the $1:"
+       echo
+       for my_file in $3; do
+           my_size=`$DU -h $my_file|sed 's,[bB]*[      ].*$,,'`
+           echo "  $2/$my_file (${my_size}B)"
+       done
+    }
+
+    # To stop bash exiting if test fails
+    :
+}
+
+
+# func_print_news_deltas
+func_print_news_deltas ()
+{
+    my_news_file="$top_srcdir/NEWS"
+    my_skipping=:
+
+    # reset the field separator to prevent whitespace removal by 'read'
+    save_IFS="$IFS"
+    IFS=
+
+    echo
+    cat $my_news_file |
+      while read line; do
+       case $line in
+         "New in $opt_current_version "*:)
+             my_skipping=false
+             echo "$line"
+             ;;
+         "New in "*:)
+             my_skipping=:
+             ;;
+         *)
+             $my_skipping || echo "$line"
+             ;;
+       esac
+      done
+
+    IFS="$save_IFS"
+}
+
+
+# func_tool_versions toolname...
+func_print_tool_versions ()
+{
+    test -n "$1" && {
+       echo
+       echo "This release was bootstrapped with the following tools:"
+       echo
+       for my_tool in ${1+"$@"}; do
+           my_tool_version=`$my_tool --version|sed 's,^.* ,,g;1q'`
+           echo "  $my_tool-$my_tool_version"
+       done
+    }
+
+    # To stop bash exiting if test fails
+    :
+}
+
+
+
+## ----- ##
+## main. ##
+## ----- ##
+
+{
+  # Neutralize the locale, so that, for instance, "du" does not
+  # issue "1,2" instead of "1.2", which confuses our regexps.
+  LC_ALL=C
+  export LC_ALL
+
+  # Secure directory for temporary files
+  tmp_dir="`func_mktempdir`"
+  trap '$RM -r "$tmp_dir"; exit $EXIT_FAILURE' 1 2 15
+
+  # Save any header or post blurb for mailnotify
+  header_file="$tmp_dir/headers"
+  blurb_file="$tmp_dir/blurb"
+
+  test -n "$opt_header" && echo "$opt_header" > "$header_file"
+  test -n "$opt_message" && echo "$opt_message" > "$blurb_file"
+  test -n "$opt_blurb" && cat "$opt_blurb" > "$blurb_file"
+
+  archive_suffixes='tar.gz tar.bz2 tar.lzma tar.xz'
+  diff_suffixes='diff.gz diff.bz2 diff.lzma diff.xz xdelta'
+
+  # Ensure there is something to announce!
+  for suffix in $archive_suffixes; do
+      candidate="$package_name-$opt_current_version.$suffix"
+      candidates="${candidates+$candidates, }$candidate"
+      test -r "$candidate" || continue
+      tarballs="${tarballs+$tarballs }$candidate"
+  done
+  for suffix in $diff_suffixes; do
+      candidate="$package_name-$opt_previous_version-$opt_current_version.$suffix"
+      candidates="${candidates+$candidates, }$candidate"
+      test -r "$candidate" || continue
+      compressed_diffs="${compressed_diffs+$compressed_diffs }$candidate"
+  done
+  test -n "$tarballs$compressed_diffs" ||
+      func_fatal_error "none of $candidates were found."
+
+  # Signature files
+  signed_files="$tarballs $compressed_diffs"
+  for signed in $signed_files; do
+      sig_files="${sig_files+$sig_files }$signed.sig"
+  done
+
+  # Displaying or posting the announcement?
+  if $opt_post; then
+      notify_file="$tmp_dir/post"
+      exec 3>$notify_file
+  else
+      exec 3>&1
+  fi
+
+  {
+      echo "Subject: $package_name $opt_current_version released ($opt_release_type)"
+      test -f "$header_file" && cat "$header_file"
+      echo
+      test -f "$blurb_file" && cat "$blurb_file"
+      func_print_locations "compressed sources" "$url_directory" "$tarballs"
+      func_print_locations "diffs against $package_name $opt_previous_version" "$url_directory" "$compressed_diffs"
+      func_print_locations "GPG detached signatures[1]" "$url_directory" "$sig_files"
+
+      $opt_print_checksums && 
+          func_print_checksums "MD5 and SHA1 checksums[2]" $tarballs $compressed_diffs
+
+      case $url_directory in
+         *"gnu.org"*)
+             echo
+             echo 'To reduce load on the main server, please one of the mirrors listed at:'
+             echo
+             echo '  http://www.gnu.org/order/ftp.html'
+             ;;
+      esac
+
+      cat <<EOF
+
+[1] You can use the above signature files to verify that the
+    corresponding file (without the .sig suffix) is the same
+    file that was released by the owner of it's GPG key ID.
+    First be sure to download both the .sig file and the
+    corresponding file. Then run a cammand like this:
+
+      gpg --verify `echo "$tarballs" | sed -e 's, .*$,,g'`.sig
+
+    If that command fails because you don't have the required
+    public key, then run this command to import it:
+
+      gpg --keyserver keys.gnupg.net --recv-keys $opt_gpg_key_id
+
+    and rerun the \`gpg --verify' command.
+EOF
+
+      $opt_print_checksums && cat <<EOF
+
+[2] You can use either of the above checksum files to verify
+    that the corresponding file is complete and correct. To
+    confirm that the file you downloaded has a checksum that
+    matches the release note, compare it against the output
+    one of the following commands:
+
+      md5sum `echo "$tarballs" | sed -e 's, .*$,,g'`
+      shasum `echo "$tarballs" | sed -e 's, .*$,,g'`
+
+    (the name of the command sometimes varies between
+    different operating systems).
+EOF
+
+      func_print_tool_versions $tool_list
+      func_print_news_deltas
+      func_print_changelog_deltas
+
+      echo 'Enjoy!'
+  } >&3
+
+  $opt_post && {
+      test -f "$top_srcdir/libltdl/config/$MAILNOTIFY" &&
+          MAILNOTIFY="$top_srcdir/libltdl/config/$MAILNOTIFY"
+      test -f "$MAILNOTIFY" ||
+          func_fatal_error "$MAILNOTIFY: file not found."
+
+      ${PAGER-more} "$notify_file" || break
+
+      sleep 1 # give the user some time for a ^C
+
+      # Break out the headers
+      header_file="$tmp_dir/headers"
+      $SED -n '/[A-Z][a-zA-Z0-9-]*: /p;/^$/q' "$notify_file" > "$header_file"
+
+      my_mail_body="`$SED '1,/^$/d' $notify_file`"
+      echo "$my_mail_body" > "$notify_file"
+
+      func_verbose "mailing release announcement to \"$sendmail_to\""
+      func_show_eval "$MAILNOTIFY $mailnotify_flags \
+         --headers='$header_file' \
+          -m 'text/plain' -f '$notify_file' -- $sendmail_to"
+  }
+}
+
+$RM -r "$tmp_dir"
+
+exit $EXIT_SUCCESS
+
+# Local Variables:
+# mode:shell-script
+# sh-indentation:2
+# End:
+]])
index d0f92f6386474d3fb6be4c758ec84d2abd001739..6e0e2c61e35ca740edfc014569ad1b73fb5dbb74 100644 (file)
-m4_if([getopt.m4sh -- getopt helper functions           -*- Autoconf -*-
+m4_include([general.m4sh])m4_divert_push(-1)
+# getopt.m4sh -- getopt helper functions                -*- Autoconf -*-
+#
+#    Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
+#    Written by Gary V. Vaughan, 2004
+#
+#    This file is part of GNU Libtool.
+#
+# GNU Libtool is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of
+# the License, or (at you option) any later version.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program or library that contains
+# a configuration script generated by Autoconf, you may include this
+# file under the same distribution terms that you use for the rest
+# of that program.
+#
+# GNU Libtool is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNES 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 GNU Libtool; see the file COPYING.  If not, a copy
+# can be downloaded from  http://www.gnu.org/licenses/gpl.html,
+# or obtained by writing to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 
-   Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Free Software
-   Foundation, Inc.
-   Written by Gary V. Vaughan, 2004
+# This file provides the M4SH_GETOPTS option processing compiler, and
+# all necessary support at the m4 and shell-script levels.
+#
+# An m4sh script can include this file, and an M4SH_GETOPTS invocation
+# that expands to a shell script option processing loop with similar
+# abilites to a C program the uses getopt_long() to process it's command
+# line options - although, unlike the C API, M4SH_GETOPTS also supplies
+# the loop to step through and process the options.
+#
+# See the comment above M4SH_GETOPTS, below, for details.
 
-   This file is part of GNU Cvs-utils.
 
-GNU Cvs-utils is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License as
-published by the Free Software Foundation; either version 2 of
-the License, or (at you option) any later version.
+# All internal macros begin with `m4go_'.
+m4_pattern_forbid([^_?m4go_])
 
-As a special exception to the GNU General Public License, if you
-distribute this file as part of a program or library that contains
-a configuration script generated by Autoconf, you may include this
-file under the same distribution terms that you use for the rest
-of that program.
+## --------------------------------- ##
+## 1. Low level string manipulation. ##
+## --------------------------------- ##
 
-GNU Cvs-utils is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNES FOR A PARTICULAR PURPOSE. See the GNU
-General Public License for more details.
+# m4go_slice(STRING, BEGIN, END)
+# ------------------------------
+# Just like m4_substr(), except that both the BEGIN and END of the
+# substring are given as offsets from the beginning of STRING, as
+# returned by m4_index().
+m4_define([m4go_slice],
+[m4_substr([$1], [$2], m4_eval([$3-$2]))])
 
-You should have received a copy of the GNU General Public License
-along with GNU Libtool; see the file COPYING.  If not, a copy
-can be downloaded from  http://www.gnu.org/licenses/gpl.html,
-or obtained by writing to the Free Software Foundation, Inc.,
-51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-])dnl
+# m4go_trimn(STRING)
+# -------------------
+# Trim all leading and trailing newlines from STRING.
+#
+# Inspite of careful quoting, this macro is NOT robust to active
+# symbols:
+#        | m4_define(active, ACTV)
+#        | m4go_trimn([[
+#        |    start active finish
+#        | ]])
+#       => start ACTV fini
+# The interaction between index counting and macro expansion also
+# results in overtrimming in this example by 2 characters (the
+# difference between the lengths of `active' and `ACTV'). Translation
+# into French is just a coincidence.
+#
+# The implementation is surprisingly finicky: We use m4go_slice() to
+# extract the middle section of the string, while using m4_bregexp() to
+# return offset counts for the first and last non-newlines in STRING.
+# But there are a number of corner cases:
+#  1. Double quoted STRING works, (i.e m4go_trimn([[\nthe string\n]]. We
+#     achieve that by transliterating quote characters as well as
+#     newlines to the same character before counting off the offsets.
+#  2. This needs a slightly different transliteration for each
+#     m4_bregexp() invocation, because we need to maintain balanced
+#     quotes in the argument and we don't want to swallow leading ']' or
+#     trailing '[' characters.  So, we turn the quote we don't want to
+#     strip into a harmless ' '.
+#  3. Because we're now effectively stripping the quotation with the
+#     m4_translit() calls, embedded commas can fool m4_bregexp() into
+#     thinking there are more arguments than we intended, so we turn
+#     them into spaces too.
+#  4. Unbalanced parentheses would also confuse m4_bregexp(), so we also
+#     turn them into spaces.  The upshot of that if STRING contains a
+#     macro invocation with arguments, it will be expanded in the result
+#     as if no arguments had been passed.
+#  5. Comments are not ignored after stripping quote marks, so we have
+#     to turn them off for the duration.
+#  6. Finally, we need to requote the result to account for the quotes
+#     we probably stripped.  m4_quote() doesn't handle commas well, so
+#     we use m4_expand() to requote without losing whitespace after any
+#     embedded commas.
+m4_define([m4go_trimn],
+[m4_changecom()m4_expand([m4go_slice([$1], m4_bregexp(m4_translit([$1],[
+[/,()]], [//     ]), [[^/]]), m4_bregexp(m4_translit([$1], [
+[/,()]], [/     /]), [/*$]))])[]m4_changecom([#])])
 
-m4_include([general.m4sh])
+# m4go_untab(STRING)
+# ------------------
+# Trim leading TABs from each line of STRING.
+m4_define([m4go_untab],
+[m4_bpatsubst([$1], [^[        ]*], [])])
 
-M4SH_VERBATIM([[
+# m4go_unindent(STRING)
+# ---------------------
+# Completely unindent STRING: Remove the leading TABs from each line of
+# STRING; trim leading newlines and trailing whitespace from STRING as
+# a whole.
+m4_define([m4go_unindent],
+[m4_ifval([$1], [m4go_untab([m4go_trimn([$1])])])])
+
+
+## ------------------------------ ##
+## 2. Option processing compiler. ##
+## ------------------------------ ##
+
+# Shell fragments are piecemeal added to these macros for each
+# invocation of m4go_option; eventually to be expanded into the compiled
+# option parsing shell script by M4SH_GETOPTS:
+
+m4_define([m4go_defaults], []) # initial shell option variable setings
+m4_define([m4go_branches], []) # case branches to process options
+
+# The initial entries in m4go_shortnoargs represent the (non-argument)
+# options that are always accepted by the expanded processing loop. We
+# also keep a list of short options that accept an option argument in
+# the macro `m4go_shortargs', but we use `m4_append([m4go_shortargs],
+# OPTION, [|])' to insert the separator pipe symbols - which requires
+# that `m4go_shortargs' be undefined if the first option appended is not
+# prefixed by a leading `|'.
+m4_define([m4go_shortnoargs], [-?*|-h*|-v*])
+
+
+# M4SH_GETOPTS(SHORT-SPEC1, LONG-MATCH1, DEF1, INIT1,
+#              SHORT-SPEC2, LONG-MATCH2, DEF2, INIT2, ... [VALIDATION])
+# ---------------------------------------------------------------------
+# Declare a series of command line options with one letter (`-m') or
+# long form `--message' formats, along with optional default values
+# incase a given option is not provided by the user when the script is
+# invoked, and validation code, for example to prevent specifying
+# mutually exclusive options or omitting required options.
+#
+# After this macro has been called, the value of each option is
+# available in a shell variable named `opt_' followed by the first part
+# (i.e. up to the first '|' symbol) of the LONG-MATCHn argument with the
+# leading `--` removed, and any further `-' converted to `_', or else if
+# no long form option was provided, simple `opt_' followed by the short
+# option letter. For example, the value supplied by the user as an
+# argument to an option `--gpg-key-id' will be available in the shell
+# variable $opt_gpg_key_id, `-c' with no long form option will be
+# available as $opt_c and so on. Where an option doesn't take an
+# argument, then the shell variable will be set to either `:' or `false'
+# depending on whether the user set that option on the script command
+# line - with one important exception: If the long form option name
+# begins with `--no-', and does not require an option argument, then the
+# variable name will be `opt_' followed by the rest of the option name
+# with the leading `no_' removed; and it's value will be `false' if
+# `--no-foo' was given on the command line, and `:' otherwise.
+#
+# Each option is declared by a set of 4 arguments as follows:
+#
+# SHORT-SPECn
+#      The short option letter, if any, for the nth option followed by
+#      any flags to denote special processing for this option. For
+#      example, `f?@'. See below for a list of the supported flags and
+#      their meaning. If you specify `h', `v' or `x', then the
+#      automatic processing of those short options for `--help',
+#      `--version' and `--debug' (resp.) will be overridden.
+# LONG-MATCHn
+#      The long option list, including leading dashes for the nth
+#      option. The value for this option is used directly as a shell
+#      `case' branch to match the option, so you can specify multiple
+#      matches. For example, `--message|--mes*|--msg'.  If you specify
+#      neither this argument nor a short option letter with
+#      SHORT-SPECn, then invalid shell code will be generated.
+# DEFn If there is a default value for the nth option to take when it
+#      is not given on the command line when the script is executed,
+#      specify it here. Double quotes are added in the expanded shell
+#      script, so it is safe to use shell variables. For example,
+#      `$HOME/.foorc'.
+# INITn        Any option specific initialisation for the nth option should be
+#      specified in this argument. The shell code it contains is added
+#      directly to the case branch that matches the nth option, after
+#      the `opt_NAME' variable has been set, with the option argument
+#      (if any) still left in `$1'.  This allows neat tricks such as
+#      injecting new arguments into the command line before the
+#      processing loop terminates.  For example:
+#
+#              `eval set -- `cat $rcfile` ${1+"$@"}'
+#
+#      Note that, because we look inside the content of INITn to
+#      determine whether there are newlines to be stripped, double
+#      quoting the whele thing doesn't work.  Instead, you'll need to
+#      quote active symbols yourself.  Generally, you'll only need to
+#      worry about $n and $@, although if you use symbols that can be
+#      expanded by m4 you'll need to quote those too.
+# VALIDATION
+#      The final argument, if any, should contain shell code to
+#      validate correctness of the processed options.  This code is
+#      expanded after the option processing loop has exited, and before
+#      the conditional script exit if errors have been found.  Try to
+#      show as many errors as possible before exiting the shell rather
+#      than bailing out on the first error discovered so that the user
+#      can correct all of them at once rather than just one between
+#      each reinvocation of the script.
+#
+# In addition to an option short form letter (e.g. `m'), each
+# SHORT-SPECn argument can also list one or more of the following flags
+# to place additional constraints on that option (only one of `?', `+'
+# and `@' can be given in any SHORT-SPECn):
+#
+# =STRING
+#      The option does not take an argument, but when specified on the
+#      command line the `opt_' variable is set to STRING.
+# ?    The option takes an optional argument. Unless the next command
+#      line argument begins with a `-' it will be the value stored in
+#      this option's `opt_' shell variable. Otherwise the `opt_'
+#      variable will contain the INITn value.
+# !    The option requires an argument. The next command line argument
+#      will be stored in this option's `opt_' shell variable, or else
+#      the INITn value, if any, will be stored if this option is not
+#      given on the command line.
+# ;    The same as `!', except that when the argument is given multiple
+#      times on the command line, each argument is appended to the
+#      `opt_' shell variable, along with a new-line to separate it from
+#      the previous argument.
+# +    The same as `!', except that each time the argument is supplied
+#      on the command line, it's value is stored in an `opt_' variable
+#      with `_n' appended to the variable name - where `n' is `1' for
+#      the first argument, `2, for the second and so on.
+# @    The option argument must point to an existing file. The
+#      processing loop will automatically contain an additional check
+#      to ensure that the named file exists. `@' can be added to a
+#      SHORT-SPECn argument in addition to any other flags.
+# ^    The value stored in the `opt_' variable is quoted by passing it
+#      through the shell function `func_quote_for_eval'.
+#
+# The M4SH_GETOPTS macro is implemented by first delegating to
+# `_M4SH_GETOPTS', a shift4-loop that repeatedly calls `m4go_options',
+# shifts away the 4 processed arguments, checks the number of remaining
+# args and loops again until only 1 argument (VALIDATION) or 0 arguments
+# (no VALIDATION code) remain. When all the processing is complete, we
+# expand 'm4go_printopts' to write out the complete command line
+# processing shell loop.
+#
+# Generally, you can combine the SHORT-SPECn flags in sensible ways,
+# but no error checking is done. If you choose a combination that makes
+# no sense, you'll probably end up with broken shell code.
+m4_define([M4SH_GETOPTS],
+[_$0($@)[]m4go_printopts])
+m4_define([_M4SH_GETOPTS],
+[m4_if([$#], 0, [],
+       [$#], 1, [m4_define([m4go_validation],[$1])],
+       [$#], 2, [m4_fatal([$0: too few arguments: $#: $2])],
+       [$#], 3, [m4_fatal([$0: too few arguments: $#: $3])],
+       [m4go_option($@)[]$0(m4_shiftn(4, $@))])])
+
+
+# m4go_option(SHORT-SPEC, LONG-MATCH, DEFAULT, INIT)
+# --------------------------------------------------
+# This macro is a wrapper for `_m4go_option', which first extracts the
+# short option letter (if any) from SHORT-SPEC, and then calculates the
+# full `opt_' shell variable name for this option before delegating
+# those results along with all of its own arguments to `_m4go_option'.
+#
+# Note that when the LONG-MATCH begins with `--no-', we add `~' to the
+# list of SHORT-SPEC flags before calling `_m4go_option' to denote that
+# the name of the `opt_' variable is reversed in the sense of the option
+# name itself.That is, we want to start with the option being true, and
+# set it to false if `--no-foo' is given on the command line.
+#
+# `m4_do' is used here to separate out the pushdef and popdef of the
+# temporary `_short' macro used to held the extracted short option
+# letter, if any.
+m4_define([m4go_option],
+[m4_do(
+    [m4_pushdef([_short],
+        m4_bmatch([$1],
+            [[?!;+@^]], m4_bpatsubst([$1], [[?!;+@^]*], []),
+            [^=],       [],
+            [.],        [[$1]],
+                        []))],
+    [_$0(opt_[]m4_ifnblank([$2],
+            m4_translit(m4_bpatsubst([$2], [^--\(no-\)?\([^|]+\).*$],
+                                     [\2]), -, _),
+                _short),
+         _short,
+         [$1]m4_bmatch([$2], [^--no-], [~]),
+         [$2],
+         [$3],
+         [$4])],
+    [m4_popdef([_short])])])
+
+
+# _m4go_option(OPTION-NAME, SHORT-OPTION, SHORT-SPEC, LONG-MATCH,
+#                  DEFAULT, INIT)
+#----------------------------------------------------------------
+# For this option, append the appropriate shell code fragments to:
+# `m4go_defaults'
+#      A shell script fragment containing `opt_' variable
+#      initialisation according to DEFAULT, if necessary;
+# `m4go_branches'
+#      The case branch to match any SHORT-OPTION or LONG-MATCH command
+#      line option, along with any automatic processing implied by
+#      SHORT-SPEC flags, and additional code from INIT;
+# `m4go_shortargs'
+#      This match string accumulates all of the short options that
+#      accept option arguments, so that we can generate some additional
+#      code to split apart compacted option strings (`-xfoo' will be
+#      treated as if `-x foo' had been passed) in `m4go_printopts'.
+# `m4go_shortnoargs'
+#      Similarly, accumulate short options that do not take option
+#      arguments, so that we can generate the code to split apart
+#      compacted options strings in `m4go_printopts' (`-xfoo' will be
+#      treated as if `-x -f -o -o' had been passed).
+#
+# The core of this macro switches the `m4go_branches' processing to an
+# appropriate macro depending on what flags are present in SHORT-SPEC.
+
+m4_define([_m4go_option],
+[m4_do(
+    [m4_append([m4go_defaults],
+        m4_bmatch([$3],
+            [[?!;+@^]], [m4_ifnblank([$5], [m4_n([$1="$5"])])],
+            [~],        [m4_n([$1=:])],
+                        [m4_n([$1=false])]))],
+    [m4_append([m4go_branches], [[]dnl (
+      m4_join([|], [$4], m4_ifnblank([$2], [-$2])))
+])],
+    [m4_append([m4go_branches],
+        [m4_bmatch([$3], [[!+@]],
+[                      test [$]# = 0 && func_missing_arg $opt && break
+])m4_n(m4_bmatch([$3],
+    [\^],      [                       func_quote_for_eval "[$]1"
+                       optarg="$func_quote_for_eval_result"],
+    [[?!;+@]], [                       optarg="[$]1"]))[]dnl
+m4_n(m4_bmatch([$3],
+    [+],       [                       $1_num=`expr 1 + ${$1_num-0}`
+                       eval $1_${$1_num}=\"$optarg\"],
+    [?],       [m4_bmatch([$3],
+                    [@], [m4_expand([m4go_optional_file_arg([$1])])],
+                         [m4_expand([m4go_optional_arg([$1])])])],
+    [[!@]],    [                       $1="$optarg"],
+    [;],       [                       $1="${$1+[$]$1
+}$optarg"],
+    [~],       [                       $1=false],
+    [=.],      [                       $1="m4_bpatsubst([$3], [^.*=], [])"],
+               [                       $1=:]))[]dnl
+dnl only write the file_arg fragment when we didn't already write opt_file_arg:
+m4_bmatch([$3], [@], [m4_bmatch([$3], [?], [],
+                   [m4_expand([m4go_file_arg([$1])])
+])])m4_n(m4go_unindent([$6]))[]dnl
+m4_bmatch([$3], [[!+]], [                      shift
+])                     ;;
+])],
+    [m4_ifnblank([$2],
+        [m4_bmatch([$3],
+            [[?!;+@^~]], [m4_append([m4go_shortargs],   [-$2*], [|])],
+                       [m4_append([m4go_shortnoargs], [-$2*],
+                                  [|])])])])])
+
+
+# m4go_optional_arg(OPTION-NAME)
+# ------------------------------
+# Expand to the case branch core code for processing a flag that takes
+# an optional argument, and sets the `opt_' variable named by
+# OPTION-NAME appropriately.
+m4_define([m4go_optional_arg],
+[                      if test [$]# -gt 0; then
+                           case $optarg in # ((
+                               -*) ;;
+                               *) $1="$optarg"; shift ;;
+                           esac
+                       fi])
+
+# m4go_file_arg(OPTION-NAME)
+# --------------------------
+# As above, but for flags that require the name of an existing file as
+# an argument.
+m4_define([m4go_file_arg],
+[                      test -r "$optarg" || {
+                           func_error "$opt: cannot read file \`$optarg'."
+                           exit_cmd=exit
+                       }])
+
+# m4go_optional_file_arg(OPTION-NAME)
+# -----------------------------------
+# As above, but for options that optionally takes the name of an
+# existing file as its argument.
+m4_define([m4go_optional_file_arg],
+[                      if test [$]# -gt 0; then
+                           case $optarg in # ((
+                               -*) ;;
+                               *)  $1="$optarg"
+                                   test -r "$optarg" || {
+                                       func_error "$opt: cannot read file \`$optarg'."
+                                       exit_cmd=exit
+                                   }
+                                   shift ;;
+                           esac
+                       fi])
+
+
+# m4go_printopts
+# --------------
+# This macro expands to the complete command line option processing
+# loop, providing for user declared options from `M4SH_GETOPTS' as well
+# as support for `-x|--debug', `-\?|-h|--help' and `--version'.  The
+# latter two extract their output from a stylized comment at the start
+# of the script, and will not work correctly if the format is not
+# followed precisely.
+m4_define([m4go_printopts],
+[
+# Option defaults:
+opt_debug=false
+m4go_defaults
+
+# Parse options once, thoroughly.  This comes as soon as possible in the
+# script to make things like `--version' happen as quickly as we can.
+{M4SH_VERBATIM([[
+  # sed scripts
+  my_sed_single_opt='1s/^\(..\).*$/\1/;q'
+  my_sed_single_rest='1s/^..\(.*\)$/\1/;q'
+  my_sed_long_opt='1s/^\(--[^=]*\)=.*/\1/;q'
+  my_sed_long_arg='1s/^--[^=]*=//'
+]])
+  # this just eases exit handling
+  while test [$]# -gt 0; do
+    opt="[$]1"
+    shift
+    case $opt in
+      --debug|-x)      opt_debug=:
+                       func_echo "enabling shell trace mode"
+                       set -x
+                       ;;
+m4go_branches
+      -\?|-h)          func_usage                              ;;
+      --help)          func_help                               ;;
+      --version)       func_version                            ;;
+
+      # Separate optargs to long options:
+      --*=*)
+                       arg=`echo "$opt" | $SED "$my_sed_long_arg"`
+                       opt=`echo "$opt" | $SED "$my_sed_long_opt"`
+                       set dummy "$opt" "$arg" ${1+"[$]@"}
+                       shift
+                       ;;
+
+m4_ifset([m4go_shortargs], dnl (
+[      # Separate optargs to short options:
+      ]m4go_shortargs[)
+                       arg=`echo "$opt" |$SED "$my_sed_single_rest"`
+                       opt=`echo "$opt" |$SED "$my_sed_single_opt"`
+                       set dummy "$opt" "$arg" ${1+"[$]@"}
+                       shift
+                       ;;
+
+])m4_ifset([m4go_shortnoargs], dnl (
+[      # Separate non-argument short options:
+      ]m4go_shortnoargs[)
+                       rest=`echo "$opt" |$SED "$my_sed_single_rest"`
+                       opt=`echo "$opt" |$SED "$my_sed_single_opt"`
+                       set dummy "$opt" "-$rest" ${1+"[$]@"}
+                       shift
+                       ;;
+
+])      --)            break                                   ;;
+      -*)              func_fatal_help "unrecognized option \`$opt'" ;;
+      *)               set dummy "$opt" ${1+"[$]@"};   shift; break  ;;
+    esac
+  done
+m4_ifset([m4go_validation],
+[
+  # Validate options:
+m4go_validation
+])
+  # Bail if the options were screwed
+  $exit_cmd $EXIT_FAILURE
+}
+])
+
+
+## ------------------------- ##
+## 3. Supporting Shell Code. ##
+## ------------------------- ##
+
+# The shell functions below are expanded verbatim into the shell script
+# at `m4_include([getopt.m4sh]', which are necessary for the correct
+# operation of the automatic `--version' and `--help' options, among
+# others.
+
+m4_divert_pop(-1)M4SH_VERBATIM([[
 # func_version
 # Echo version message to standard output and exit.
 func_version ()
@@ -57,7 +522,7 @@ func_version ()
 # Echo short help message to standard output and exit.
 func_usage ()
 {
-    $SED -n '/^# Usage:/,/^#  *-h/ {
+    $SED -n '/^# Usage:/,/^#  *.*--help/ {
         s/^# //
        s/^# *$//
        s/\$progname/'$progname'/
@@ -98,7 +563,7 @@ func_help ()
 # exit_cmd.
 func_missing_arg ()
 {
-    func_error "missing argument for $1"
+    func_error "missing argument for $1."
     exit_cmd=exit
 }