]> Dogcows Code - chaz/tar/commitdiff
Port to latest gnulib. There were a lot of changes, so the
authorPaul Eggert <eggert@cs.ucla.edu>
Thu, 30 Nov 2006 00:14:10 +0000 (00:14 +0000)
committerPaul Eggert <eggert@cs.ucla.edu>
Thu, 30 Nov 2006 00:14:10 +0000 (00:14 +0000)
simplest way to get this up and running was to switch to coreutils
bootstrap procedure.  I noticed one feature missing after this
merge: the ability to update a single .po file.  I can add that
later if need be.
* README-cvs, bootstrap.conf: New files.
* lib/.cvsignore: Remove Makefile.am, printf-parse.c, vasnprintf.c.
* lib/printf-parse.c, lib/vasnprintf.c: New files, from coreutils,
to override gnulib, so that we don't need xsize.h.
* bootstrap: Replace with coreutils bootstrap, except add support
for paxutils.
* configure.ac (gl_USE_SYSTEM_EXTENSIONS): Remove, as gl_EARLY now
does this.
(gl_EARLY, gl_INIT): Add.
(tar_GNULIB): Remove.
* gnulib.modules: Add configmake.
* lib/Makefile.tmpl: Remove, replacing with....
* lib/Makefile.am: New file.
* src/Makefile.am (tar.o): Remove dependency: Automake does this
for us.
* src/tar.c: Include <configmake.h> and <rmt-command.h>, not
<localedir.h>.

13 files changed:
ChangeLog
README-cvs [new file with mode: 0644]
bootstrap
bootstrap.conf [new file with mode: 0644]
configure.ac
gnulib.modules
lib/.cvsignore
lib/Makefile.am [new file with mode: 0644]
lib/Makefile.tmpl [deleted file]
lib/printf-parse.c [new file with mode: 0644]
lib/vasnprintf.c [new file with mode: 0644]
src/Makefile.am
src/tar.c

index 58873bdb820454b7d33d1d63bd8ae1b3b775d8a2..652c428457fac21340c8b2715ea6472940a37f0a 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,28 @@
+2006-11-29  Paul Eggert  <eggert@cs.ucla.edu>
+
+       Port to latest gnulib.  There were a lot of changes, so the
+       simplest way to get this up and running was to switch to coreutils
+       bootstrap procedure.  I noticed one feature missing after this
+       merge: the ability to update a single .po file.  I can add that
+       later if need be.
+       * README-cvs, bootstrap.conf: New files.
+       * lib/.cvsignore: Remove Makefile.am, printf-parse.c, vasnprintf.c.
+       * lib/printf-parse.c, lib/vasnprintf.c: New files, from coreutils,
+       to override gnulib, so that we don't need xsize.h.
+       * bootstrap: Replace with coreutils bootstrap, except add support
+       for paxutils.
+       * configure.ac (gl_USE_SYSTEM_EXTENSIONS): Remove, as gl_EARLY now
+       does this.
+       (gl_EARLY, gl_INIT): Add.
+       (tar_GNULIB): Remove.
+       * gnulib.modules: Add configmake.
+       * lib/Makefile.tmpl: Remove, replacing with....
+       * lib/Makefile.am: New file.
+       * src/Makefile.am (tar.o): Remove dependency: Automake does this
+       for us.
+       * src/tar.c: Include <configmake.h> and <rmt-command.h>, not
+       <localedir.h>.
+
 2006-11-13  Sergey Poznyakoff  <gray@gnu.org.ua>
 
        * src/xheader.c (mtime_coder): Treat non-null data as a pointer to
