summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog29
-rw-r--r--Makefile.am9
-rw-r--r--acconfig.h16
-rw-r--r--configure.in13
-rw-r--r--m4/Makefile.am11
-rw-r--r--m4/decl.m437
-rw-r--r--m4/inttypes_h.m422
-rw-r--r--m4/uintmax_t.m422
-rw-r--r--m4/ulonglong.m417
-rw-r--r--m4/xstrtoumax.m434
-rw-r--r--src/Makefile.am8
-rw-r--r--src/grep.c43
-rw-r--r--src/strtol.c472
-rw-r--r--src/strtoul.c22
-rw-r--r--src/strtoull.c27
-rw-r--r--src/strtoumax.c81
-rw-r--r--src/xstrtol.c282
-rw-r--r--src/xstrtol.h64
-rw-r--r--src/xstrtoumax.c31
19 files changed, 1200 insertions, 40 deletions
diff --git a/ChangeLog b/ChangeLog
index 9a66b4a1..9351a60a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,32 @@
+2000-03-26 Paul Eggert <eggert@twinsun.com>
+
+ * Makefile.am (ACINCLUDE_INPUTS): Add decl.m4, inttypes_h.m4,
+ uintmax_t.m4, ulonglong.m4, xstrtoumax.m4.
+ * m4/Makefile.am (EXTRA_DIST): Likewise.
+
+ * src/Makefile.am (base_sources):
+ Add xstrtol.c, xstrtol.h, xstrtoumax.c.
+ (EXTRA_DIST): Add strtol.c.
+
+ * configure.in (jm_AC_TYPE_UINTMAX_T, jm_AC_PREREQ_XSTRTOUMAX,
+ HAVE_DECL_STRTOUL, HAVE_DECL_STRTOULL): Add.
+ (AC_REPLACE_FUNCS): Add strtoul.
+
+ * src/grep.c: Include xstrtol.h.
+ (ck_atio): Use xstrtoumax and do proper overflow checking.
+ (max_count, outleft): Now off_t, not int.
+ (main): Likewise. Use xstrtoumax to convert max_count from string.
+
+ * acconfig.h (HAVE_DECL_STRTOUL, HAVE_DECL_STRTOULL): New #undefs.
+ (HAVE_STPCPY, ENABLE_NLS, HAVE_CATGETS, HAVE_GETTEXT,
+ HAVE_LC_MESSAGES): Remove.
+
+ * m4/decl.m4, m4/inttypes_h.m4, m4/uintmax_t.m4, m4/ulonglong.m4,
+ m4/xstrtoumax.m4, src/strtol.c, src/strtoul.c, src/strtoull.c,
+ src/strtoumax.c, src/xstrtol.c, src/xstrtol.h, src/xstrtoumax.c:
+ New files, taken unchanged from textutils, fileutils, sh-utils
+ and/or tar.
+
2000-03-23 Paul Eggert <eggert@twinsun.com>
* src/search.c (Pcompile): Add support for NUL bytes in
diff --git a/Makefile.am b/Makefile.am
index 76a8a408..64ac4439 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -10,11 +10,12 @@ EXTRA_DIST = TODO README PATCHES.AC PATCHES.AM
# The following hack works around this bug by creating acinclude.m4 manually.
ACLOCAL_AMFLAGS =
M4DIR = $(srcdir)/m4
-ACINCLUDE_INPUTS = $(M4DIR)/djgpp.m4 $(M4DIR)/dosfile.m4 \
+ACINCLUDE_INPUTS = $(M4DIR)/decl.m4 $(M4DIR)/djgpp.m4 $(M4DIR)/dosfile.m4 \
$(M4DIR)/envsep.m4 $(M4DIR)/gettext.m4 $(M4DIR)/glibc.m4 \
$(M4DIR)/header.m4 $(M4DIR)/init.m4 $(M4DIR)/install.m4 \
- $(M4DIR)/isc-posix.m4 $(M4DIR)/largefile.m4 $(M4DIR)/lcmessage.m4 \
- $(M4DIR)/missing.m4 $(M4DIR)/progtest.m4 $(M4DIR)/regex.m4 \
- $(M4DIR)/sanity.m4
+ $(M4DIR)/inttypes_h.m4 $(M4DIR)/isc-posix.m4 $(M4DIR)/largefile.m4 \
+ $(M4DIR)/lcmessage.m4 $(M4DIR)/missing.m4 $(M4DIR)/progtest.m4 \
+ $(M4DIR)/regex.m4 $(M4DIR)/sanity.m4 $(M4DIR)/uintmax_t.m4 \
+ $(M4DIR)/ulonglong.m4 $(M4DIR)/xstrtoumax.m4
$(srcdir)/acinclude.m4 : $(ACINCLUDE_INPUTS)
cat $(ACINCLUDE_INPUTS) >$(srcdir)/acinclude.m4
diff --git a/acconfig.h b/acconfig.h
index 8eb82dc6..dd5786c8 100644
--- a/acconfig.h
+++ b/acconfig.h
@@ -13,19 +13,11 @@
/* Hack for Visual C++ suggested by irox. */
#undef alloca
-/*
- * Internationalization stuffs.
- */
-
-#undef HAVE_STPCPY
-
-#undef ENABLE_NLS
-
-#undef HAVE_CATGETS
-
-#undef HAVE_GETTEXT
+/* Define if <stdlib.h> declares strtoul. */
+#undef HAVE_DECL_STRTOUL
-#undef HAVE_LC_MESSAGES
+/* Define if <stdlib.h> declares strtoull. */
+#undef HAVE_DECL_STRTOULL
/*
* DOS specific
diff --git a/configure.in b/configure.in
index a0a524ae..d9cf5374 100644
--- a/configure.in
+++ b/configure.in
@@ -24,6 +24,7 @@ AM_C_PROTOTYPES
AC_TYPE_SIZE_T
AC_CHECK_TYPE(ssize_t, int)
AC_C_CONST
+jm_AC_TYPE_UINTMAX_T
dnl Checks for header files.
AC_HEADER_STDC
@@ -38,7 +39,17 @@ AC_FUNC_CLOSEDIR_VOID
AC_FUNC_MMAP
dnl getpagesize is checked for by AC_FUNC_MMAP.
AC_CHECK_FUNCS(btowc isascii memmove setmode strerror wctype)
-AC_REPLACE_FUNCS(memchr stpcpy)
+AC_REPLACE_FUNCS(memchr stpcpy strtoul)
+jm_AC_PREREQ_XSTRTOUMAX
+
+dnl Replace this with jm_CHECK_DECLS once autoconf 2.15 is out.
+jm_CHECK_DECLARATIONS([#include <stdlib.h>], strtoul strtoull)
+test $jm_cv_func_decl_strtoul != yes
+AC_DEFINE_UNQUOTED(HAVE_DECL_STRTOUL, $?,
+ [Define if <stdlib.h> declares strtoul.])
+test $jm_cv_func_decl_strtoull != yes
+AC_DEFINE_UNQUOTED(HAVE_DECL_STRTOULL, $?,
+ [Define if <stdlib.h> declares strtoull.])
dnl for VC++
case "$ac_cv_prog_CC" in
diff --git a/m4/Makefile.am b/m4/Makefile.am
index 3be5753c..21cd7d19 100644
--- a/m4/Makefile.am
+++ b/m4/Makefile.am
@@ -1,7 +1,8 @@
## Process this file with automake to create Makefile.in
AUTOMAKE_OPTIONS = no-dependencies
-EXTRA_DIST = djgpp.m4 \
+EXTRA_DIST = decl.m4 \
+ djgpp.m4 \
dosfile.m4 \
envsep.m4 \
gettext.m4 \
@@ -9,10 +10,14 @@ EXTRA_DIST = djgpp.m4 \
header.m4 \
init.m4 \
install.m4 \
+ inttypes_h.m4 \
isc-posix.m4 \
- lcmessage.m4 \
largefile.m4 \
+ lcmessage.m4 \
missing.m4 \
progtest.m4 \
regex.m4 \
- sanity.m4
+ sanity.m4 \
+ uintmax_t.m4 \
+ ulonglong.m4 \
+ xstrtoumax.m4
diff --git a/m4/decl.m4 b/m4/decl.m4
new file mode 100644
index 00000000..4dd7e0d6
--- /dev/null
+++ b/m4/decl.m4
@@ -0,0 +1,37 @@
+#serial 5
+
+AC_DEFUN(jm_CHECK_DECLARATION,
+[
+ AC_MSG_CHECKING([whether $1 is declared])
+ AC_CACHE_VAL(jm_cv_func_decl_$1,
+ [AC_TRY_COMPILE([$2],
+ [
+#ifndef $1
+char *(*pfn) = (char *(*)) $1
+#endif
+ ],
+ eval "jm_cv_func_decl_$1=yes",
+ eval "jm_cv_func_decl_$1=no")])
+
+ if eval "test \"`echo '$jm_cv_func_decl_'$1`\" = yes"; then
+ AC_MSG_RESULT(yes)
+ ifelse([$3], , :, [$3])
+ else
+ AC_MSG_RESULT(no)
+ ifelse([$4], , , [$4
+])dnl
+ fi
+])dnl
+
+dnl jm_CHECK_DECLARATIONS(INCLUDES, FUNCTION... [, ACTION-IF-DECLARED
+dnl [, ACTION-IF-NOT-DECLARED]])
+AC_DEFUN(jm_CHECK_DECLARATIONS,
+[
+ for jm_func in $2
+ do
+ jm_CHECK_DECLARATION($jm_func, [$1],
+ [
+ jm_tr_func=HAVE_DECL_`echo $jm_func | tr abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ`
+ AC_DEFINE_UNQUOTED($jm_tr_func) $3], [$4])dnl
+ done
+])
diff --git a/m4/inttypes_h.m4 b/m4/inttypes_h.m4
new file mode 100644
index 00000000..750639d6
--- /dev/null
+++ b/m4/inttypes_h.m4
@@ -0,0 +1,22 @@
+#serial 3
+
+dnl From Paul Eggert.
+
+# Define HAVE_INTTYPES_H if <inttypes.h> exists,
+# doesn't clash with <sys/types.h>, and declares uintmax_t.
+
+AC_DEFUN(jm_AC_HEADER_INTTYPES_H,
+[
+ AC_CACHE_CHECK([for inttypes.h], jm_ac_cv_header_inttypes_h,
+ [AC_TRY_COMPILE(
+ [#include <sys/types.h>
+#include <inttypes.h>],
+ [uintmax_t i = (uintmax_t) -1;],
+ jm_ac_cv_header_inttypes_h=yes,
+ jm_ac_cv_header_inttypes_h=no)])
+ if test $jm_ac_cv_header_inttypes_h = yes; then
+ AC_DEFINE_UNQUOTED(HAVE_INTTYPES_H, 1,
+[Define if <inttypes.h> exists, doesn't clash with <sys/types.h>,
+ and declares uintmax_t. ])
+ fi
+])
diff --git a/m4/uintmax_t.m4 b/m4/uintmax_t.m4
new file mode 100644
index 00000000..222beffa
--- /dev/null
+++ b/m4/uintmax_t.m4
@@ -0,0 +1,22 @@
+#serial 5
+
+dnl From Paul Eggert.
+
+AC_PREREQ(2.13)
+
+# Define uintmax_t to `unsigned long' or `unsigned long long'
+# if <inttypes.h> does not exist.
+
+AC_DEFUN(jm_AC_TYPE_UINTMAX_T,
+[
+ AC_REQUIRE([jm_AC_HEADER_INTTYPES_H])
+ if test $jm_ac_cv_header_inttypes_h = no; then
+ AC_REQUIRE([jm_AC_TYPE_UNSIGNED_LONG_LONG])
+ test $ac_cv_type_unsigned_long_long = yes \
+ && ac_type='unsigned long long' \
+ || ac_type='unsigned long'
+ AC_DEFINE_UNQUOTED(uintmax_t, $ac_type,
+[ Define to unsigned long or unsigned long long
+ if <inttypes.h> doesn't define.])
+ fi
+])
diff --git a/m4/ulonglong.m4 b/m4/ulonglong.m4
new file mode 100644
index 00000000..e2fbb552
--- /dev/null
+++ b/m4/ulonglong.m4
@@ -0,0 +1,17 @@
+#serial 2
+
+dnl From Paul Eggert.
+
+AC_DEFUN(jm_AC_TYPE_UNSIGNED_LONG_LONG,
+[
+ AC_CACHE_CHECK([for unsigned long long], ac_cv_type_unsigned_long_long,
+ [AC_TRY_LINK([unsigned long long ull = 1; int i = 63;],
+ [unsigned long long ullmax = (unsigned long long) -1;
+ return ull << i | ull >> i | ullmax / ull | ullmax % ull;],
+ ac_cv_type_unsigned_long_long=yes,
+ ac_cv_type_unsigned_long_long=no)])
+ if test $ac_cv_type_unsigned_long_long = yes; then
+ AC_DEFINE(HAVE_UNSIGNED_LONG_LONG, 1,
+ [Define if you have the unsigned long long type.])
+ fi
+])
diff --git a/m4/xstrtoumax.m4 b/m4/xstrtoumax.m4
new file mode 100644
index 00000000..f6e31996
--- /dev/null
+++ b/m4/xstrtoumax.m4
@@ -0,0 +1,34 @@
+#serial 2
+
+# autoconf tests required for use of xstrtoumax.c
+
+AC_DEFUN(jm_AC_PREREQ_XSTRTOUMAX,
+[
+ AC_REQUIRE([jm_AC_HEADER_INTTYPES_H])
+ AC_REQUIRE([jm_AC_TYPE_UNSIGNED_LONG_LONG])
+ AC_CHECK_HEADERS(stdlib.h)
+
+ AC_CACHE_CHECK([whether <inttypes.h> defines strtoumax as a macro],
+ jm_cv_func_strtoumax_macro,
+ AC_EGREP_CPP([inttypes_h_defines_strtoumax], [#include <inttypes.h>
+#ifdef strtoumax
+ inttypes_h_defines_strtoumax
+#endif],
+ jm_cv_func_strtoumax_macro=yes,
+ jm_cv_func_strtoumax_macro=no))
+
+ if test "$jm_cv_func_strtoumax_macro" != yes; then
+ AC_REPLACE_FUNCS(strtoumax)
+ fi
+
+ dnl We don't need (and can't compile) the replacement strtoull
+ dnl unless the type `unsigned long long' exists.
+ dnl Also, only the replacement strtoumax invokes strtoull,
+ dnl so we need the replacement strtoull only if strtoumax does not exist.
+ case "$ac_cv_type_unsigned_long_long,$jm_cv_func_strtoumax_macro,$ac_cv_func_strtoumax" in
+ yes,no,no)
+ AC_REPLACE_FUNCS(strtoull)
+ ;;
+ esac
+
+])
diff --git a/src/Makefile.am b/src/Makefile.am
index f2ecdc01..0b43d4d7 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -5,15 +5,15 @@ SUBDIRS = posix
LN = ln
-# We let configure figure out if we need the regex.c or not
-# it is provided in GNU/Linux system
-# regex.c regex.h
+# We let configure figure out whether we need
+# regex.c, strtoul.c, strtoull.c, and strtoumax.c.
bin_PROGRAMS = grep egrep fgrep
base_sources = grep.c grep.h \
dfa.c dfa.h \
kwset.c kwset.h \
obstack.c obstack.h \
savedir.c savedir.h \
+ xstrtol.c xstrtol.h xstrtoumax.c \
getopt.c getopt1.c getopt.h \
search.c getpagesize.h system.h
egrep_SOURCES = $(base_sources) egrepmat.c
@@ -28,4 +28,4 @@ INCLUDES = -I../intl -DLOCALEDIR=\"$(localedir)\"
EXTRA_DIST = \
dosbuf.c \
vms_fab.c vms_fab.h \
- regex.h
+ regex.h strtol.c
diff --git a/src/grep.c b/src/grep.c
index 3816f2c4..4ba826a0 100644
--- a/src/grep.c
+++ b/src/grep.c
@@ -36,6 +36,7 @@
#include "getpagesize.h"
#include "grep.h"
#include "savedir.h"
+#include "xstrtol.h"
#undef MAX
#define MAX(A,B) ((A) > (B) ? (A) : (B))
@@ -204,17 +205,14 @@ xrealloc (char *ptr, size_t size)
}
/* Convert STR to a positive integer, storing the result in *OUT.
- If STR is not a valid integer, return -1 (otherwise 0). */
+ Return nonzero if STR is invalid or out of range. */
static int
ck_atoi (char const *str, int *out)
{
- char const *p;
- for (p = str; *p; p++)
- if (*p < '0' || *p > '9')
- return -1;
-
- *out = atoi (optarg);
- return 0;
+ uintmax_t value;
+ return ! (xstrtoumax (str, 0, 10, &value, "") == LONGINT_OK
+ && 0 <= (*out = value)
+ && *out == value);
}
@@ -492,9 +490,8 @@ static int count_matches; /* Count matching lines. */
static int list_files; /* List matching files. */
static int no_filenames; /* Suppress file names. */
static int suppress_errors; /* Suppress diagnostics. */
-static int max_count; /* Stop after outputting this many
- lines from an input file.
- FIXME: should be off_t. */
+static off_t max_count; /* Stop after outputting this many
+ lines from an input file. */
/* Internal variables to keep track of byte count, context, etc. */
static off_t totalcc; /* Total character count before bufbeg. */
@@ -503,8 +500,7 @@ static char *lastout; /* Pointer after last character output;
NULL if no character has been output
or if it's conceptually before bufbeg. */
static off_t totalnl; /* Total newline count before lastnl. */
-static int outleft; /* Maximum number of lines to be output.
- FIXME: should be off_t. */
+static off_t outleft; /* Maximum number of lines to be output. */
static int pending; /* Pending lines of output.
Always kept 0 if out_quiet is true. */
static int done_on_match; /* Stop scanning file on first match */
@@ -1226,7 +1222,7 @@ main (int argc, char **argv)
eolbyte = '\n';
filename_mask = ~0;
- max_count = INT_MAX;
+ max_count = TYPE_MAXIMUM (off_t);
/* The value -1 means to use DEFAULT_CONTEXT. */
out_after = out_before = -1;
/* Default before/after context: chaged by -C/-NUM options */
@@ -1390,8 +1386,23 @@ main (int argc, char **argv)
done_on_match = 1;
break;
case 'm':
- if (ck_atoi (optarg, &max_count))
- fatal (_("invalid max count"), 0);
+ {
+ uintmax_t value;
+ switch (xstrtoumax (optarg, 0, 10, &value, ""))
+ {
+ case LONGINT_OK:
+ max_count = value;
+ if (0 <= max_count && max_count == value)
+ break;
+ /* Fall through. */
+ case LONGINT_OVERFLOW:
+ max_count = TYPE_MAXIMUM (off_t);
+ break;
+
+ default:
+ fatal (_("invalid max count"), 0);
+ }
+ }
break;
case 'n':
out_line = 1;
diff --git a/src/strtol.c b/src/strtol.c
new file mode 100644
index 00000000..0c9c2767
--- /dev/null
+++ b/src/strtol.c
@@ -0,0 +1,472 @@
+/* Convert string representation of a number into an integer value.
+ Copyright (C) 1991, 92, 94, 95, 96, 97, 98, 99 Free Software Foundation, Inc.
+ NOTE: The canonical source of this file is maintained with the GNU C
+ Library. Bugs can be reported to bug-glibc@gnu.org.
+
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#ifdef _LIBC
+# define USE_NUMBER_GROUPING
+# define STDC_HEADERS
+# define HAVE_LIMITS_H
+#endif
+
+#include <ctype.h>
+#include <errno.h>
+#ifndef errno
+extern int errno;
+#endif
+#ifndef __set_errno
+# define __set_errno(Val) errno = (Val)
+#endif
+
+#ifdef HAVE_LIMITS_H
+# include <limits.h>
+#endif
+
+#ifdef STDC_HEADERS
+# include <stddef.h>
+# include <stdlib.h>
+# include <string.h>
+#else
+# ifndef NULL
+# define NULL 0
+# endif
+#endif
+
+#ifdef USE_NUMBER_GROUPING
+# include "../locale/localeinfo.h"
+#endif
+
+/* Nonzero if we are defining `strtoul' or `strtoull', operating on
+ unsigned integers. */
+#ifndef UNSIGNED
+# define UNSIGNED 0
+# define INT LONG int
+#else
+# define INT unsigned LONG int
+#endif
+
+/* Determine the name. */
+#ifdef USE_IN_EXTENDED_LOCALE_MODEL
+# if UNSIGNED
+# ifdef USE_WIDE_CHAR
+# ifdef QUAD
+# define strtol __wcstoull_l
+# else
+# define strtol __wcstoul_l
+# endif
+# else
+# ifdef QUAD
+# define strtol __strtoull_l
+# else
+# define strtol __strtoul_l
+# endif
+# endif
+# else
+# ifdef USE_WIDE_CHAR
+# ifdef QUAD
+# define strtol __wcstoll_l
+# else
+# define strtol __wcstol_l
+# endif
+# else
+# ifdef QUAD
+# define strtol __strtoll_l
+# else
+# define strtol __strtol_l
+# endif
+# endif
+# endif
+#else
+# if UNSIGNED
+# ifdef USE_WIDE_CHAR
+# ifdef QUAD
+# define strtol wcstoull
+# else
+# define strtol wcstoul
+# endif
+# else
+# ifdef QUAD
+# define strtol strtoull
+# else
+# define strtol strtoul
+# endif
+# endif
+# else
+# ifdef USE_WIDE_CHAR
+# ifdef QUAD
+# define strtol wcstoll
+# else
+# define strtol wcstol
+# endif
+# else
+# ifdef QUAD
+# define strtol strtoll
+# endif
+# endif
+# endif
+#endif
+
+/* If QUAD is defined, we are defining `strtoll' or `strtoull',
+ operating on `long long int's. */
+#ifdef QUAD
+# define LONG long long
+# define STRTOL_LONG_MIN LONG_LONG_MIN
+# define STRTOL_LONG_MAX LONG_LONG_MAX
+# define STRTOL_ULONG_MAX ULONG_LONG_MAX
+
+/* The extra casts work around common compiler bugs,
+ e.g. Cray C 5.0.3.0 when t == time_t. */
+# ifndef TYPE_SIGNED
+# define TYPE_SIGNED(t) (! ((t) 0 < (t) -1))
+# endif
+# ifndef TYPE_MINIMUM
+# define TYPE_MINIMUM(t) ((t) (TYPE_SIGNED (t) \
+ ? ~ (t) 0 << (sizeof (t) * CHAR_BIT - 1) \
+ : (t) 0))
+# endif
+# ifndef TYPE_MAXIMUM
+# define TYPE_MAXIMUM(t) ((t) (~ (t) 0 - TYPE_MINIMUM (t)))
+# endif
+
+# ifndef ULONG_LONG_MAX
+# define ULONG_LONG_MAX TYPE_MAXIMUM (unsigned long long)
+# endif
+# ifndef LONG_LONG_MAX
+# define LONG_LONG_MAX TYPE_MAXIMUM (long long int)
+# endif
+# ifndef LONG_LONG_MIN
+# define LONG_LONG_MIN TYPE_MINIMUM (long long int)
+# endif
+
+# if __GNUC__ == 2 && __GNUC_MINOR__ < 7
+ /* Work around gcc bug with using this constant. */
+ static const unsigned long long int maxquad = ULONG_LONG_MAX;
+# undef STRTOL_ULONG_MAX
+# define STRTOL_ULONG_MAX maxquad
+# endif
+#else
+# define LONG long
+
+# ifndef ULONG_MAX
+# define ULONG_MAX ((unsigned long) ~(unsigned long) 0)
+# endif
+# ifndef LONG_MAX
+# define LONG_MAX ((long int) (ULONG_MAX >> 1))
+# endif
+# define STRTOL_LONG_MIN LONG_MIN
+# define STRTOL_LONG_MAX LONG_MAX
+# define STRTOL_ULONG_MAX ULONG_MAX
+#endif
+
+
+/* We use this code also for the extended locale handling where the
+ function gets as an additional argument the locale which has to be
+ used. To access the values we have to redefine the _NL_CURRENT
+ macro. */
+#ifdef USE_IN_EXTENDED_LOCALE_MODEL
+# undef _NL_CURRENT
+# define _NL_CURRENT(category, item) \
+ (current->values[_NL_ITEM_INDEX (item)].string)
+# define LOCALE_PARAM , loc
+# define LOCALE_PARAM_DECL __locale_t loc;
+#else
+# define LOCALE_PARAM
+# define LOCALE_PARAM_DECL
+#endif
+
+#if defined _LIBC || defined HAVE_WCHAR_H
+# include <wchar.h>
+#endif
+
+#ifdef USE_WIDE_CHAR
+# include <wctype.h>
+# define L_(Ch) L##Ch
+# define UCHAR_TYPE wint_t
+# define STRING_TYPE wchar_t
+# ifdef USE_IN_EXTENDED_LOCALE_MODEL
+# define ISSPACE(Ch) __iswspace_l ((Ch), loc)
+# define ISALPHA(Ch) __iswalpha_l ((Ch), loc)
+# define TOUPPER(Ch) __towupper_l ((Ch), loc)
+# else
+# define ISSPACE(Ch) iswspace (Ch)
+# define ISALPHA(Ch) iswalpha (Ch)
+# define TOUPPER(Ch) towupper (Ch)
+# endif
+#else
+# if defined STDC_HEADERS || (!defined isascii && !defined HAVE_ISASCII)
+# define IN_CTYPE_DOMAIN(c) 1
+# else
+# define IN_CTYPE_DOMAIN(c) isascii(c)
+# endif
+# define L_(Ch) Ch
+# define UCHAR_TYPE unsigned char
+# define STRING_TYPE char
+# ifdef USE_IN_EXTENDED_LOCALE_MODEL
+# define ISSPACE(Ch) __isspace_l ((Ch), loc)
+# define ISALPHA(Ch) __isalpha_l ((Ch), loc)
+# define TOUPPER(Ch) __toupper_l ((Ch), loc)
+# else
+# define ISSPACE(Ch) (IN_CTYPE_DOMAIN (Ch) && isspace (Ch))
+# define ISALPHA(Ch) (IN_CTYPE_DOMAIN (Ch) && isalpha (Ch))
+# define TOUPPER(Ch) (IN_CTYPE_DOMAIN (Ch) ? toupper (Ch) : (Ch))
+# endif
+#endif
+
+/* For compilers which are ansi but don't define __STDC__, like SGI
+ Irix-4.0.5 cc, also check whether PROTOTYPES is defined. */
+#if defined (__STDC__) || defined (PROTOTYPES)
+# define INTERNAL(X) INTERNAL1(X)
+# define INTERNAL1(X) __##X##_internal
+# define WEAKNAME(X) WEAKNAME1(X)
+#else
+# define INTERNAL(X) __/**/X/**/_internal
+#endif
+
+#ifdef USE_NUMBER_GROUPING
+/* This file defines a function to check for correct grouping. */
+# include "grouping.h"
+#endif
+
+
+
+/* Convert NPTR to an `unsigned long int' or `long int' in base BASE.
+ If BASE is 0 the base is determined by the presence of a leading
+ zero, indicating octal or a leading "0x" or "0X", indicating hexadecimal.
+ If BASE is < 2 or > 36, it is reset to 10.
+ If ENDPTR is not NULL, a pointer to the character after the last
+ one converted is stored in *ENDPTR. */
+
+INT
+INTERNAL (strtol) (nptr, endptr, base, group LOCALE_PARAM)
+ const STRING_TYPE *nptr;
+ STRING_TYPE **endptr;
+ int base;
+ int group;
+ LOCALE_PARAM_DECL
+{
+ int negative;
+ register unsigned LONG int cutoff;
+ register unsigned int cutlim;
+ register unsigned LONG int i;
+ register const STRING_TYPE *s;
+ register UCHAR_TYPE c;
+ const STRING_TYPE *save, *end;
+ int overflow;
+
+#ifdef USE_NUMBER_GROUPING
+# ifdef USE_IN_EXTENDED_LOCALE_MODEL
+ struct locale_data *current = loc->__locales[LC_NUMERIC];
+# endif
+ /* The thousands character of the current locale. */
+ wchar_t thousands = L'\0';
+ /* The numeric grouping specification of the current locale,
+ in the format described in <locale.h>. */
+ const char *grouping;
+
+ if (group)
+ {
+ grouping = _NL_CURRENT (LC_NUMERIC, GROUPING);
+ if (*grouping <= 0 || *grouping == CHAR_MAX)
+ grouping = NULL;
+ else
+ {
+ /* Figure out the thousands separator character. */
+# if defined _LIBC || defined _HAVE_BTOWC
+ thousands = __btowc (*_NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP));
+ if (thousands == WEOF)
+ thousands = L'\0';
+# endif
+ if (thousands == L'\0')
+ grouping = NULL;
+ }
+ }
+ else
+ grouping = NULL;
+#endif
+
+ if (base < 0 || base == 1 || base > 36)
+ {
+ __set_errno (EINVAL);
+ return 0;
+ }
+
+ save = s = nptr;
+
+ /* Skip white space. */
+ while (ISSPACE (*s))
+ ++s;
+ if (*s == L_('\0'))
+ goto noconv;
+
+ /* Check for a sign. */
+ if (*s == L_('-'))
+ {
+ negative = 1;
+ ++s;
+ }
+ else if (*s == L_('+'))
+ {
+ negative = 0;
+ ++s;
+ }
+ else
+ negative = 0;
+
+ /* Recognize number prefix and if BASE is zero, figure it out ourselves. */
+ if (*s == L_('0'))
+ {
+ if ((base == 0 || base == 16) && TOUPPER (s[1]) == L_('X'))
+ {
+ s += 2;
+ base = 16;
+ }
+ else if (base == 0)
+ base = 8;
+ }
+ else if (base == 0)
+ base = 10;
+
+ /* Save the pointer so we can check later if anything happened. */
+ save = s;
+
+#ifdef USE_NUMBER_GROUPING
+ if (group)
+ {
+ /* Find the end of the digit string and check its grouping. */
+ end = s;
+ for (c = *end; c != L_('\0'); c = *++end)
+ if ((wchar_t) c != thousands
+ && ((wchar_t) c < L_('0') || (wchar_t) c > L_('9'))
+ && (!ISALPHA (c) || (int) (TOUPPER (c) - L_('A') + 10) >= base))
+ break;
+ if (*s == thousands)
+ end = s;
+ else
+ end = correctly_grouped_prefix (s, end, thousands, grouping);
+ }
+ else
+#endif
+ end = NULL;
+
+ cutoff = STRTOL_ULONG_MAX / (unsigned LONG int) base;
+ cutlim = STRTOL_ULONG_MAX % (unsigned LONG int) base;
+
+ overflow = 0;
+ i = 0;
+ for (c = *s; c != L_('\0'); c = *++s)
+ {
+ if (s == end)
+ break;
+ if (c >= L_('0') && c <= L_('9'))
+ c -= L_('0');
+ else if (ISALPHA (c))
+ c = TOUPPER (c) - L_('A') + 10;
+ else
+ break;
+ if ((int) c >= base)
+ break;
+ /* Check for overflow. */
+ if (i > cutoff || (i == cutoff && c > cutlim))
+ overflow = 1;
+ else
+ {
+ i *= (unsigned LONG int) base;
+ i += c;
+ }
+ }
+
+ /* Check if anything actually happened. */
+ if (s == save)
+ goto noconv;
+
+ /* Store in ENDPTR the address of one character
+ past the last character we converted. */
+ if (endptr != NULL)
+ *endptr = (STRING_TYPE *) s;
+
+#if !UNSIGNED
+ /* Check for a value that is within the range of
+ `unsigned LONG int', but outside the range of `LONG int'. */
+ if (overflow == 0
+ && i > (negative
+ ? -((unsigned LONG int) (STRTOL_LONG_MIN + 1)) + 1
+ : (unsigned LONG int) STRTOL_LONG_MAX))
+ overflow = 1;
+#endif
+
+ if (overflow)
+ {
+ __set_errno (ERANGE);
+#if UNSIGNED
+ return STRTOL_ULONG_MAX;
+#else
+ return negative ? STRTOL_LONG_MIN : STRTOL_LONG_MAX;
+#endif
+ }
+
+ /* Return the result of the appropriate sign. */
+ return negative ? -i : i;
+
+noconv:
+ /* We must handle a special case here: the base is 0 or 16 and the
+ first two characters are '0' and 'x', but the rest are no
+ hexadecimal digits. This is no error case. We return 0 and
+ ENDPTR points to the `x`. */
+ if (endptr != NULL)
+ {
+ if (save - nptr >= 2 && TOUPPER (save[-1]) == L_('X')
+ && save[-2] == L_('0'))
+ *endptr = (STRING_TYPE *) &save[-1];
+ else
+ /* There was no number to convert. */
+ *endptr = (STRING_TYPE *) nptr;
+ }
+
+ return 0L;
+}
+
+/* External user entry point. */
+
+#if _LIBC - 0 == 0
+# undef PARAMS
+# if defined (__STDC__) && __STDC__
+# define PARAMS(Args) Args
+# else
+# define PARAMS(Args) ()
+# endif
+
+/* Prototype. */
+INT strtol PARAMS ((const STRING_TYPE *nptr, STRING_TYPE **endptr, int base));
+#endif
+
+
+INT
+#ifdef weak_function
+weak_function
+#endif
+strtol (nptr, endptr, base LOCALE_PARAM)
+ const STRING_TYPE *nptr;
+ STRING_TYPE **endptr;
+ int base;
+ LOCALE_PARAM_DECL
+{
+ return INTERNAL (strtol) (nptr, endptr, base, 0 LOCALE_PARAM);
+}
diff --git a/src/strtoul.c b/src/strtoul.c
new file mode 100644
index 00000000..298ae9ea
--- /dev/null
+++ b/src/strtoul.c
@@ -0,0 +1,22 @@
+/* Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+
+NOTE: The canonical source of this file is maintained with the GNU C Library.
+Bugs can be reported to bug-glibc@prep.ai.mit.edu.
+
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define UNSIGNED 1
+
+#include <strtol.c>
diff --git a/src/strtoull.c b/src/strtoull.c
new file mode 100644
index 00000000..d6aa1f80
--- /dev/null
+++ b/src/strtoull.c
@@ -0,0 +1,27 @@
+/* Function to parse an `unsigned long long int' from text.
+ Copyright (C) 1995, 1996, 1997, 1999 Free Software Foundation, Inc.
+ NOTE: The canonical source of this file is maintained with the GNU C
+ Library. Bugs can be reported to bug-glibc@gnu.org.
+
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define QUAD 1
+
+#include "strtoul.c"
+
+#ifdef _LIBC
+strong_alias (__strtoull_internal, __strtouq_internal)
+weak_alias (strtoull, strtouq)
+#endif
diff --git a/src/strtoumax.c b/src/strtoumax.c
new file mode 100644
index 00000000..a147604a
--- /dev/null
+++ b/src/strtoumax.c
@@ -0,0 +1,81 @@
+/* Convert string representation of a number into an uintmax_t value.
+ Copyright 1999 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Written by Paul Eggert. */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#if HAVE_INTTYPES_H
+# include <inttypes.h>
+#endif
+
+#if HAVE_STDLIB_H
+# include <stdlib.h>
+#endif
+
+#ifndef PARAMS
+# if defined PROTOTYPES || defined __STDC__
+# define PARAMS(Args) Args
+# else
+# define PARAMS(Args) ()
+# endif
+#endif
+
+#ifndef HAVE_DECL_STRTOUL
+"this configure-time declaration test was not run"
+#endif
+#if !HAVE_DECL_STRTOUL
+unsigned long strtoul PARAMS ((char const *, char **, int));
+#endif
+
+#ifndef HAVE_DECL_STRTOULL
+"this configure-time declaration test was not run"
+#endif
+#if !HAVE_DECL_STRTOULL && HAVE_UNSIGNED_LONG_LONG
+unsigned long long strtoull PARAMS ((char const *, char **, int));
+#endif
+
+uintmax_t
+strtoumax (char const *ptr, char **endptr, int base)
+{
+#define USE_IF_EQUIVALENT(function) \
+ if (sizeof (uintmax_t) == sizeof function (ptr, endptr, base)) \
+ return function (ptr, endptr, base);
+
+#if HAVE_UNSIGNED_LONG_LONG
+ USE_IF_EQUIVALENT (strtoull)
+#endif
+
+ USE_IF_EQUIVALENT (strtoul)
+
+ abort ();
+}
+
+#ifdef TESTING
+# include <stdio.h>
+int
+main ()
+{
+ char *p, *endptr;
+ printf ("sizeof uintmax_t: %d\n", sizeof (uintmax_t));
+ printf ("sizeof strtoull(): %d\n", sizeof strtoull(p, &endptr, 10));
+ printf ("sizeof strtoul(): %d\n", sizeof strtoul(p, &endptr, 10));
+ exit (0);
+}
+#endif
diff --git a/src/xstrtol.c b/src/xstrtol.c
new file mode 100644
index 00000000..07023d9f
--- /dev/null
+++ b/src/xstrtol.c
@@ -0,0 +1,282 @@
+/* A more useful interface to strtol.
+ Copyright (C) 1995, 1996, 1998-2000 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Written by Jim Meyering. */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#ifndef __strtol
+# define __strtol strtol
+# define __strtol_t long int
+# define __xstrtol xstrtol
+#endif
+
+/* Some pre-ANSI implementations (e.g. SunOS 4)
+ need stderr defined if assertion checking is enabled. */
+#include <stdio.h>
+
+#if STDC_HEADERS
+# include <stdlib.h>
+#endif
+
+#if HAVE_STRING_H
+# include <string.h>
+#else
+# include <strings.h>
+# ifndef strchr
+# define strchr index
+# endif
+#endif
+
+#include <assert.h>
+#include <ctype.h>
+
+#include <errno.h>
+#ifndef errno
+extern int errno;
+#endif
+
+#if HAVE_LIMITS_H
+# include <limits.h>
+#endif
+
+#ifndef CHAR_BIT
+# define CHAR_BIT 8
+#endif
+
+/* The extra casts work around common compiler bugs. */
+#define TYPE_SIGNED(t) (! ((t) 0 < (t) -1))
+/* The outer cast is needed to work around a bug in Cray C 5.0.3.0.
+ It is necessary at least when t == time_t. */
+#define TYPE_MINIMUM(t) ((t) (TYPE_SIGNED (t) \
+ ? ~ (t) 0 << (sizeof (t) * CHAR_BIT - 1) : (t) 0))
+#define TYPE_MAXIMUM(t) (~ (t) 0 - TYPE_MINIMUM (t))
+
+#if defined (STDC_HEADERS) || (!defined (isascii) && !defined (HAVE_ISASCII))
+# define IN_CTYPE_DOMAIN(c) 1
+#else
+# define IN_CTYPE_DOMAIN(c) isascii(c)
+#endif
+
+#define ISSPACE(c) (IN_CTYPE_DOMAIN (c) && isspace (c))
+
+#include "xstrtol.h"
+
+#ifndef strtol
+long int strtol ();
+#endif
+
+#ifndef strtoul
+unsigned long int strtoul ();
+#endif
+
+#ifndef strtoumax
+uintmax_t strtoumax ();
+#endif
+
+static int
+bkm_scale (__strtol_t *x, int scale_factor)
+{
+ __strtol_t product = *x * scale_factor;
+ if (*x != product / scale_factor)
+ return 1;
+ *x = product;
+ return 0;
+}
+
+static int
+bkm_scale_by_power (__strtol_t *x, int base, int power)
+{
+ while (power--)
+ if (bkm_scale (x, base))
+ return 1;
+
+ return 0;
+}
+
+/* FIXME: comment. */
+
+strtol_error
+__xstrtol (const char *s, char **ptr, int strtol_base,
+ __strtol_t *val, const char *valid_suffixes)
+{
+ char *t_ptr;
+ char **p;
+ __strtol_t tmp;
+
+ assert (0 <= strtol_base && strtol_base <= 36);
+
+ p = (ptr ? ptr : &t_ptr);
+
+ if (! TYPE_SIGNED (__strtol_t))
+ {
+ const char *q = s;
+ while (ISSPACE ((unsigned char) *q))
+ ++q;
+ if (*q == '-')
+ return LONGINT_INVALID;
+ }
+
+ errno = 0;
+ tmp = __strtol (s, p, strtol_base);
+ if (errno != 0)
+ return LONGINT_OVERFLOW;
+ if (*p == s)
+ return LONGINT_INVALID;
+
+ /* Let valid_suffixes == NULL mean `allow any suffix'. */
+ /* FIXME: update all callers except the ones that allow suffixes
+ after the number, changing last parameter NULL to `""'. */
+ if (!valid_suffixes)
+ {
+ *val = tmp;
+ return LONGINT_OK;
+ }
+
+ if (**p != '\0')
+ {
+ int base = 1024;
+ int suffixes = 1;
+ int overflow;
+
+ if (!strchr (valid_suffixes, **p))
+ {
+ *val = tmp;
+ return LONGINT_INVALID_SUFFIX_CHAR;
+ }
+
+ if (strchr (valid_suffixes, '0'))
+ {
+ /* The ``valid suffix'' '0' is a special flag meaning that
+ an optional second suffix is allowed, which can change
+ the base, e.g. "100MD" for 100 megabytes decimal. */
+
+ switch (p[0][1])
+ {
+ case 'B':
+ suffixes++;
+ break;
+
+ case 'D':
+ base = 1000;
+ suffixes++;
+ break;
+ }
+ }
+
+ switch (**p)
+ {
+ case 'b':
+ overflow = bkm_scale (&tmp, 512);
+ break;
+
+ case 'B':
+ overflow = bkm_scale (&tmp, 1024);
+ break;
+
+ case 'c':
+ overflow = 0;
+ break;
+
+ case 'E': /* Exa */
+ overflow = bkm_scale_by_power (&tmp, base, 6);
+ break;
+
+ case 'G': /* Giga */
+ overflow = bkm_scale_by_power (&tmp, base, 3);
+ break;
+
+ case 'k': /* kilo */
+ overflow = bkm_scale_by_power (&tmp, base, 1);
+ break;
+
+ case 'M': /* Mega */
+ case 'm': /* 'm' is undocumented; for backward compatibility only */
+ overflow = bkm_scale_by_power (&tmp, base, 2);
+ break;
+
+ case 'P': /* Peta */
+ overflow = bkm_scale_by_power (&tmp, base, 5);
+ break;
+
+ case 'T': /* Tera */
+ overflow = bkm_scale_by_power (&tmp, base, 4);
+ break;
+
+ case 'w':
+ overflow = bkm_scale (&tmp, 2);
+ break;
+
+ case 'Y': /* Yotta */
+ overflow = bkm_scale_by_power (&tmp, base, 8);
+ break;
+
+ case 'Z': /* Zetta */
+ overflow = bkm_scale_by_power (&tmp, base, 7);
+ break;
+
+ default:
+ *val = tmp;
+ return LONGINT_INVALID_SUFFIX_CHAR;
+ break;
+ }
+
+ if (overflow)
+ return LONGINT_OVERFLOW;
+
+ (*p) += suffixes;
+ }
+
+ *val = tmp;
+ return LONGINT_OK;
+}
+
+#ifdef TESTING_XSTRTO
+
+# include <stdio.h>
+# include "error.h"
+
+char *program_name;
+
+int
+main (int argc, char** argv)
+{
+ strtol_error s_err;
+ int i;
+
+ program_name = argv[0];
+ for (i=1; i<argc; i++)
+ {
+ char *p;
+ __strtol_t val;
+
+ s_err = __xstrtol (argv[i], &p, 0, &val, "bckmw");
+ if (s_err == LONGINT_OK)
+ {
+ printf ("%s->%lu (%s)\n", argv[i], val, p);
+ }
+ else
+ {
+ STRTOL_FATAL_ERROR (argv[i], "arg", s_err);
+ }
+ }
+ exit (0);
+}
+
+#endif /* TESTING_XSTRTO */
diff --git a/src/xstrtol.h b/src/xstrtol.h
new file mode 100644
index 00000000..7a9a0244
--- /dev/null
+++ b/src/xstrtol.h
@@ -0,0 +1,64 @@
+#ifndef XSTRTOL_H_
+# define XSTRTOL_H_ 1
+
+# if HAVE_INTTYPES_H
+# include <inttypes.h> /* for uintmax_t */
+# endif
+
+# ifndef PARAMS
+# if defined PROTOTYPES || (defined __STDC__ && __STDC__)
+# define PARAMS(Args) Args
+# else
+# define PARAMS(Args) ()
+# endif
+# endif
+
+# ifndef _STRTOL_ERROR
+enum strtol_error
+ {
+ LONGINT_OK, LONGINT_INVALID, LONGINT_INVALID_SUFFIX_CHAR, LONGINT_OVERFLOW
+ };
+typedef enum strtol_error strtol_error;
+# endif
+
+# define _DECLARE_XSTRTOL(name, type) \
+ strtol_error \
+ name PARAMS ((const char *s, char **ptr, int base, \
+ type *val, const char *valid_suffixes));
+_DECLARE_XSTRTOL (xstrtol, long int)
+_DECLARE_XSTRTOL (xstrtoul, unsigned long int)
+_DECLARE_XSTRTOL (xstrtoumax, uintmax_t)
+
+# define _STRTOL_ERROR(Exit_code, Str, Argument_type_string, Err) \
+ do \
+ { \
+ switch ((Err)) \
+ { \
+ case LONGINT_OK: \
+ abort (); \
+ \
+ case LONGINT_INVALID: \
+ error ((Exit_code), 0, "invalid %s `%s'", \
+ (Argument_type_string), (Str)); \
+ break; \
+ \
+ case LONGINT_INVALID_SUFFIX_CHAR: \
+ error ((Exit_code), 0, "invalid character following %s `%s'", \
+ (Argument_type_string), (Str)); \
+ break; \
+ \
+ case LONGINT_OVERFLOW: \
+ error ((Exit_code), 0, "%s `%s' too large", \
+ (Argument_type_string), (Str)); \
+ break; \
+ } \
+ } \
+ while (0)
+
+# define STRTOL_FATAL_ERROR(Str, Argument_type_string, Err) \
+ _STRTOL_ERROR (2, Str, Argument_type_string, Err)
+
+# define STRTOL_FAIL_WARN(Str, Argument_type_string, Err) \
+ _STRTOL_ERROR (0, Str, Argument_type_string, Err)
+
+#endif /* not XSTRTOL_H_ */
diff --git a/src/xstrtoumax.c b/src/xstrtoumax.c
new file mode 100644
index 00000000..04d7cf98
--- /dev/null
+++ b/src/xstrtoumax.c
@@ -0,0 +1,31 @@
+/* xstrtoumax.c -- A more useful interface to strtoumax.
+ Copyright 1999 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Written by Paul Eggert. */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#if HAVE_INTTYPES_H
+# include <inttypes.h>
+#endif
+
+#define __strtol strtoumax
+#define __strtol_t uintmax_t
+#define __xstrtol xstrtoumax
+#include "xstrtol.c"