diff --git a/README-cvs b/README-cvs
new file mode 100644 (file)
index 0000000..dd27837
--- /dev/null
@@ -0,0 +1,70 @@
+-*- outline -*-
+
+These notes intend to help people working on the CVS version of
+this package.
+
+* Requirements
+
+Only the sources are installed in the CVS repository (to ease the
+maintenance, merges etc.), therefore you will have to get the latest
+stable versions of the maintainer tools we depend upon, including:
+
+- Automake <http://www.gnu.org/software/automake/>
+- Autoconf <http://www.gnu.org/software/autoconf/>
+- Bison <http://www.gnu.org/software/bison/>
+- Gettext <http://www.gnu.org/software/gettext/>
+- Gzip <http://www.gnu.org/software/gzip/>
+- Tar <http://www.gnu.org/software/tar/>
+- Wget <http://www.gnu.org/software/wget/>
+
+As of this writing, the latest stable version of Gzip is 1.2.4 but we
+suggest using test version 1.3.5 (or later, if one becomes available).
+
+Valgrind <http://valgrind.org/> is also highly recommended, if
+Valgrind supports your architecture.
+
+Only building the initial full source tree will be a bit painful,
+later, a plain `cvs update -P && make' should be sufficient.
+
+* First CVS checkout
+
+Obviously, if you are reading these notes, you did manage to check out
+this package from CVS.  The next step is to get other files needed to
+build, which are extracted from other source packages:
+
+       $ ./bootstrap
+
+And there you are!  Just
+
+       $ ./configure
+       $ make
+       $ make check
+
+At this point, there should be no difference between your local copy,
+and the CVS master copy:
+
+       $ cvs diff
+
+should output no difference.
+
+Enjoy!
+
+-----
+
+Copyright (C) 2002, 2003, 2004, 2005, 2006 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 2, 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, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, USA.
index c250cf05bdfb1854e6191d56b8aa4852d1b3296a..5e7082ad621477ca996b3d39555409a232b58fa3 100755 (executable)
--- a/bootstrap
+++ b/bootstrap
 
 # Written by Paul Eggert and Sergey Poznyakoff.
 
-package=tar
-
-# Translation Project URL, for the registry of all projects.
-TP_URL='http://www.iro.umontreal.ca/translation/registry.cgi?domain='
+nl='
+'
 
 # Ensure file names are sorted consistently across platforms.
 # Also, ensure diagnostics are in English, e.g., "wget --help" below.
@@ -32,215 +30,182 @@ LC_ALL=C
 export LC_ALL
 
 usage() {
- cat <<EOF
- usage: $0 [--gnulib-srcdir=DIR][--paxutils-srcdir=DIR][--cvs-auth=AUTH-METHOD][--cvs-user=USERNAME][--no-po]
- Options are:
- --paxutils-srcdir=DIRNAME    Specify the local directory where paxutils
-                              sources reside. Use this if you already
-                              have paxutils sources on your machine, and
-                              do not want to waste your bandwidth dowloading
-                              them again.
- --gnulib-srcdir=DIRNAME      Specify the local directory where gnulib
-                              sources reside. Use this if you already
-                              have gnulib sources on your machine, and
-                              do not want to waste your bandwidth dowloading
-                              them again.
- --cvs-auth=METHOD            Set the CVS access method used for downloading
-                              gnulib files. METHOD is one of the keywords
-                              accepted by cvs -d option (see info cvs
-                              repository).
- --cvs-user=USERNAME          Set the CVS username to be used when accessing
-                              the gnulib repository.
- --no-po                      Do not download po files.
- --update-po[=LANG]           Update po file(s) and exit.
-
-If the file \`.bootstrap' exists in the current working directory, its
-contents is read, comments and empty lines removed, shell variables expanded
-and the result is prepended to the command line options.
-
-Running without arguments will suffice in most cases. It is equivalent
-to
-
-    ./bootstrap --cvs-auth=pserver
-
-EOF
+  echo >&2 "\
+Usage: $0 [OPTION]...
+Bootstrap this package from the checked-out sources.
+
+Options:
+ --paxutils-srcdir=DIRNAME  Specify the local directory where paxutils
+                          sources reside. Use this if you already
+                          have paxutils sources on your machine, and
+                          do not want to waste your bandwidth dowloading
+                          them again.
+ --gnulib-srcdir=DIRNAME  Specify the local directory where gnulib
+                          sources reside.  Use this if you already
+                          have gnulib sources on your machine, and
+                          do not want to waste your bandwidth dowloading
+                          them again.
+ --copy                   Copy files instead of creating symbolic links.
+ --force                  Attempt to bootstrap even if the sources seem
+                          not to have been checked out.
+ --skip-po                Do not download po files.
+ --cvs-user=USERNAME      Set the CVS username to be used when accessing
+                          the gnulib repository.
+
+If the file .bootstrap.conf exists in the current working directory, its
+contents are read as shell variables to configure the bootstrap.
+
+Running without arguments will suffice in most cases.
+"
 }
 
-# Read configuration file
-if [ -r .bootstrap ]; then
-  echo "$0: Reading configuration file .bootstrap"
-  eval set -- "`sed 's/#.*$//;/^$/d' .bootstrap | tr '\n' ' '` $*"
-fi
+checkout() {
+  if [ ! -d $1 ]; then
+    echo "$0: getting $1 files..."
+
+    case ${CVS_AUTH-pserver} in
+    pserver)
+      CVS_PREFIX=':pserver:anonymous@';;
+    ssh)
+      CVS_PREFIX="$CVS_USER${CVS_USER+@}";;
+    *)
+      echo "$0: $CVS_AUTH: Unknown CVS access method" >&2
+      exit 1;;
+    esac
+
+    case $CVS_RSH in
+    '') CVS_RSH=ssh; export CVS_RSH;;
+    esac
+
+    trap "cleanup $1" 1 2 13 15
+
+    cvs -z3 -q -d ${CVS_PREFIX}cvs.savannah.gnu.org:/cvsroot/"$1" co $1 ||
+      cleanup $1
+
+    trap - 1 2 13 15
+  fi
+}
+
+cleanup() {
+  status=$?
+  rm -fr $1
+  exit $status
+}
+
+# Configuration.
+
+# List of gnulib modules needed.
+gnulib_modules=
+
+# Any gnulib files needed that are not in modules.
+gnulib_files=
+
+# Translation Project URL, for the registry of all projects
+# and for the translation-team master directory.
+TP_URL='http://www.iro.umontreal.ca/translation/registry.cgi?domain='
+TP_PO_URL='http://www.iro.umontreal.ca/translation/teams/PO/'
+
+extract_package_name='
+  /^AC_INIT(/{
+     /.*,.*,.*,/{
+       s///
+       s/[][]//g
+       p
+       q
+     }
+     s/AC_INIT(\[*//
+     s/]*,.*//
+     s/^GNU //
+     y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/
+     s/[^A-Za-z0-9_]/-/g
+     p
+  }
+'
+package=`sed -n "$extract_package_name" configure.ac` || exit
+
+# Extra files from gnulib, which override files from other sources.
+gnulib_extra_files='
+       build-aux/announce-gen
+       build-aux/install-sh
+       build-aux/missing
+       build-aux/mdate-sh
+       build-aux/texinfo.tex
+       build-aux/depcomp
+       build-aux/config.guess
+       build-aux/config.sub
+       doc/INSTALL
+'
+
+# Other locale categories that need message catalogs.
+EXTRA_LOCALE_CATEGORIES=
+
+# Additional xgettext options to use.  Use "\\\newline" to break lines.
+XGETTEXT_OPTIONS='\\\
+ --flag=_:1:pass-c-format\\\
+ --flag=N_:1:pass-c-format\\\
+ --flag=error:3:c-format --flag=error_at_line:5:c-format\\\
+'
+
+# Files we don't want to import.
+excluded_files=
+
+# File that should exist in the top directory of a checked out hierarchy,
+# but not in a distribution tarball.
+CVS_only_file=README-cvs
+
+# Whether to use copies instead of symlinks.
+copy=false
+
+# Override the default configuration, if necessary.
+test -r bootstrap.conf && . ./bootstrap.conf
+
+# Translate configuration into internal form.
 
 # Parse options.
 
-DOWNLOAD_PO=yes
 for option
 do
   case $option in
   --help)
     usage
     exit;;
-  --gnulib-srcdir=*)
-    GNULIB_SRCDIR=`expr "$option" : '--gnulib-srcdir=\(.*\)'`;;
   --paxutils-srcdir=*)
     PAXUTILS_SRCDIR=`expr "$option" : '--paxutils-srcdir=\(.*\)'`;;
-  --cvs-auth=*)
-    CVS_AUTH=`expr "$option" : '--cvs-auth=\(.*\)'`;;
+  --gnulib-srcdir=*)
+    GNULIB_SRCDIR=`expr "$option" : '--gnulib-srcdir=\(.*\)'`;;
   --cvs-user=*)
     CVS_USER=`expr "$option" : '--cvs-user=\(.*\)'`;;
-  --no-po)
-    DOWNLOAD_PO=no;;
-  --update-po=*)
-    DOWNLOAD_PO=`expr "$option" : '--update-po=\(.*\)'`;;
-  --update-po)
-    DOWNLOAD_PO=only;;
+  --skip-po | --no-po) # --no-po is for compatibility with 'tar' tradition.
+    SKIP_PO=t;;
+  --force)
+    CVS_only_file=;;
+  --copy)
+    copy=true;;
   *)
     echo >&2 "$0: $option: unknown option"
     exit 1;;
   esac
 done
 
-# Get translations.
-
-get_translations() {
-  subdir=$1
-  domain=$2
-  po_file=$3
-
-  echo "$0: getting translations into $subdir for $domain..."
-
-  case $po_file in
-  '') (cd $subdir && rm -f dummy `ls | sed -n '/\.gmo$/p; /\.po/p'`);;
-  esac &&
-
-  $WGET_COMMAND -O "$subdir/$domain.html" "$TP_URL$domain" &&
-
-  sed -n 's|.*"http://[^"]*/translation/teams/PO/\([^/"]*\)/'"$domain"'-\([^/"]*\)\.[^."]*\.po".*|\1.\2|p' <"$subdir/$domain.html" |
-  sort -k 1,1 -k 2,2n -k2,2 -k3,3n -k3,3 -k4,4n -k4,4 -k5,5n -k5.5 |
-  awk -F. '
-    { if (lang && $1 != lang) print lang, ver }
-    { lang = $1; ver = substr($0, index($0, ".") + 1) }
-    END { if (lang) print lang, ver }
-  ' |
-  awk -v domain="$domain" -v po_file="$po_file" -v subdir="$subdir" '
-    {
-      lang = $1
-      if (po_file && po_file != (lang ".po")) next
-
-      # Work around bugs in translations uncovered by gettext 0.15.
-      # This workaround can be removed once the translations are fixed.
-      if (lang == "hu" || lang == "zh_TW") next
-
-      ver = $2
-      urlfmt = ""
-      printf "$WGET_COMMAND -O %s/%s.po 'http://www.iro.umontreal.ca/translation/teams/PO/%s/%s-%s.%s.po' &&\n", subdir, lang, lang, domain, ver, lang
-    }
-    END { print ":" }
-  ' |
-  sh &&
-  ls "$subdir"/*.po | sed 's|.*/||; s|\.po$||' >"$subdir/LINGUAS" &&
-  rm "$subdir/$domain.html"
-}
-
-update_po() {
-  if [ $# = 1 ]; then
-    case $1 in
-    *.po)  POFILE=$1;;
-    *)     POFILE=${1}.po;;
-    esac
-    get_translations po $package "$POFILE"
-  else
-    get_translations po $package
-  fi
-}
-
-case $DOWNLOAD_PO in
-no) ;;
-*)
-  case `wget --help` in
-  *'--no-cache'*)
-    no_cache='--no-cache';;
-  *'--cache=on/off'*)
-    no_cache='--cache=off';;
-  *)
-    no_cache='';;
-  esac
-
-  WGET_COMMAND="wget -nv $no_cache"
-  export WGET_COMMAND
-esac
-
-case $DOWNLOAD_PO in
-only)  update_po
-       exit
-       ;;
-no|yes) ;;
-*)     update_po $DOWNLOAD_PO
-       exit
-esac
-
+if test -n "$CVS_only_file" && test ! -r "$CVS_only_file"; then
+  echo "$0: Bootstrapping from a non-checked-out distribution is risky." >&2
+  exit 1
+fi
 
 echo "$0: Bootstrapping CVS $package..."
 
-build_cvs_prefix() {
-  CVS_PREFIX=:${1}:
-  if [ "${2}" != - ]; then
-    CVS_PREFIX=${CVS_PREFIX}${2}@
-  fi
-  if [ "$1" = "ext" ]; then
-    if [ -z "${CVS_RSH}" ]; then
-       CVS_RSH=ssh
-       export CVS_RSH
-    fi
-  fi
-}
-
-# checkout package
-checkout() {
-  if [ ! -d $1 ]; then
-    echo "$0: getting $1 files..."
-
-    trap exit 1 2 13 15
-    trap 'rm -fr $1; exit 1' 0
-
-    case "${CVS_AUTH-pserver}" in
-    pserver) build_cvs_prefix pserver ${CVS_USER:-anonymous}
-             ;;
-    gserver|server)
-            build_cvs_prefix $CVS_AUTH ${CVS_USER--}
-            ;;
-    ext)     build_cvs_prefix $CVS_AUTH ${CVS_USER--}
-             ;;
-    *)       echo "$0: Unknown CVS access method" >&2
-            exit 1;;
-    esac
-    cvs -q -d ${CVS_PREFIX}cvs.sv.gnu.org:/cvsroot/$1 co $1 || exit
-
-    trap - 0
-  fi
-}
-
-gnulib_modules=
-newline='
-'
+# Get paxutils files.
 
-get_modules() {
-  new_gnulib_modules=`sed '/^[  ]*#/d; /^[      ]*$/d' $*`
-  case $gnulib_modules,$new_gnulib_modules in
-  ?*,?*) new_gnulib_modules=$newline$new_gnulib_modules;;
-  esac
-  gnulib_modules=$gnulib_modules$new_gnulib_modules
-}
-
-# Get paxutils files
 case ${PAXUTILS_SRCDIR--} in
 -) checkout paxutils
    PAXUTILS_SRCDIR=paxutils
 esac
 
 if [ -r $PAXUTILS_SRCDIR/gnulib.modules ]; then
-  get_modules $PAXUTILS_SRCDIR/gnulib.modules
+  gnulib_modules=`
+    (echo "$gnulib_modules"; grep '^[^#]' $PAXUTILS_SRCDIR/gnulib.modules) |
+    sort -u
+  `
 fi
 
 # copy_files srcdir dstdir
@@ -286,110 +251,265 @@ copy_files ${PAXUTILS_SRCDIR}/paxlib lib pax
 # Get gnulib files.
 
 case ${GNULIB_SRCDIR--} in
--) checkout gnulib
-   GNULIB_SRCDIR=gnulib
+-)
+  checkout gnulib
+  GNULIB_SRCDIR=gnulib
 esac
 
 gnulib_tool=$GNULIB_SRCDIR/gnulib-tool
 <$gnulib_tool || exit
 
-get_modules gnulib.modules
+# Get translations.
 
-gnulib_modules=`echo "$gnulib_modules" | sort -u`
-previous_gnulib_modules=
-while [ "$gnulib_modules" != "$previous_gnulib_modules" ]; do
-  previous_gnulib_modules=$gnulib_modules
-  gnulib_modules=`
-    (echo "$gnulib_modules"
-     for gnulib_module in $gnulib_modules; do
-       $gnulib_tool --extract-dependencies $gnulib_module
-     done) | sort -u
-  `
-done
+get_translations() {
+  subdir=$1
+  domain=$2
 
-gnulib_files=`
-  (for gnulib_module in $gnulib_modules; do
-     $gnulib_tool --extract-filelist $gnulib_module
-   done) | sort -u
-`
+  case $WGET_COMMAND in
+  '')
+    echo "$0: wget not available; skipping translations";;
+  ?*)
+    echo "$0: getting translations into $subdir for $domain..." &&
+
+    (cd $subdir && rm -f dummy `ls | sed -n '/\.gmo$/p; /\.po/p'`) &&
+    $WGET_COMMAND -O "$subdir/$domain.html" "$TP_URL$domain" &&
+
+    sed -n 's|.*"http://[^"]*/translation/teams/PO/\([^/"]*\)/'"$domain"'-\([^/"]*\)\.[^."]*\.po".*|\1.\2|p' <"$subdir/$domain.html" |
+    sort -k 1,1 -k 2,2n -k2,2 -k3,3n -k3,3 -k4,4n -k4,4 -k5,5n -k5.5 |
+    awk -F. '
+      { if (lang && $1 != lang) print lang, ver }
+      { lang = $1; ver = substr($0, index($0, ".") + 1) }
+      END { if (lang) print lang, ver }
+    ' | awk -v domain="$domain" -v subdir="$subdir" '
+      {
+       lang = $1
+       ver = $2
+       urlfmt = ""
+       printf "{ $WGET_COMMAND -O %s/%s.po '\'"$TP_PO_URL"'/%s/%s-%s.%s.po'\'' &&\n", subdir, lang, lang, domain, ver, lang
+       printf "  msgfmt -c -o /dev/null %s/%s.po || {\n", subdir, lang
+       printf "    echo >&2 '\'"$0"': omitting translation for %s'\''\n", lang
+       printf "    rm -f %s/%s.po; }; } &&\n", subdir, lang
+      }
+      END { print ":" }
+    ' | WGET_COMMAND="$WGET_COMMAND" sh;;
+  esac &&
+  ls "$subdir"/*.po 2>/dev/null |
+    sed 's|.*/||; s|\.po$||' >"$subdir/LINGUAS" &&
+  rm -f "$subdir/$domain.html"
+}
 
-gnulib_dirs=`echo "$gnulib_files" | sed 's,/[^/]*$,,' | sort -u`
-mkdir -p $gnulib_dirs || exit
+case $SKIP_PO in
+'')
+  case `wget --help` in
+  *'--no-cache'*)
+    WGET_COMMAND='wget -nv --no-cache';;
+  *'--cache=on/off'*)
+    WGET_COMMAND='wget -nv --cache=off';;
+  *'--non-verbose'*)
+    WGET_COMMAND='wget -nv';;
+  *)
+    WGET_COMMAND='';;
+  esac
 
-for gnulib_file in $gnulib_files; do
-  dest=$gnulib_file
-  rm -f $dest &&
-  echo "$0: Copying file $GNULIB_SRCDIR/$gnulib_file" &&
-  cp -p $GNULIB_SRCDIR/$gnulib_file $dest || exit
-done
+  get_translations po $package || exit
 
-# This suppresses a bogus diagnostic
-# "warning: macro `AM_LANGINFO_CODESET' not found in library".
-echo "$0: patching m4/gettext.m4 to remove need for intl/* ..."
-sed '
-  /^AC_DEFUN(\[AM_INTL_SUBDIR],/,/^]/c\
-    AC_DEFUN([AM_INTL_SUBDIR], [])
-  /^AC_DEFUN(\[gt_INTL_SUBDIR_CORE],/,/^]/c\
-    AC_DEFUN([gt_INTL_SUBDIR_CORE], [])
-' m4/gettext.m4 >m4/gettext_gl.m4 || exit
+  if test -d runtime-po; then
+    get_translations runtime-po $package-runtime || exit
+  fi;;
+esac
 
-echo "$0: Creating m4/gnulib.m4"
-(echo "# This file is generated automatically. Please, do not edit."
- echo "#"
- echo "AC_DEFUN([${package}_GNULIB],["
- for gnulib_module in $gnulib_modules; do
-    echo "# $gnulib_module"
-    $gnulib_tool --extract-autoconf-snippet $gnulib_module
- done | sed '/AM_GNU_GETTEXT/d'
- echo "])") > ./m4/gnulib.m4
-
-echo "$0: Creating lib/Makefile.am"
-(echo "# This file is generated automatically. Do not edit!"
- cat lib/Makefile.tmpl
-
- for gnulib_module in $gnulib_modules; do
-    echo "# $gnulib_module"
-    $gnulib_tool --extract-automake-snippet $gnulib_module
- done | sed "s/lib_SOURCES/lib${package}_a_SOURCES/g" ) > lib/Makefile.am
+symlink_to_gnulib()
+{
+  src=$GNULIB_SRCDIR/$1
+  dst=${2-$1}
+
+  test -f "$src" && {
+    if $copy; then
+      {
+       test ! -h "$dst" || {
+         echo "$0: rm -f $dst" &&
+         rm -f "$dst"
+       }
+      } &&
+      test -f "$dst" &&
+      cmp -s "$src" "$dst" || {
+       echo "$0: cp -fp $src $dst" &&
+       cp -fp "$src" "$dst"
+      }
+    else
+      test -h "$dst" &&
+      src_ls=`ls -diL "$src" 2>/dev/null` && set $src_ls && src_i=$1 &&
+      dst_ls=`ls -diL "$dst" 2>/dev/null` && set $dst_ls && dst_i=$1 &&
+      test "$src_i" = "$dst_i" || {
+       dot_dots=
+       case $src in
+       /*) ;;
+       *)
+         case /$dst/ in
+         *//* | */../* | */./* | /*/*/*/*/*/)
+            echo >&2 "$0: invalid symlink calculation: $src -> $dst"
+            exit 1;;
+         /*/*/*/*/)    dot_dots=../../../;;
+         /*/*/*/)      dot_dots=../../;;
+         /*/*/)        dot_dots=../;;
+         esac;;
+       esac
+
+       echo "$0: ln -fs $dot_dots$src $dst" &&
+       ln -fs "$dot_dots$src" "$dst"
+      }
+    fi
+  }
+}
 
-# Get translations.
-if test "$DOWNLOAD_PO" = "yes"; then
-  update_po
-fi
+cp_mark_as_generated()
+{
+  cp_src=$1
+  cp_dst=$2
 
-# Reconfigure, getting other files.
+  if cmp -s "$cp_src" "$GNULIB_SRCDIR/$cp_dst"; then
+    symlink_to_gnulib "$cp_dst"
+  else
+    case $cp_dst in
+      *.[ch])             c1='/* '; c2=' */';;
+      *.texi)             c1='@c '; c2=     ;;
+      *.m4|*/Make*|Make*) c1='# ' ; c2=     ;;
+      *)                  c1=     ; c2=     ;;
+    esac
 
-echo "$0: autopoint --force ..."
-autopoint --force || exit
-
-# We don't need intl, so remove it.
-intl_files_to_remove='
-  intl
-  m4/gettext.m4
-  m4/glibc2.m4
-  m4/intdiv0.m4
-  m4/intmax.m4
-  m4/lcmessage.m4
-  m4/lock.m4
-  m4/printf-posix.m4
-  m4/visibility.m4
-'
-echo $0: rm -fr $intl_files_to_remove ...
-rm -fr $intl_files_to_remove || exit
+    if test -z "$c1"; then
+      cmp -s "$cp_src" "$cp_dst" || {
+       echo "$0: cp -f $cp_src $cp_dst" &&
+       cp -f "$cp_src" "$cp_dst"
+      }
+    else
+      # Copy the file first to get proper permissions if it
+      # doesn't already exist.  Then overwrite the copy.
+      cp "$cp_src" "$cp_dst-t" &&
+      (
+       echo "$c1-*- buffer-read-only: t -*- vi: set ro:$c2" &&
+       echo "${c1}DO NOT EDIT! GENERATED AUTOMATICALLY!$c2" &&
+       cat "$cp_src"
+      ) > $cp_dst-t &&
+      if cmp -s "$cp_dst-t" "$cp_dst"; then
+       rm -f "$cp_dst-t"
+      else
+       echo "$0: cp $cp_src $cp_dst # with edits" &&
+       mv -f "$cp_dst-t" "$cp_dst"
+      fi
+    fi
+  fi
+}
 
+version_controlled_file() {
+  dir=$1
+  file=$2
+  found=no
+  if test -d CVS; then
+    grep -F "/$file/" $dir/CVS/Entries 2>/dev/null |
+            grep '^/[^/]*/[0-9]' > /dev/null && found=yes
+  elif test -d .git; then
+    git-rm -n "$dir/$file" > /dev/null 2>&1 && found=yes
+  else
+    echo "$0: no version control for $dir/$file?" >&2
+  fi
+  test $found = yes
+}
 
-# Undo changes to gnulib files that autoreconf made.
+slurp() {
+  for dir in . `(cd $1 && find * -type d -print)`; do
+    copied=
+    sep=
+    for file in `ls $1/$dir`; do
+      test -d $1/$dir/$file && continue
+      for excluded_file in $excluded_files; do
+       test "$dir/$file" = "$excluded_file" && continue 2
+      done
+      if test $file = Makefile.am; then
+        copied=$copied${sep}gnulib.mk; sep=$nl
+       remove_intl='/^[^#].*\/intl/s/^/#/'
+        sed "$remove_intl" $1/$dir/$file | cmp -s - $dir/gnulib.mk || {
+         echo "$0: Copying $1/$dir/$file to $dir/gnulib.mk ..." &&
+         rm -f $dir/gnulib.mk &&
+         sed "$remove_intl" $1/$dir/$file >$dir/gnulib.mk
+       }
+      elif { test "${2+set}" = set && test -r $2/$dir/$file; } ||
+          version_controlled_file $dir $file; then
+       echo "$0: $dir/$file overrides $1/$dir/$file"
+      else
+       copied=$copied$sep$file; sep=$nl
+       if test $file = gettext.m4; then
+         echo "$0: patching m4/gettext.m4 to remove need for intl/* ..."
+         rm -f $dir/$file
+         sed '
+           /^AC_DEFUN(\[AM_INTL_SUBDIR],/,/^]/c\
+             AC_DEFUN([AM_INTL_SUBDIR], [
+           /^AC_DEFUN(\[gt_INTL_SUBDIR_CORE],/,/^]/c\
+             AC_DEFUN([gt_INTL_SUBDIR_CORE], [])
+           $a\
+             AC_DEFUN([gl_LOCK_EARLY], [])
+         ' $1/$dir/$file >$dir/$file
+       else
+         cp_mark_as_generated $1/$dir/$file $dir/$file
+       fi
+      fi || exit
+    done
+
+    for dot_ig in .cvsignore .gitignore; do
+      ig=$dir/$dot_ig
+      if test -n "$copied" && test -f $ig; then
+       echo "$copied" | sort -u - $ig | cmp -s - $ig ||
+       echo "$copied" | sort -u - $ig -o $ig || exit
+      fi
+    done
+  done
+}
 
-for gnulib_file in $gnulib_files; do
-  test ! -f $gnulib_file || cmp -s $gnulib_file $GNULIB_SRCDIR/$gnulib_file || {
-    rm -f $gnulib_file &&
-    echo "$0: Copying file $GNULIB_SRCDIR/$gnulib_file again" &&
-    cp -p $GNULIB_SRCDIR/$gnulib_file $gnulib_file || exit
-  }
+
+# Create boot temporary directories to import from gnulib and gettext.
+
+bt='.#bootmp'
+bt2=${bt}2
+rm -fr $bt $bt2 &&
+mkdir $bt $bt2 || exit
+
+# Import from gnulib.
+
+test -d build-aux || {
+  echo "$0: mkdir build-aux ..." &&
+  mkdir build-aux
+} || exit
+gnulib_tool_options="\
+ --import\
+ --no-changelog\
+ --aux-dir $bt/build-aux\
+ --doc-base $bt/doc\
+ --lib lib$package\
+ --m4-base $bt/m4/\
+ --source-base $bt/lib/\
+ --tests-base $bt/tests\
+ --local-dir gl\
+"
+echo "$0: $gnulib_tool $gnulib_tool_options --import ..."
+$gnulib_tool $gnulib_tool_options --import $gnulib_modules &&
+slurp $bt || exit
+
+for file in $gnulib_files; do
+  symlink_to_gnulib $file || exit
 done
 
-# Make sure aclocal.m4 is not older than input files.
-sleep 1
+
+# Import from gettext.
+
+echo "$0: (cd $bt2; autopoint) ..."
+cp configure.ac $bt2 &&
+(cd $bt2 && autopoint && rm configure.ac) &&
+slurp $bt2 $bt || exit
+
+rm -fr $bt $bt2 || exit
+
+
+# Reconfigure, getting other files.
 
 for command in \
   'aclocal --force -I m4' \
@@ -402,25 +522,46 @@ do
 done
 
 
+# Get some extra files from gnulib, overriding existing files.
+
+for file in $gnulib_extra_files; do
+  case $file in
+  */INSTALL) dst=INSTALL;;
+  *) dst=$file;;
+  esac
+  symlink_to_gnulib $file $dst || exit
+done
+
+
 # Create gettext configuration.
 echo "$0: Creating po/Makevars from po/Makevars.template ..."
+rm -f po/Makevars
 sed '
+  /^EXTRA_LOCALE_CATEGORIES *=/s/=.*/= '"$EXTRA_LOCALE_CATEGORIES"'/
   /^MSGID_BUGS_ADDRESS *=/s/=.*/= bug-'"$package"'@gnu.org/
   /^XGETTEXT_OPTIONS *=/{
     s/$/ \\/
     a\
-       --flag=_:1:pass-c-format \\\
-       --flag=N_:1:pass-c-format \\\
-       --flag=error:3:c-format --flag=error_at_line:5:c-format \\\
-       --flag=asnprintf:3:c-format --flag=vasnprintf:3:c-format \\\
-       --flag=argp_error:2:c-format \\\
-       --flag=__argp_error:2:c-format \\\
-       --flag=argp_failure:4:c-format \\\
-       --flag=__argp_failure:4:c-format \\\
-       --flag=argp_fmtstream_printf:2:c-format \\\
-       --flag=__argp_fmtstream_printf:2:c-format
+       '"$XGETTEXT_OPTIONS"' $${end_of_xgettext_options+}
   }
 ' po/Makevars.template >po/Makevars
 
+if test -d runtime-po; then
+  # Similarly for runtime-po/Makevars, but not quite the same.
+  rm -f runtime-po/Makevars
+  sed '
+    /^DOMAIN *=.*/s/=.*/= '"$package"'-runtime/
+    /^subdir *=.*/s/=.*/= runtime-po/
+    /^MSGID_BUGS_ADDRESS *=/s/=.*/= bug-'"$package"'@gnu.org/
+    /^XGETTEXT_OPTIONS *=/{
+      s/$/ \\/
+      a\
+         '"$XGETTEXT_OPTIONS_RUNTIME"' $${end_of_xgettext_options+}
+    }
+  ' <po/Makevars.template >runtime-po/Makevars
+
+  # Copy identical files from po to runtime-po.
+  (cd po && cp -p Makefile.in.in *-quot *.header *.sed *.sin ../runtime-po)
+fi
 
 echo "$0: done.  Now you can run './configure'."
diff --git a/bootstrap.conf b/bootstrap.conf
new file mode 100644 (file)
index 0000000..16d92ed
--- /dev/null
@@ -0,0 +1,61 @@
+# Bootstrap configuration.
+
+# Copyright (C) 2006 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 2, 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, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+# 02110-1301, USA.
+
+
+# We don't need these modules, even though gnulib-tool mistakenly
+# includes them because of gettext dependencies.
+avoided_gnulib_modules='
+       --avoid=lock
+       --avoid=size_max
+       --avoid=xsize
+'
+
+# gnulib modules used by this package.
+gnulib_modules="$avoided_gnulib_modules
+`grep '^[^#]' gnulib.modules`
+"
+
+# Additional xgettext options to use.  Use "\\\newline" to break lines.
+XGETTEXT_OPTIONS=$XGETTEXT_OPTIONS'\\\
+ --flag=_:1:pass-c-format\\\
+ --flag=N_:1:pass-c-format\\\
+ --flag=error:3:c-format --flag=error_at_line:5:c-format\\\
+ --flag=asnprintf:3:c-format --flag=vasnprintf:3:c-format\\\
+ --flag=argp_error:2:c-format\\\
+ --flag=__argp_error:2:c-format\\\
+ --flag=argp_failure:4:c-format\\\
+ --flag=__argp_failure:4:c-format\\\
+ --flag=argp_fmtstream_printf:2:c-format\\\
+ --flag=__argp_fmtstream_printf:2:c-format\\\
+'
+
+# Gettext supplies these files, but we don't need them since
+# we don't have an intl subdirectory.
+excluded_files='
+    m4/glibc2.m4
+    m4/intdiv0.m4
+    m4/lcmessage.m4
+    m4/lock.m4
+    m4/printf-posix.m4
+    m4/size_max.m4
+    m4/uintmax_t.m4
+    m4/ulonglong.m4
+    m4/visibility.m4
+    m4/xsize.m4
+'
index 1ae29699523b57bd868a2641b87a178ebc468713..c6bb4212037607f7bd7b48548378ef261cae7a05 100644 (file)
@@ -25,11 +25,12 @@ AC_CONFIG_HEADERS([config.h:config.hin])
 AC_PREREQ([2.60])
 AM_INIT_AUTOMAKE([1.9 gnits tar-ustar dist-bzip2 dist-shar std-options])
 
-gl_USE_SYSTEM_EXTENSIONS
 AC_PROG_CC
 AC_EXEEXT
 AC_PROG_RANLIB
 AC_PROG_YACC
+gl_EARLY
+
 AC_SYS_LARGEFILE
 AC_ISC_POSIX
 AC_C_INLINE
@@ -82,7 +83,7 @@ AC_CHECK_TYPE(ino_t, unsigned)
 gt_TYPE_SSIZE_T
 
 # gnulib modules
-tar_GNULIB
+gl_INIT
 # paxutils modules
 tar_PAXUTILS
 
@@ -213,7 +214,7 @@ AC_CHECK_TYPE(iconv_t,:,
 
 # Gettext.
 AM_GNU_GETTEXT([external], [need-formatstring-macros])
-AM_GNU_GETTEXT_VERSION([0.15])
+AM_GNU_GETTEXT_VERSION([0.16])
 
 # Initialize the test suite.
 AC_CONFIG_TESTDIR(tests)
index c32440e428d058d50f6808683a796c5b59424db1..d313483efa745c45869a06e7fa655a1b5aa02005 100644 (file)
@@ -6,6 +6,7 @@ argmatch
 argp
 backupfile
 closeout
+configmake
 dirname
 error
 exclude
index ff13bff25aef5324593060a4d23d0a222aa20179..b1620608a904afcd9fdd6fbca5270b4e40efa026 100644 (file)
@@ -1,6 +1,5 @@
 .deps
 Makefile
-Makefile.am
 Makefile.in
 __fpending.c
 __fpending.h
@@ -133,7 +132,6 @@ paxnames.c
 pipe-safer.c
 printf-args.c
 printf-args.h
-printf-parse.c
 printf-parse.h
 quote.c
 quote.h
@@ -209,7 +207,6 @@ unsetenv.c
 utime.c
 utimens.c
 utimens.h
-vasnprintf.c
 vasnprintf.h
 verify.h
 version-etc-fsf.c
diff --git a/lib/Makefile.am b/lib/Makefile.am
new file mode 100644 (file)
index 0000000..b9fc8a4
--- /dev/null
@@ -0,0 +1,41 @@
+# Makefile for GNU tar library.                        -*- Makefile -*-
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1999, 2000, 2001, 2003, 2004,
+# 2005, 2006 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 2 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, write to the Free Software Foundation, Inc.,
+# 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+include gnulib.mk
+
+rmt-command.h : Makefile
+       rm -f $@-t $@
+       echo "#ifndef DEFAULT_RMT_COMMAND" >> $@-t
+       echo "# define DEFAULT_RMT_COMMAND \"$(DEFAULT_RMT_DIR)/`echo rmt | sed '$(transform)'`$(EXEEXT)\"" >> $@-t
+       echo "#endif" >> $@-t
+       mv $@-t $@
+BUILT_SOURCES += rmt-command.h
+CLEANFILES += rmt-command.h rmt-command.h-t
+
+noinst_HEADERS += system.h system-ioctl.h rmt.h paxlib.h stdopen.h
+libtar_a_SOURCES += \
+  paxerror.c paxexit.c paxlib.h paxnames.c \
+  prepargs.c prepargs.h \
+  rtapelib.c \
+  rmt.h \
+  stdopen.c stdopen.h \
+  system.h system-ioctl.h
+
+libtar_a_LIBADD += $(LIBOBJS)
+libtar_a_DEPENDENCIES += $(LIBOBJS)
diff --git a/lib/Makefile.tmpl b/lib/Makefile.tmpl
deleted file mode 100644 (file)
index 4869201..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-# Makefile for GNU tar library.        -*- Makefile -*-
-
-# Copyright (C) 1994, 1995, 1996, 1997, 1999, 2000, 2001, 2003, 2004,
-# 2005, 2006 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 2, 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, write to the Free Software
-## Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
-## 02110-1301, USA.
-
-noinst_LIBRARIES = libtar.a
-noinst_HEADERS = system.h system-ioctl.h localedir.h rmt.h paxlib.h stdopen.h
-libtar_a_SOURCES = prepargs.c prepargs.h rtapelib.c paxerror.c paxexit.c paxnames.c stdopen.c
-
-localedir = $(datadir)/locale
-
-DISTCLEANFILES = localedir.h
-localedir.h : Makefile
-       echo '#define LOCALEDIR "$(localedir)"' >$@
-       echo "#ifndef DEFAULT_RMT_COMMAND" >> $@
-       echo "# define DEFAULT_RMT_COMMAND \"$(DEFAULT_RMT_DIR)/`echo rmt | sed '$(transform)'`$(EXEEXT)\"" >> $@
-       echo "#endif" >> $@
-
-rtapelib.o: localedir.h
-
-libtar_a_LIBADD = $(LIBOBJS) $(ALLOCA)
-libtar_a_DEPENDENCIES = $(libtar_a_LIBADD)
-
-BUILT_SOURCES =
-AM_CPPFLAGS =
-EXTRA_DIST = Makefile.tmpl
-MAINTAINERCLEANFILES =
-MOSTLYCLEANFILES =
-lib_OBJECTS = $(libtar_a_OBJECTS)
-
-# Special rule for getdate
-#
-# Say $(srcdir), so GNU make does not report an ambiguity with the .y.c rule.
-$(srcdir)/getdate.c: getdate.y
-       cd $(srcdir) && \
-         $(YACC) $(YFLAGS) getdate.y && \
-         mv -f y.tab.c getdate.c
-
-SUFFIXES = .o .c .h
-CLEANFILES =
-# gnulib modules
diff --git a/lib/printf-parse.c b/lib/printf-parse.c
new file mode 100644 (file)
index 0000000..f8e0ced
--- /dev/null
@@ -0,0 +1,535 @@
+/* Formatted output to strings.
+   Copyright (C) 1999-2000, 2002-2004, 2006 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 2, 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, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+#include <config.h>
+
+/* Specification.  */
+#if WIDE_CHAR_VERSION
+# include "wprintf-parse.h"
+#else
+# include "printf-parse.h"
+#endif
+
+/* Get size_t, NULL.  */
+#include <stddef.h>
+
+/* Get intmax_t.  */
+#if HAVE_STDINT_H_WITH_UINTMAX
+# include <stdint.h>
+#endif
+#if HAVE_INTTYPES_H_WITH_UINTMAX
+# include <inttypes.h>
+#endif
+
+/* malloc(), realloc(), free().  */
+#include <stdlib.h>
+
+#ifndef SIZE_MAX
+# define SIZE_MAX ((size_t) -1)
+#endif
+
+#if WIDE_CHAR_VERSION
+# define PRINTF_PARSE wprintf_parse
+# define CHAR_T wchar_t
+# define DIRECTIVE wchar_t_directive
+# define DIRECTIVES wchar_t_directives
+#else
+# define PRINTF_PARSE printf_parse
+# define CHAR_T char
+# define DIRECTIVE char_directive
+# define DIRECTIVES char_directives
+#endif
+
+#ifdef STATIC
+STATIC
+#endif
+int
+PRINTF_PARSE (const CHAR_T *format, DIRECTIVES *d, arguments *a)
+{
+  const CHAR_T *cp = format;           /* pointer into format */
+  size_t arg_posn = 0;         /* number of regular arguments consumed */
+  size_t d_allocated;                  /* allocated elements of d->dir */
+  size_t a_allocated;                  /* allocated elements of a->arg */
+  size_t max_width_length = 0;
+  size_t max_precision_length = 0;
+
+  d->count = 0;
+  d_allocated = 1;
+  d->dir = malloc (d_allocated * sizeof (DIRECTIVE));
+  if (d->dir == NULL)
+    /* Out of memory.  */
+    return -1;
+
+  a->count = 0;
+  a_allocated = 0;
+  a->arg = NULL;
+
+#define REGISTER_ARG(_index_,_type_) \
+  {                                                                    \
+    size_t n = (_index_);                                              \
+    if (n >= a_allocated)                                              \
+      {                                                                        \
+       size_t memory_size;                                             \
+       argument *memory;                                               \
+                                                                       \
+       a_allocated *= 2;                                               \
+       if (a_allocated <= n)                                           \
+         a_allocated = n + 1;                                          \
+       if (SIZE_MAX / sizeof (argument) < a_allocated)                 \
+         /* Overflow, would lead to out of memory.  */                 \
+         goto error;                                                   \
+       memory_size = a_allocated * sizeof (argument);                  \
+       memory = (a->arg                                                \
+                 ? realloc (a->arg, memory_size)                       \
+                 : malloc (memory_size));                              \
+       if (memory == NULL)                                             \
+         /* Out of memory.  */                                         \
+         goto error;                                                   \
+       a->arg = memory;                                                \
+      }                                                                        \
+    while (a->count <= n)                                              \
+      a->arg[a->count++].type = TYPE_NONE;                             \
+    if (a->arg[n].type == TYPE_NONE)                                   \
+      a->arg[n].type = (_type_);                                       \
+    else if (a->arg[n].type != (_type_))                               \
+      /* Ambiguous type for positional argument.  */                   \
+      goto error;                                                      \
+  }
+
+  while (*cp != '\0')
+    {
+      CHAR_T c = *cp++;
+      if (c == '%')
+       {
+         size_t arg_index = ARG_NONE;
+         DIRECTIVE *dp = &d->dir[d->count];/* pointer to next directive */
+
+         /* Initialize the next directive.  */
+         dp->dir_start = cp - 1;
+         dp->flags = 0;
+         dp->width_start = NULL;
+         dp->width_end = NULL;
+         dp->width_arg_index = ARG_NONE;
+         dp->precision_start = NULL;
+         dp->precision_end = NULL;
+         dp->precision_arg_index = ARG_NONE;
+         dp->arg_index = ARG_NONE;
+
+         /* Test for positional argument.  */
+         if (*cp >= '0' && *cp <= '9')
+           {
+             const CHAR_T *np;
+
+             for (np = cp; *np >= '0' && *np <= '9'; np++)
+               ;
+             if (*np == '$')
+               {
+                 size_t n = 0;
+
+                 for (np = cp; *np >= '0' && *np <= '9'; np++)
+                   if (n < SIZE_MAX / 10)
+                     n = 10 * n + (*np - '0');
+                   else
+                     /* n too large for memory.  */
+                     goto error;
+                 if (n == 0)
+                   /* Positional argument 0.  */
+                   goto error;
+                 arg_index = n - 1;
+                 cp = np + 1;
+               }
+           }
+
+         /* Read the flags.  */
+         for (;;)
+           {
+             if (*cp == '\'')
+               {
+                 dp->flags |= FLAG_GROUP;
+                 cp++;
+               }
+             else if (*cp == '-')
+               {
+                 dp->flags |= FLAG_LEFT;
+                 cp++;
+               }
+             else if (*cp == '+')
+               {
+                 dp->flags |= FLAG_SHOWSIGN;
+                 cp++;
+               }
+             else if (*cp == ' ')
+               {
+                 dp->flags |= FLAG_SPACE;
+                 cp++;
+               }
+             else if (*cp == '#')
+               {
+                 dp->flags |= FLAG_ALT;
+                 cp++;
+               }
+             else if (*cp == '0')
+               {
+                 dp->flags |= FLAG_ZERO;
+                 cp++;
+               }
+             else
+               break;
+           }
+
+         /* Parse the field width.  */
+         if (*cp == '*')
+           {
+             dp->width_start = cp;
+             cp++;
+             dp->width_end = cp;
+             if (max_width_length < 1)
+               max_width_length = 1;
+
+             /* Test for positional argument.  */
+             if (*cp >= '0' && *cp <= '9')
+               {
+                 const CHAR_T *np;
+
+                 for (np = cp; *np >= '0' && *np <= '9'; np++)
+                   ;
+                 if (*np == '$')
+                   {
+                     size_t n = 0;
+
+                     for (np = cp; *np >= '0' && *np <= '9'; np++)
+                       if (n < SIZE_MAX / 10)
+                         n = 10 * n + (*np - '0');
+                       else
+                         /* n too large for memory.  */
+                         goto error;
+                     if (n == 0)
+                       /* Positional argument 0.  */
+                       goto error;
+                     dp->width_arg_index = n - 1;
+                     cp = np + 1;
+                   }
+               }
+             if (dp->width_arg_index == ARG_NONE)
+               {
+                 dp->width_arg_index = arg_posn++;
+                 if (dp->width_arg_index == ARG_NONE)
+                   /* arg_posn wrapped around.  */
+                   goto error;
+               }
+             REGISTER_ARG (dp->width_arg_index, TYPE_INT);
+           }
+         else if (*cp >= '0' && *cp <= '9')
+           {
+             size_t width_length;
+
+             dp->width_start = cp;
+             for (; *cp >= '0' && *cp <= '9'; cp++)
+               ;
+             dp->width_end = cp;
+             width_length = dp->width_end - dp->width_start;
+             if (max_width_length < width_length)
+               max_width_length = width_length;
+           }
+
+         /* Parse the precision.  */
+         if (*cp == '.')
+           {
+             cp++;
+             if (*cp == '*')
+               {
+                 dp->precision_start = cp - 1;
+                 cp++;
+                 dp->precision_end = cp;
+                 if (max_precision_length < 2)
+                   max_precision_length = 2;
+
+                 /* Test for positional argument.  */
+                 if (*cp >= '0' && *cp <= '9')
+                   {
+                     const CHAR_T *np;
+
+                     for (np = cp; *np >= '0' && *np <= '9'; np++)
+                       ;
+                     if (*np == '$')
+                       {
+                         size_t n = 0;
+
+                         for (np = cp; *np >= '0' && *np <= '9'; np++)
+                           if (n < SIZE_MAX / 10)
+                             n = 10 * n + (*np - '0');
+                           else
+                             /* n too large for memory.  */
+                             goto error;
+                         if (n == 0)
+                           /* Positional argument 0.  */
+                           goto error;
+                         dp->precision_arg_index = n - 1;
+                         cp = np + 1;
+                       }
+                   }
+                 if (dp->precision_arg_index == ARG_NONE)
+                   {
+                     dp->precision_arg_index = arg_posn++;
+                     if (dp->precision_arg_index == ARG_NONE)
+                       /* arg_posn wrapped around.  */
+                       goto error;
+                   }
+                 REGISTER_ARG (dp->precision_arg_index, TYPE_INT);
+               }
+             else
+               {
+                 size_t precision_length;
+
+                 dp->precision_start = cp - 1;
+                 for (; *cp >= '0' && *cp <= '9'; cp++)
+                   ;
+                 dp->precision_end = cp;
+                 precision_length = dp->precision_end - dp->precision_start;
+                 if (max_precision_length < precision_length)
+                   max_precision_length = precision_length;
+               }
+           }
+
+         {
+           arg_type type;
+
+           /* Parse argument type/size specifiers.  */
+           {
+             int flags = 0;
+
+             for (;;)
+               {
+                 if (*cp == 'h')
+                   {
+                     flags |= (1 << (flags & 1));
+                     cp++;
+                   }
+                 else if (*cp == 'L')
+                   {
+                     flags |= 4;
+                     cp++;
+                   }
+                 else if (*cp == 'l')
+                   {
+                     flags += 8;
+                     cp++;
+                   }
+#ifdef HAVE_INTMAX_T
+                 else if (*cp == 'j')
+                   {
+                     if (sizeof (intmax_t) > sizeof (long))
+                       {
+                         /* intmax_t = long long */
+                         flags += 16;
+                       }
+                     else if (sizeof (intmax_t) > sizeof (int))
+                       {
+                         /* intmax_t = long */
+                         flags += 8;
+                       }
+                     cp++;
+                   }
+#endif
+                 else if (*cp == 'z' || *cp == 'Z')
+                   {
+                     /* 'z' is standardized in ISO C 99, but glibc uses 'Z'
+                        because the warning facility in gcc-2.95.2 understands
+                        only 'Z' (see gcc-2.95.2/gcc/c-common.c:1784).  */
+                     if (sizeof (size_t) > sizeof (long))
+                       {
+                         /* size_t = long long */
+                         flags += 16;
+                       }
+                     else if (sizeof (size_t) > sizeof (int))
+                       {
+                         /* size_t = long */
+                         flags += 8;
+                       }
+                     cp++;
+                   }
+                 else if (*cp == 't')
+                   {
+                     if (sizeof (ptrdiff_t) > sizeof (long))
+                       {
+                         /* ptrdiff_t = long long */
+                         flags += 16;
+                       }
+                     else if (sizeof (ptrdiff_t) > sizeof (int))
+                       {
+                         /* ptrdiff_t = long */
+                         flags += 8;
+                       }
+                     cp++;
+                   }
+                 else
+                   break;
+               }
+
+             /* Read the conversion character.  */
+             c = *cp++;
+             switch (c)
+               {
+               case 'd': case 'i':
+#ifdef HAVE_LONG_LONG
+                 if (flags >= 16 || (flags & 4))
+                   type = TYPE_LONGLONGINT;
+                 else
+#endif
+                 if (flags >= 8)
+                   type = TYPE_LONGINT;
+                 else if (flags & 2)
+                   type = TYPE_SCHAR;
+                 else if (flags & 1)
+                   type = TYPE_SHORT;
+                 else
+                   type = TYPE_INT;
+                 break;
+               case 'o': case 'u': case 'x': case 'X':
+#ifdef HAVE_LONG_LONG
+                 if (flags >= 16 || (flags & 4))
+                   type = TYPE_ULONGLONGINT;
+                 else
+#endif
+                 if (flags >= 8)
+                   type = TYPE_ULONGINT;
+                 else if (flags & 2)
+                   type = TYPE_UCHAR;
+                 else if (flags & 1)
+                   type = TYPE_USHORT;
+                 else
+                   type = TYPE_UINT;
+                 break;
+               case 'f': case 'F': case 'e': case 'E': case 'g': case 'G':
+               case 'a': case 'A':
+#ifdef HAVE_LONG_DOUBLE
+                 if (flags >= 16 || (flags & 4))
+                   type = TYPE_LONGDOUBLE;
+                 else
+#endif
+                 type = TYPE_DOUBLE;
+                 break;
+               case 'c':
+                 if (flags >= 8)
+#ifdef HAVE_WINT_T
+                   type = TYPE_WIDE_CHAR;
+#else
+                   goto error;
+#endif
+                 else
+                   type = TYPE_CHAR;
+                 break;
+#ifdef HAVE_WINT_T
+               case 'C':
+                 type = TYPE_WIDE_CHAR;
+                 c = 'c';
+                 break;
+#endif
+               case 's':
+                 if (flags >= 8)
+#ifdef HAVE_WCHAR_T
+                   type = TYPE_WIDE_STRING;
+#else
+                   goto error;
+#endif
+                 else
+                   type = TYPE_STRING;
+                 break;
+#ifdef HAVE_WCHAR_T
+               case 'S':
+                 type = TYPE_WIDE_STRING;
+                 c = 's';
+                 break;
+#endif
+               case 'p':
+                 type = TYPE_POINTER;
+                 break;
+               case 'n':
+#ifdef HAVE_LONG_LONG
+                 if (flags >= 16 || (flags & 4))
+                   type = TYPE_COUNT_LONGLONGINT_POINTER;
+                 else
+#endif
+                 if (flags >= 8)
+                   type = TYPE_COUNT_LONGINT_POINTER;
+                 else if (flags & 2)
+                   type = TYPE_COUNT_SCHAR_POINTER;
+                 else if (flags & 1)
+                   type = TYPE_COUNT_SHORT_POINTER;
+                 else
+                   type = TYPE_COUNT_INT_POINTER;
+                 break;
+               case '%':
+                 type = TYPE_NONE;
+                 break;
+               default:
+                 /* Unknown conversion character.  */
+                 goto error;
+               }
+           }
+
+           if (type != TYPE_NONE)
+             {
+               dp->arg_index = arg_index;
+               if (dp->arg_index == ARG_NONE)
+                 {
+                   dp->arg_index = arg_posn++;
+                   if (dp->arg_index == ARG_NONE)
+                     /* arg_posn wrapped around.  */
+                     goto error;
+                 }
+               REGISTER_ARG (dp->arg_index, type);
+             }
+           dp->conversion = c;
+           dp->dir_end = cp;
+         }
+
+         d->count++;
+         if (d->count >= d_allocated)
+           {
+             DIRECTIVE *memory;
+
+             if (SIZE_MAX / (2 * sizeof (DIRECTIVE)) < d_allocated)
+               /* Overflow, would lead to out of memory.  */
+               goto error;
+             d_allocated *= 2;
+             memory = realloc (d->dir, d_allocated * sizeof (DIRECTIVE));
+             if (memory == NULL)
+               /* Out of memory.  */
+               goto error;
+             d->dir = memory;
+           }
+       }
+    }
+  d->dir[d->count].dir_start = cp;
+
+  d->max_width_length = max_width_length;
+  d->max_precision_length = max_precision_length;
+  return 0;
+
+error:
+  if (a->arg)
+    free (a->arg);
+  if (d->dir)
+    free (d->dir);
+  return -1;
+}
+
+#undef DIRECTIVES
+#undef DIRECTIVE
+#undef CHAR_T
+#undef PRINTF_PARSE
diff --git a/lib/vasnprintf.c b/lib/vasnprintf.c
new file mode 100644 (file)
index 0000000..78ead8e
--- /dev/null
@@ -0,0 +1,918 @@
+/* vsprintf with automatic memory allocation.
+   Copyright (C) 1999, 2002-2006 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 2, 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, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+/* Tell glibc's <stdio.h> to provide a prototype for snprintf().
+   This must come before <config.h> because <config.h> may include
+   <features.h>, and once <features.h> has been included, it's too late.  */
+#ifndef _GNU_SOURCE
+# define _GNU_SOURCE    1
+#endif
+
+#include <config.h>
+
+#ifndef IN_LIBINTL
+# include <alloca.h>
+#endif
+
+/* Specification.  */
+#if WIDE_CHAR_VERSION
+# include "vasnwprintf.h"
+#else
+# include "vasnprintf.h"
+#endif
+
+#include <stdio.h>     /* snprintf(), sprintf() */
+#include <stdlib.h>    /* abort(), malloc(), realloc(), free() */
+#include <string.h>    /* memcpy(), strlen() */
+#include <errno.h>     /* errno */
+#include <limits.h>    /* CHAR_BIT, INT_MAX */
+#include <float.h>     /* DBL_MAX_EXP, LDBL_MAX_EXP */
+#if WIDE_CHAR_VERSION
+# include "wprintf-parse.h"
+#else
+# include "printf-parse.h"
+#endif
+
+#ifndef SIZE_MAX
+# define SIZE_MAX ((size_t) -1)
+#endif
+
+/* Some systems, like OSF/1 4.0 and Woe32, don't have EOVERFLOW.  */
+#ifndef EOVERFLOW
+# define EOVERFLOW E2BIG
+#endif
+
+#ifdef HAVE_WCHAR_T
+# ifdef HAVE_WCSLEN
+#  define local_wcslen wcslen
+# else
+   /* Solaris 2.5.1 has wcslen() in a separate library libw.so. To avoid
+      a dependency towards this library, here is a local substitute.
+      Define this substitute only once, even if this file is included
+      twice in the same compilation unit.  */
+#  ifndef local_wcslen_defined
+#   define local_wcslen_defined 1
+static size_t
+local_wcslen (const wchar_t *s)
+{
+  const wchar_t *ptr;
+
+  for (ptr = s; *ptr != (wchar_t) 0; ptr++)
+    ;
+  return ptr - s;
+}
+#  endif
+# endif
+#endif
+
+#if WIDE_CHAR_VERSION
+# define VASNPRINTF vasnwprintf
+# define CHAR_T wchar_t
+# define DIRECTIVE wchar_t_directive
+# define DIRECTIVES wchar_t_directives
+# define PRINTF_PARSE wprintf_parse
+# define USE_SNPRINTF 1
+# if HAVE_DECL__SNWPRINTF
+   /* On Windows, the function swprintf() has a different signature than
+      on Unix; we use the _snwprintf() function instead.  */
+#  define SNPRINTF _snwprintf
+# else
+   /* Unix.  */
+#  define SNPRINTF swprintf
+# endif
+#else
+# define VASNPRINTF vasnprintf
+# define CHAR_T char
+# define DIRECTIVE char_directive
+# define DIRECTIVES char_directives
+# define PRINTF_PARSE printf_parse
+# define USE_SNPRINTF (HAVE_DECL__SNPRINTF || HAVE_SNPRINTF)
+# if HAVE_DECL__SNPRINTF
+   /* Windows.  */
+#  define SNPRINTF _snprintf
+# else
+   /* Unix.  */
+#  define SNPRINTF snprintf
+# endif
+#endif
+
+CHAR_T *
+VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list args)
+{
+  DIRECTIVES d;
+  arguments a;
+
+  if (PRINTF_PARSE (format, &d, &a) < 0)
+    {
+      errno = EINVAL;
+      return NULL;
+    }
+
+#define CLEANUP() \
+  free (d.dir);                                                                \
+  if (a.arg)                                                           \
+    free (a.arg);
+
+  if (printf_fetchargs (args, &a) < 0)
+    {
+      CLEANUP ();
+      errno = EINVAL;
+      return NULL;
+    }
+
+  {
+    size_t buf_neededlength;
+    CHAR_T *buf;
+    CHAR_T *buf_malloced;
+    const CHAR_T *cp;
+    size_t i;
+    DIRECTIVE *dp;
+    /* Output string accumulator.  */
+    CHAR_T *result;
+    size_t allocated;
+    size_t length;
+
+    /* Allocate a small buffer that will hold a directive passed to
+       sprintf or snprintf.  */
+    buf_neededlength = 7 + d.max_width_length + d.max_precision_length + 6;
+#if HAVE_ALLOCA
+    if (buf_neededlength < 4000 / sizeof (CHAR_T))
+      {
+       buf = (CHAR_T *) alloca (buf_neededlength * sizeof (CHAR_T));
+       buf_malloced = NULL;
+      }
+    else
+#endif
+      {
+       if (SIZE_MAX / sizeof (CHAR_T) < buf_neededlength)
+         goto out_of_memory_1;
+       buf = (CHAR_T *) malloc (buf_neededlength * sizeof (CHAR_T));
+       if (buf == NULL)
+         goto out_of_memory_1;
+       buf_malloced = buf;
+      }
+
+    if (resultbuf != NULL)
+      {
+       result = resultbuf;
+       allocated = *lengthp;
+      }
+    else
+      {
+       result = NULL;
+       allocated = 0;
+      }
+    length = 0;
+    /* Invariants:
+       result is either == resultbuf or == NULL or malloc-allocated.
+       If length > 0, then result != NULL.  */
+
+    /* Ensures that allocated >= length + extra.  Aborts through a jump to
+       out_of_memory if size is too big.  */
+#define ENSURE_ALLOCATION(extra) \
+  {                                                                         \
+    size_t needed = length + (extra);                                       \
+    if (needed < length)                                                    \
+      goto out_of_memory;                                                   \
+    if (needed > allocated)                                                 \
+      {                                                                             \
+       size_t memory_size;                                                  \
+       CHAR_T *memory;                                                      \
+                                                                            \
+       allocated = (allocated > 0 ? 2 * allocated : 12);                    \
+       if (needed > allocated)                                              \
+         allocated = needed;                                                \
+       if (SIZE_MAX / sizeof (CHAR_T) < allocated)                          \
+         goto out_of_memory;                                                \
+       memory_size = allocated * sizeof (CHAR_T);                           \
+       if (result == resultbuf || result == NULL)                           \
+         memory = (CHAR_T *) malloc (memory_size);                          \
+       else                                                                 \
+         memory = (CHAR_T *) realloc (result, memory_size);                 \
+       if (memory == NULL)                                                  \
+         goto out_of_memory;                                                \
+       if (result == resultbuf && length > 0)                               \
+         memcpy (memory, result, length * sizeof (CHAR_T));                 \
+       result = memory;                                                     \
+      }                                                                             \
+  }
+
+    for (cp = format, i = 0, dp = &d.dir[0]; ; cp = dp->dir_end, i++, dp++)
+      {
+       if (cp != dp->dir_start)
+         {
+           size_t n = dp->dir_start - cp;
+
+           ENSURE_ALLOCATION (n);
+           memcpy (result + length, cp, n * sizeof (CHAR_T));
+           length += n;
+         }
+       if (i == d.count)
+         break;
+
+       /* Execute a single directive.  */
+       if (dp->conversion == '%')
+         {
+           if (!(dp->arg_index == ARG_NONE))
+             abort ();
+           ENSURE_ALLOCATION (1);
+           result[length] = '%';
+           length += 1;
+         }
+       else
+         {
+           if (!(dp->arg_index != ARG_NONE))
+             abort ();
+
+           if (dp->conversion == 'n')
+             {
+               switch (a.arg[dp->arg_index].type)
+                 {
+                 case TYPE_COUNT_SCHAR_POINTER:
+                   *a.arg[dp->arg_index].a.a_count_schar_pointer = length;
+                   break;
+                 case TYPE_COUNT_SHORT_POINTER:
+                   *a.arg[dp->arg_index].a.a_count_short_pointer = length;
+                   break;
+                 case TYPE_COUNT_INT_POINTER:
+                   *a.arg[dp->arg_index].a.a_count_int_pointer = length;
+                   break;
+                 case TYPE_COUNT_LONGINT_POINTER:
+                   *a.arg[dp->arg_index].a.a_count_longint_pointer = length;
+                   break;
+#ifdef HAVE_LONG_LONG
+                 case TYPE_COUNT_LONGLONGINT_POINTER:
+                   *a.arg[dp->arg_index].a.a_count_longlongint_pointer = length;
+                   break;
+#endif
+                 default:
+                   abort ();
+                 }
+             }
+           else
+             {
+               arg_type type = a.arg[dp->arg_index].type;
+               CHAR_T *p;
+               unsigned int prefix_count;
+               int prefixes[2];
+#if !USE_SNPRINTF
+               size_t tmp_length;
+               CHAR_T tmpbuf[700];
+               CHAR_T *tmp;
+
+               /* Allocate a temporary buffer of sufficient size for calling
+                  sprintf.  */
+               {
+                 size_t width;
+                 size_t precision;
+
+                 width = 0;
+                 if (dp->width_start != dp->width_end)
+                   {
+                     if (dp->width_arg_index != ARG_NONE)
+                       {
+                         int arg;
+
+                         if (!(a.arg[dp->width_arg_index].type == TYPE_INT))
+                           abort ();
+                         arg = a.arg[dp->width_arg_index].a.a_int;
+                         width = (arg < 0 ? (unsigned int) (-arg) : arg);
+                       }
+                     else
+                       {
+                         const CHAR_T *digitp = dp->width_start;
+
+                         do
+                           {
+                             size_t w_tmp = width * 10 + (*digitp++ - '0');
+                             if (SIZE_MAX / 10 < width || w_tmp < width)
+                               goto out_of_memory;
+                             width = w_tmp;
+                           }
+                         while (digitp != dp->width_end);
+                       }
+                   }
+
+                 precision = 6;
+                 if (dp->precision_start != dp->precision_end)
+                   {
+                     if (dp->precision_arg_index != ARG_NONE)
+                       {
+                         int arg;
+
+                         if (!(a.arg[dp->precision_arg_index].type == TYPE_INT))
+                           abort ();
+                         arg = a.arg[dp->precision_arg_index].a.a_int;
+                         precision = (arg < 0 ? 0 : arg);
+                       }
+                     else
+                       {
+                         const CHAR_T *digitp = dp->precision_start + 1;
+
+                         precision = 0;
+                         while (digitp != dp->precision_end)
+                           {
+                             size_t p1 = 10 * precision + (*digitp++ - '0');
+                             precision = ((SIZE_MAX / 10 < precision
+                                           || p1 < precision)
+                                          ? SIZE_MAX : p1);
+                           }
+                       }
+                   }
+
+                 switch (dp->conversion)
+                   {
+
+                   case 'd': case 'i': case 'u':
+# ifdef HAVE_LONG_LONG
+                     if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT)
+                       tmp_length =
+                         (unsigned int) (sizeof (unsigned long long) * CHAR_BIT
+                                         * 0.30103 /* binary -> decimal */
+                                        )
+                         + 1; /* turn floor into ceil */
+                     else
+# endif
+                     if (type == TYPE_LONGINT || type == TYPE_ULONGINT)
+                       tmp_length =
+                         (unsigned int) (sizeof (unsigned long) * CHAR_BIT
+                                         * 0.30103 /* binary -> decimal */
+                                        )
+                         + 1; /* turn floor into ceil */
+                     else
+                       tmp_length =
+                         (unsigned int) (sizeof (unsigned int) * CHAR_BIT
+                                         * 0.30103 /* binary -> decimal */
+                                        )
+                         + 1; /* turn floor into ceil */
+                     if (tmp_length < precision)
+                       tmp_length = precision;
+                     /* Multiply by 2, as an estimate for FLAG_GROUP.  */
+                     /* Add 1, to account for a leading sign.  */
+                     tmp_length = (tmp_length < SIZE_MAX / 2
+                                   ? 2 * tmp_length + 1
+                                   : SIZE_MAX);
+                     break;
+
+                   case 'o':
+# ifdef HAVE_LONG_LONG
+                     if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT)
+                       tmp_length =
+                         (unsigned int) (sizeof (unsigned long long) * CHAR_BIT
+                                         * 0.333334 /* binary -> octal */
+                                        )
+                         + 1; /* turn floor into ceil */
+                     else
+# endif
+                     if (type == TYPE_LONGINT || type == TYPE_ULONGINT)
+                       tmp_length =
+                         (unsigned int) (sizeof (unsigned long) * CHAR_BIT
+                                         * 0.333334 /* binary -> octal */
+                                        )
+                         + 1; /* turn floor into ceil */
+                     else
+                       tmp_length =
+                         (unsigned int) (sizeof (unsigned int) * CHAR_BIT
+                                         * 0.333334 /* binary -> octal */
+                                        )
+                         + 1; /* turn floor into ceil */
+                     if (tmp_length < precision)
+                       tmp_length = precision;
+                     /* Add 1, to account for a leading sign.  */
+                     tmp_length += (tmp_length < SIZE_MAX);
+                     break;
+
+                   case 'x': case 'X':
+# ifdef HAVE_LONG_LONG
+                     if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT)
+                       tmp_length =
+                         (unsigned int) (sizeof (unsigned long long) * CHAR_BIT
+                                         * 0.25 /* binary -> hexadecimal */
+                                        )
+                         + 1; /* turn floor into ceil */
+                     else
+# endif
+                     if (type == TYPE_LONGINT || type == TYPE_ULONGINT)
+                       tmp_length =
+                         (unsigned int) (sizeof (unsigned long) * CHAR_BIT
+                                         * 0.25 /* binary -> hexadecimal */
+                                        )
+                         + 1; /* turn floor into ceil */
+                     else
+                       tmp_length =
+                         (unsigned int) (sizeof (unsigned int) * CHAR_BIT
+                                         * 0.25 /* binary -> hexadecimal */
+                                        )
+                         + 1; /* turn floor into ceil */
+                     if (tmp_length < precision)
+                       tmp_length = precision;
+                     /* Add 2, to account for a leading sign or alternate form.  */
+                     if (tmp_length <= SIZE_MAX / 2)
+                       tmp_length *= 2;
+                     break;
+
+                   case 'f': case 'F':
+# ifdef HAVE_LONG_DOUBLE
+                     if (type == TYPE_LONGDOUBLE)
+                       tmp_length =
+                         (unsigned int) (LDBL_MAX_EXP
+                                         * 0.30103 /* binary -> decimal */
+                                         * 2 /* estimate for FLAG_GROUP */
+                                        )
+                         + 1 /* turn floor into ceil */
+                         + 10; /* sign, decimal point etc. */
+                     else
+# endif
+                       tmp_length =
+                         (unsigned int) (DBL_MAX_EXP
+                                         * 0.30103 /* binary -> decimal */
+                                         * 2 /* estimate for FLAG_GROUP */
+                                        )
+                         + 1 /* turn floor into ceil */
+                         + 10; /* sign, decimal point etc. */
+                     tmp_length += precision;
+                     if (tmp_length < precision)
+                       goto out_of_memory;
+                     break;
+
+                   case 'e': case 'E': case 'g': case 'G':
+                   case 'a': case 'A':
+                     tmp_length =
+                       12; /* sign, decimal point, exponent etc. */
+                     tmp_length += precision;
+                     if (tmp_length < precision)
+                       goto out_of_memory;
+                     break;
+
+                   case 'c':
+# if defined HAVE_WINT_T && !WIDE_CHAR_VERSION
+                     if (type == TYPE_WIDE_CHAR)
+                       tmp_length = MB_CUR_MAX;
+                     else
+# endif
+                       tmp_length = 1;
+                     break;
+
+                   case 's':
+# ifdef HAVE_WCHAR_T
+                     if (type == TYPE_WIDE_STRING)
+                       {
+                         tmp_length =
+                           local_wcslen (a.arg[dp->arg_index].a.a_wide_string);
+
+#  if !WIDE_CHAR_VERSION
+                         if (SIZE_MAX / MB_CUR_MAX < tmp_length)
+                           goto out_of_memory;
+                         tmp_length *= MB_CUR_MAX;
+#  endif
+                       }
+                     else
+# endif
+                       tmp_length = strlen (a.arg[dp->arg_index].a.a_string);
+                     break;
+
+                   case 'p':
+                     tmp_length =
+                       (unsigned int) (sizeof (void *) * CHAR_BIT
+                                       * 0.25 /* binary -> hexadecimal */
+                                      )
+                         + 1 /* turn floor into ceil */
+                         + 2; /* account for leading 0x */
+                     break;
+
+                   default:
+                     abort ();
+                   }
+
+                 if (tmp_length < width)
+                   tmp_length = width;
+
+                 tmp_length++; /* account for trailing NUL */
+                 if (!tmp_length)
+                   goto out_of_memory;
+               }
+
+               if (tmp_length <= sizeof (tmpbuf) / sizeof (CHAR_T))
+                 tmp = tmpbuf;
+               else
+                 {
+                   if (SIZE_MAX / sizeof (CHAR_T) < tmp_length)
+                     /* Overflow, would lead to out of memory.  */
+                     goto out_of_memory;
+                   tmp = (CHAR_T *) malloc (tmp_length * sizeof (CHAR_T));
+                   if (tmp == NULL)
+                     /* Out of memory.  */
+                     goto out_of_memory;
+                 }
+#endif
+
+               /* Construct the format string for calling snprintf or
+                  sprintf.  */
+               p = buf;
+               *p++ = '%';
+               if (dp->flags & FLAG_GROUP)
+                 *p++ = '\'';
+               if (dp->flags & FLAG_LEFT)
+                 *p++ = '-';
+               if (dp->flags & FLAG_SHOWSIGN)
+                 *p++ = '+';
+               if (dp->flags & FLAG_SPACE)
+                 *p++ = ' ';
+               if (dp->flags & FLAG_ALT)
+                 *p++ = '#';
+               if (dp->flags & FLAG_ZERO)
+                 *p++ = '0';
+               if (dp->width_start != dp->width_end)
+                 {
+                   size_t n = dp->width_end - dp->width_start;
+                   memcpy (p, dp->width_start, n * sizeof (CHAR_T));
+                   p += n;
+                 }
+               if (dp->precision_start != dp->precision_end)
+                 {
+                   size_t n = dp->precision_end - dp->precision_start;
+                   memcpy (p, dp->precision_start, n * sizeof (CHAR_T));
+                   p += n;
+                 }
+
+               switch (type)
+                 {
+#ifdef HAVE_LONG_LONG
+                 case TYPE_LONGLONGINT:
+                 case TYPE_ULONGLONGINT:
+                   *p++ = 'l';
+                   /*FALLTHROUGH*/
+#endif
+                 case TYPE_LONGINT:
+                 case TYPE_ULONGINT:
+#ifdef HAVE_WINT_T
+                 case TYPE_WIDE_CHAR:
+#endif
+#ifdef HAVE_WCHAR_T
+                 case TYPE_WIDE_STRING:
+#endif
+                   *p++ = 'l';
+                   break;
+#ifdef HAVE_LONG_DOUBLE
+                 case TYPE_LONGDOUBLE:
+                   *p++ = 'L';
+                   break;
+#endif
+                 default:
+                   break;
+                 }
+               *p = dp->conversion;
+#if USE_SNPRINTF
+               p[1] = '%';
+               p[2] = 'n';
+               p[3] = '\0';
+#else
+               p[1] = '\0';
+#endif
+
+               /* Construct the arguments for calling snprintf or sprintf.  */
+               prefix_count = 0;
+               if (dp->width_arg_index != ARG_NONE)
+                 {
+                   if (!(a.arg[dp->width_arg_index].type == TYPE_INT))
+                     abort ();
+                   prefixes[prefix_count++] = a.arg[dp->width_arg_index].a.a_int;
+                 }
+               if (dp->precision_arg_index != ARG_NONE)
+                 {
+                   if (!(a.arg[dp->precision_arg_index].type == TYPE_INT))
+                     abort ();
+                   prefixes[prefix_count++] = a.arg[dp->precision_arg_index].a.a_int;
+                 }
+
+#if USE_SNPRINTF
+               /* Prepare checking whether snprintf returns the count
+                  via %n.  */
+               ENSURE_ALLOCATION (1);
+               result[length] = '\0';
+#endif
+
+               for (;;)
+                 {
+                   size_t maxlen;
+                   int count;
+                   int retcount;
+
+                   maxlen = allocated - length;
+                   count = -1;
+                   retcount = 0;
+
+#if USE_SNPRINTF
+# define SNPRINTF_BUF(arg) \
+                   switch (prefix_count)                                   \
+                     {                                                     \
+                     case 0:                                               \
+                       retcount = SNPRINTF (result + length, maxlen, buf,  \
+                                            arg, &count);                  \
+                       break;                                              \
+                     case 1:                                               \
+                       retcount = SNPRINTF (result + length, maxlen, buf,  \
+                                            prefixes[0], arg, &count);     \
+                       break;                                              \
+                     case 2:                                               \
+                       retcount = SNPRINTF (result + length, maxlen, buf,  \
+                                            prefixes[0], prefixes[1], arg, \
+                                            &count);                       \
+                       break;                                              \
+                     default:                                              \
+                       abort ();                                           \
+                     }
+#else
+# define SNPRINTF_BUF(arg) \
+                   switch (prefix_count)                                   \
+                     {                                                     \
+                     case 0:                                               \
+                       count = sprintf (tmp, buf, arg);                    \
+                       break;                                              \
+                     case 1:                                               \
+                       count = sprintf (tmp, buf, prefixes[0], arg);       \
+                       break;                                              \
+                     case 2:                                               \
+                       count = sprintf (tmp, buf, prefixes[0], prefixes[1],\
+                                        arg);                              \
+                       break;                                              \
+                     default:                                              \
+                       abort ();                                           \
+                     }
+#endif
+
+                   switch (type)
+                     {
+                     case TYPE_SCHAR:
+                       {
+                         int arg = a.arg[dp->arg_index].a.a_schar;
+                         SNPRINTF_BUF (arg);
+                       }
+                       break;
+                     case TYPE_UCHAR:
+                       {
+                         unsigned int arg = a.arg[dp->arg_index].a.a_uchar;
+                         SNPRINTF_BUF (arg);
+                       }
+                       break;
+                     case TYPE_SHORT:
+                       {
+                         int arg = a.arg[dp->arg_index].a.a_short;
+                         SNPRINTF_BUF (arg);
+                       }
+                       break;
+                     case TYPE_USHORT:
+                       {
+                         unsigned int arg = a.arg[dp->arg_index].a.a_ushort;
+                         SNPRINTF_BUF (arg);
+                       }
+                       break;
+                     case TYPE_INT:
+                       {
+                         int arg = a.arg[dp->arg_index].a.a_int;
+                         SNPRINTF_BUF (arg);
+                       }
+                       break;
+                     case TYPE_UINT:
+                       {
+                         unsigned int arg = a.arg[dp->arg_index].a.a_uint;
+                         SNPRINTF_BUF (arg);
+                       }
+                       break;
+                     case TYPE_LONGINT:
+                       {
+                         long int arg = a.arg[dp->arg_index].a.a_longint;
+                         SNPRINTF_BUF (arg);
+                       }
+                       break;
+                     case TYPE_ULONGINT:
+                       {
+                         unsigned long int arg = a.arg[dp->arg_index].a.a_ulongint;
+                         SNPRINTF_BUF (arg);
+                       }
+                       break;
+#ifdef HAVE_LONG_LONG
+                     case TYPE_LONGLONGINT:
+                       {
+                         long long int arg = a.arg[dp->arg_index].a.a_longlongint;
+                         SNPRINTF_BUF (arg);
+                       }
+                       break;
+                     case TYPE_ULONGLONGINT:
+                       {
+                         unsigned long long int arg = a.arg[dp->arg_index].a.a_ulonglongint;
+                         SNPRINTF_BUF (arg);
+                       }
+                       break;
+#endif
+                     case TYPE_DOUBLE:
+                       {
+                         double arg = a.arg[dp->arg_index].a.a_double;
+                         SNPRINTF_BUF (arg);
+                       }
+                       break;
+#ifdef HAVE_LONG_DOUBLE
+                     case TYPE_LONGDOUBLE:
+                       {
+                         long double arg = a.arg[dp->arg_index].a.a_longdouble;
+                         SNPRINTF_BUF (arg);
+                       }
+                       break;
+#endif
+                     case TYPE_CHAR:
+                       {
+                         int arg = a.arg[dp->arg_index].a.a_char;
+                         SNPRINTF_BUF (arg);
+                       }
+                       break;
+#ifdef HAVE_WINT_T
+                     case TYPE_WIDE_CHAR:
+                       {
+                         wint_t arg = a.arg[dp->arg_index].a.a_wide_char;
+                         SNPRINTF_BUF (arg);
+                       }
+                       break;
+#endif
+                     case TYPE_STRING:
+                       {
+                         const char *arg = a.arg[dp->arg_index].a.a_string;
+                         SNPRINTF_BUF (arg);
+                       }
+                       break;
+#ifdef HAVE_WCHAR_T
+                     case TYPE_WIDE_STRING:
+                       {
+                         const wchar_t *arg = a.arg[dp->arg_index].a.a_wide_string;
+                         SNPRINTF_BUF (arg);
+                       }
+                       break;
+#endif
+                     case TYPE_POINTER:
+                       {
+                         void *arg = a.arg[dp->arg_index].a.a_pointer;
+                         SNPRINTF_BUF (arg);
+                       }
+                       break;
+                     default:
+                       abort ();
+                     }
+
+#if USE_SNPRINTF
+                   /* Portability: Not all implementations of snprintf()
+                      are ISO C 99 compliant.  Determine the number of
+                      bytes that snprintf() has produced or would have
+                      produced.  */
+                   if (count >= 0)
+                     {
+                       /* Verify that snprintf() has NUL-terminated its
+                          result.  */
+                       if (count < maxlen && result[length + count] != '\0')
+                         abort ();
+                       /* Portability hack.  */
+                       if (retcount > count)
+                         count = retcount;
+                     }
+                   else
+                     {
+                       /* snprintf() doesn't understand the '%n'
+                          directive.  */
+                       if (p[1] != '\0')
+                         {
+                           /* Don't use the '%n' directive; instead, look
+                              at the snprintf() return value.  */
+                           p[1] = '\0';
+                           continue;
+                         }
+                       else
+                         {
+                           /* Look at the snprintf() return value.  */
+                           if (retcount < 0)
+                             {
+                               /* HP-UX 10.20 snprintf() is doubly deficient:
+                                  It doesn't understand the '%n' directive,
+                                  *and* it returns -1 (rather than the length
+                                  that would have been required) when the
+                                  buffer is too small.  */
+                               size_t bigger_need =
+                                 (allocated > 12 ? allocated : 12);
+                               ENSURE_ALLOCATION (bigger_need);
+                               continue;
+                             }
+                           else
+                             count = retcount;
+                         }
+                     }
+#endif
+
+                   /* Attempt to handle failure.  */
+                   if (count < 0)
+                     {
+                       if (!(result == resultbuf || result == NULL))
+                         free (result);
+                       if (buf_malloced != NULL)
+                         free (buf_malloced);
+                       CLEANUP ();
+                       errno = EINVAL;
+                       return NULL;
+                     }
+
+#if !USE_SNPRINTF
+                   if (count >= tmp_length)
+                     /* tmp_length was incorrectly calculated - fix the
+                        code above!  */
+                     abort ();
+#endif
+
+                   /* Make room for the result.  */
+                   if (count >= maxlen)
+                     {
+                       /* Need at least count bytes.  But allocate
+                          proportionally, to avoid looping eternally if
+                          snprintf() reports a too small count.  */
+                       ENSURE_ALLOCATION (count < allocated
+                                          ? allocated : count);
+#if USE_SNPRINTF
+                       continue;
+#endif
+                     }
+
+#if USE_SNPRINTF
+                   /* The snprintf() result did fit.  */
+#else
+                   /* Append the sprintf() result.  */
+                   memcpy (result + length, tmp, count * sizeof (CHAR_T));
+                   if (tmp != tmpbuf)
+                     free (tmp);
+#endif
+
+                   length += count;
+                   break;
+                 }
+             }
+         }
+      }
+
+    /* Add the final NUL.  */
+    ENSURE_ALLOCATION (1);
+    result[length] = '\0';
+
+    if (result != resultbuf && length + 1 < allocated)
+      {
+       /* Shrink the allocated memory if possible.  */
+       CHAR_T *memory;
+
+       memory = (CHAR_T *) realloc (result, (length + 1) * sizeof (CHAR_T));
+       if (memory != NULL)
+         result = memory;
+      }
+
+    if (buf_malloced != NULL)
+      free (buf_malloced);
+    CLEANUP ();
+    *lengthp = length;
+    if (length > INT_MAX)
+      goto length_overflow;
+    return result;
+
+  length_overflow:
+    /* We could produce such a big string, but its length doesn't fit into
+       an 'int'.  POSIX says that snprintf() fails with errno = EOVERFLOW in
+       this case.  */
+    if (result != resultbuf)
+      free (result);
+    errno = EOVERFLOW;
+    return NULL;
+
+  out_of_memory:
+    if (!(result == resultbuf || result == NULL))
+      free (result);
+    if (buf_malloced != NULL)
+      free (buf_malloced);
+  out_of_memory_1:
+    CLEANUP ();
+    errno = ENOMEM;
+    return NULL;
+  }
+}
+
+#undef SNPRINTF
+#undef USE_SNPRINTF
+#undef PRINTF_PARSE
+#undef DIRECTIVES
+#undef DIRECTIVE
+#undef CHAR_T
+#undef VASNPRINTF
index 2c4c4a07f03833b0034b22e81ed05505f4dc0f22..e5af026a102d23f828e364271ba57f8f2b773baf 100644 (file)
@@ -1,7 +1,7 @@
 # Makefile for GNU tar sources.
 
-# Copyright (C) 1994, 1995, 1996, 1997, 1999, 2000, 2001, 2003 Free
-# Software Foundation, Inc.
+# Copyright (C) 1994, 1995, 1996, 1997, 1999, 2000, 2001, 2003, 2006
+# 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
@@ -42,8 +42,6 @@ tar_SOURCES = \
 
 INCLUDES = -I$(top_srcdir)/lib -I../ -I../lib
 
-tar.o: ../lib/localedir.h
-
 LDADD = ../lib/libtar.a $(LIBINTL) $(LIBICONV)
 
 tar_LDADD = $(LDADD) $(LIB_CLOCK_GETTIME)
index bd48d7be1f22cc8334d0764de5bb157b697cc741..68c8801b1dd07be662e6e16d5ab26058f832a406 100644 (file)
--- a/src/tar.c
+++ b/src/tar.c
 
 #include <argmatch.h>
 #include <closeout.h>
+#include <configmake.h>
 #include <exitfail.h>
 #include <getdate.h>
-#include <localedir.h>
 #include <rmt.h>
+#include <rmt-command.h>
 #include <prepargs.h>
 #include <quotearg.h>
 #include <version-etc.h>
@@ -980,7 +981,7 @@ read_name_from_file (FILE *fp, struct obstack *stk)
 
   if (counter == 0 && c != EOF)
     return file_list_skip;
-  
+
   obstack_1grow (stk, 0);
 
   return (counter == 0 && c == EOF) ? file_list_end : file_list_success;
@@ -1068,7 +1069,7 @@ update_argv (const char *filename, struct argp_state *state)
        case file_list_success:
          count++;
          break;
-         
+
        case file_list_end: /* won't happen, just to pacify gcc */
          break;
 
@@ -1093,7 +1094,7 @@ update_argv (const char *filename, struct argp_state *state)
            filename_terminator = 0;
            break;
          }
-         
+
        case file_list_skip:
          break;
        }
@@ -2346,7 +2347,7 @@ main (int argc, char **argv)
 
   if (stdlis == stdout)
     close_stdout ();
-  else if (ferror (stderr) || fclose (stderr) != 0) 
+  else if (ferror (stderr) || fclose (stderr) != 0)
     exit_status = TAREXIT_FAILURE;
 
   return exit_status;
This page took 0.079778 seconds and 4 git commands to generate.