bug-bash
[Top][All Lists]
Advanced

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

Bash 2.05 support for file sizes wider than 'long'


From: Paul Eggert
Subject: Bash 2.05 support for file sizes wider than 'long'
Date: Tue, 1 May 2001 12:55:21 -0700 (PDT)

Configuration Information [Automatically generated, do not change]:
Machine: sparc
OS: solaris2.8
Compiler: gcc
Compilation CFLAGS:  -DPROGRAM='bash' -DCONF_HOSTTYPE='sparc' 
-DCONF_OSTYPE='solaris2.8' -DCONF_MACHTYPE='sparc-sun-solaris2.8' 
-DCONF_VENDOR='sun' -DSHELL  -DHAVE_CONFIG_H   -I.  -I. -I./include -I./lib 
-I/opt/reb/include -g -O2
uname output: SunOS shade.twinsun.com 5.8 Generic_108528-07 sun4u sparc 
SUNW,Ultra-1
Machine Type: sparc-sun-solaris2.8

Bash Version: 2.05
Patch Level: 0
Release Status: release

Description:
        Bash 2.05 uses 'long' for most of its internal arithmetic.
        Unfortunately, this doesn't work on hosts like recent versions
        of GNU/Linux x86 and 32-bit Solaris, which support "large files"
        whose sizes are wider than 'long'.  On these hosts, Bash mishandles
        calculations involving sizes of large files.

        The latest POSIX draft (1003.1-200x draft 6 rationale section
        C.2.6.4) says that shell implementations "are encouraged to
        support signed integer values at least as large as the size of
        the largest file allowed on the implementation".

Repeat-By:
        $ echo hello | dd bs=1024k oseek=2048 >large
        0+1 records in
        0+1 records out
        $ ls -l large
        -rw-rw-r--   1 eggert   eggert   2147483654 May  1 11:56 large
        $ set x $(ls -l large)
        $ filesize=$6    
        $ echo $filesize
        2147483654
        $ ((halfsize=$filesize/2))
        $ echo $halfsize
        -1073741821

        The correct answer is 1073741827.

Fix:

This fix assumes the Bash 2.05 patches I've already sent in.

2001-05-01  Paul Eggert  <eggert@twinsun.com>

        Use 'intmax_t', not 'long', for arithmetic calculations.
        POSIX 1003.1-200x draft 6 recommends that we use an integer as
        least as wide as off_t, and off_t is longer than 'long' on
        "large-file" hosts.

        Most of this fix comes from two sources:

        * Uniformly replacing 'long' with the C99 type 'intmax_t'.

        * Adding Support for intmax_t on pre-C99 hosts.  Much of this
          support is taken taken from GNU fileutils 4.1, which in turn
          is taken from glibc without modification (except for
          changing the LGPL to the GPL).  This should make it easier
          to maintain this code in the future, as it is no longer
          forked from glibc.

        * MANIFEST: Add lib/sh/strtoimax.c, lib/sh/strtoll.c,
        lib/sh/strtoull.c, lib/sh/strtoumax.c.
        * Makefile.in (SHLIB_SOURCE): Add strtoimax.c, strtoll.c,
        strtoull.c, strtoumax.c in the directory ${SH_LIBSRC}.
        * lib/sh/strtoimax.c, lib/sh/strtoll.c, lib/sh/strtoull.c,
        lib/sh/strtoumax.c: New files.  All but strtoimax.c are taken
        from fileutils 4.1.
        * lib/sh/strtol.c, lib/sh/strtoul.c: Upgrade to the same versions
        that are used in fileutils 4.1.
        * lib/sh/Makefile.in (LIBOBJS): New var.
        (CSOURCES): Add strtoimax.c, strtoll.c, strtoull.c, strtoumax.c.
        (OBJECTS): Replace strtol.o and strtoul.o with $(LIBOBJS).
        (strtoimax.o, strtoll.o, strtoull.o, strtoumax.o): New rules.
        (strtol.o, strtoul.o): No longer depend on bashansi.h, ansi_stdlib.h.
        * externs.h (strtol, strtoul): Remove declarations; no longer used.
        (strtoimax, strtoumax): New declarations.

        * aclocal.m4 (BASH_HEADER_INTTYPES, BASH_TYPE_LONG_LONG,
        BASH_TYPE_UNSIGNED_LONG_LONG, BASH_CHECK_DECL): New macros.
        (BASH_CHECK_TYPE): Require BASH_HEADER_INTTYPES and include
        <inttypes.h> if present.  Use AC_DEFINE_UNQUOTED so that the caller
        can pass in a shell var.
        * configure.in (AC_CHECK_FUNCS):
        Move strtol and strtoul to AC_REPLACE_FUNCS.
        (AC_REPLACE_FUNCS): Add strtoimax, strtoll, strtoull, strtoumax.
        (BASH_CHECK_DECL): Check for strtoimax, strtol, strtoll, strtoul,
        strtoull, strtoumax.
        (AC_CHECK_SIZEOF): Add long long.
        (BASH_TYPE_LONG_LONG, BASH_TYPE_UNSIGNED_LONG_LONG): Add.
        (BASH_CHECK_TYPE): Add intmax_t, uintmax_t.
        * config.h.in (SIZEOF_LONG_LONG, intmax_t, uintmax_t, HAVE_LONG_LONG,
        HAVE_UNSIGNED_LONG_LONG, HAVE_DECL_STRTOIMAX, HAVE_DECL_STRTOL,
        HAVE_DECL_STRTOLL, HAVE_DECL_STRTOUL, HAVE_DECL_STRTOULL,
        HAVE_DECL_STRTOUMAX, HAVE_INTTYPES_H): New undefs.
        (HAVE_STRTOL, HAVE_STRTOUL): Remove.

        * array.h (arrayind_t): Use intmax_t, not long.
        * builtins/break.def (break_builtin, continue_builtin): Likewise.
        * builtins/common.c (get_numeric_arg, display_signal_list): Likewise.
        * builtins/common.h (get_numeric_arg, get_dirstack_element,
        set_dirstack_element): Likewise.
        * builtins/history.def (history_builtin, display_history): Likewise.
        * builtins/jobs.def (disown_builtin): Likewise.
        * builtins/kill.def (kill_builtin): Likewise.
        * builtins/let.def (let_builtin, exp_builtin): Likewise.
        * builtins/printf.def (getlong, getulong, getint, printf_builtin):
        Likewise.
        * builtins/pushd.def (pushd_builtin, popd_builtin, dirs_builtin,
        get_dirstack_index, get_dirstack_from_string, get_dirstack_element,
        set_dirstack_element): Likewise.
        * builtins/read.def (read_builtin): Likewise.
        * builtins/shift.def (shift_builtin): Likewise.
        * builtins/wait.def (wait_builtin): Likewise.
        * execute_cmd.c (eval_arith_for_expr, execute_arith_for_command,
        select_query, execute_arith_command): Likewise.
        * expr.c (tokval, subexpr, expassign, exp0, exp1, exp2, exp3, exp4,
        exp5, expshift, expland, explor, expband, expbor, expbxor, expcond,
        exppower, expcomma, strlong, EXPR_CONTENT, evalexp, main, itos):
        Likewise.
        * externs.h (evalexp, inttostr, itos): Likewise.
        * general.h (legal_number): Likewise.
        * general.c (legal_number): Likewise.
        * lib/sh/itos.c (inttostr, itos): Likewise.
        * lib/sh/netopen.c (_getserv): Likewise.
        * mailcheck.c (time_to_check_mail): Likewise.
        * parse.y (read_token_word): Likewise.
        * redir.c: (redir_special_open, do_redirection_internal): Likewise.
        * subst.h (sub_append_number, get_dollar_var_value): Likewise.
        * subst.c (sub_append_number, get_dollar_var_value,
        parameter_brace_expand_word, parameter_brace_expand_length,
        verify_substring_values, parameter_brace_substring,
        parameter_brace_expand, param_expand): Likewise.
        * variables.c (sbrand, assign_seconds, get_seconds, rseed,
        assign_random, make_variable_value, sv_histsize): Likewise.
        * test.c (test_stat, arithcomp, unary_operator, unary_test): Likewise.
        * trap.c (decode_signal): Likewise.

        * array.c (print_element): Use %jd, not %ld.  This is needed
        for the long->intmax_t switch.  This code is for maintainer use
        only, and we can assume the maintainer's libc supports %jd.

        * bashtypes.h: Include <inttypes.h> if present.

        * builtins/bashgetopt.c (internal_getopt): Do not cast 0 to (long *),
        since the proper type is now (intmax_t *).  Just pass NULL.
        * builtins/fc.def (fc_number): Do not cast NULL to (long *),
        since the proper type is now (intmax_t *).

        * builtins/common.c (display_signal_list): Use %d, not %ld, and
        make sure the printf arg is 'int'; the value always fits in 'int'
        anyway.

        * builtins/printf.def (LONG_MAX, LONG_MIN): Remove unused macros.
        (PRIdMAX, PRIuMAX, PRIoMAX, PRIxMAX, PRIXMAX): New macros, defined
        if <inttypes.h> does not exist or does not define them.
        (max): New macro.
        (printf_builtin): Use PRIdMAX etc., not "ld"; this is needed to
        accommodate the switch to intmax_t.

        * include/ansi_stdlib.h (atol): Remove decl; no longer used.

===================================================================
RCS file: MANIFEST,v
retrieving revision 2.5
retrieving revision 2.5.0.1
diff -pu -r2.5 -r2.5.0.1
--- MANIFEST    2001/03/20 14:35:19     2.5
+++ MANIFEST    2001/05/01 01:00:09     2.5.0.1
@@ -328,8 +328,12 @@ lib/sh/stringlist.c        f
 lib/sh/stringvec.c     f
 lib/sh/strpbrk.c       f
 lib/sh/strtod.c                f
+lib/sh/strtoimax.c     f
 lib/sh/strtol.c                f
+lib/sh/strtoll.c       f
 lib/sh/strtoul.c       f
+lib/sh/strtoull.c      f
+lib/sh/strtoumax.c     f
 lib/sh/strtrans.c      f
 lib/sh/times.c         f
 lib/sh/timeval.c       f
===================================================================
RCS file: RCS/Makefile.in,v
retrieving revision 2.5
retrieving revision 2.5.0.1
diff -pu -r2.5 -r2.5.0.1
--- Makefile.in 2001/04/03 19:03:24     2.5
+++ Makefile.in 2001/05/01 01:00:09     2.5.0.1
@@ -142,8 +142,10 @@ SHLIB_SOURCE = ${SH_LIBSRC}/clktck.c ${S
               ${SH_LIBSRC}/getenv.c ${SH_LIBSRC}/oslib.c \
               ${SH_LIBSRC}/setlinebuf.c \
               ${SH_LIBSRC}/strcasecmp.c ${SH_LIBSRC}/strerror.c \
-              ${SH_LIBSRC}/strtod.c ${SH_LIBSRC}/strtol.c \
-              ${SH_LIBSRC}/strtoul.c ${SH_LIBSRC}/vprint.c \
+              ${SH_LIBSRC}/strtod.c ${SH_LIBSRC}/strtoimax.c \
+              ${SH_LIBSRC}/strtol.c ${SH_LIBSRC}/strtoll.c \
+              ${SH_LIBSRC}/strtoul.c ${SH_LIBSRC}/strtoull.c \
+              ${SH_LIBSRC}/strtoumax.c ${SH_LIBSRC}/vprint.c \
               ${SH_LIBSRC}/itos.c ${SH_LIBSRC}/rename.c \
               ${SH_LIBSRC}/zread.c ${SH_LIBSRC}/zwrite.c \
               ${SH_LIBSRC}/shtty.c ${SH_LIBSRC}/inet_aton.c \
===================================================================
RCS file: aclocal.m4,v
retrieving revision 2.5.0.1
retrieving revision 2.5.0.2
diff -pu -r2.5.0.1 -r2.5.0.2
--- aclocal.m4  2001/04/10 19:15:14     2.5.0.1
+++ aclocal.m4  2001/05/01 01:00:09     2.5.0.2
@@ -139,18 +139,32 @@ fi
 ])
 
 dnl
+dnl Check for <inttypes.h>.  This is separated out so that it can be
+dnl AC_REQUIREd.
+dnl
+dnl BASH_HEADER_INTTYPES
+AC_DEFUN(BASH_HEADER_INTTYPES,
+[
+  AC_CHECK_HEADERS(inttypes.h)
+])
+
+dnl
 dnl check for typedef'd symbols in header files, but allow the caller to
 dnl specify the include files to be checked in addition to the default
 dnl 
 dnl BASH_CHECK_TYPE(TYPE, HEADERS, DEFAULT[, VALUE-IF-FOUND])
 AC_DEFUN(BASH_CHECK_TYPE,
 [AC_REQUIRE([AC_HEADER_STDC])dnl
+AC_REQUIRE([BASH_HEADER_INTTYPES])
 AC_MSG_CHECKING(for $1)
 AC_CACHE_VAL(bash_cv_type_$1,
 [AC_EGREP_CPP($1, [#include <sys/types.h>
 #if STDC_HEADERS
 #include <stdlib.h>
 #endif
+#if HAVE_INTTYPES_H
+#include <inttypes.h>
+#endif
 $2
 ], bash_cv_type_$1=yes, bash_cv_type_$1=no)])
 AC_MSG_RESULT($bash_cv_type_$1)
@@ -158,7 +172,7 @@ ifelse($#, 4, [if test $bash_cv_type_$1 
        AC_DEFINE($4)
        fi])
 if test $bash_cv_type_$1 = no; then
-  AC_DEFINE($1, $3)
+  AC_DEFINE_UNQUOTED($1, $3)
 fi
 ])
 
@@ -1373,6 +1387,57 @@ AC_DEFUN(BASH_SYS_LARGEFILE,
    fi
   ])
 
+AC_DEFUN(BASH_TYPE_LONG_LONG,
+[
+  AC_CACHE_CHECK([for long long], bash_cv_type_long_long,
+    [AC_TRY_LINK([long long ll = 1; int i = 63;],
+      [long long llm = (long long) -1;
+       return ll << i | ll >> i | llm / ll | llm % ll;],
+      bash_cv_type_long_long='long long',
+      bash_cv_type_long_long='long')])
+  if test "$bash_cv_type_long_long" = 'long long'; then
+    AC_DEFINE(HAVE_LONG_LONG, 1)
+  fi
+])
+
+AC_DEFUN(BASH_TYPE_UNSIGNED_LONG_LONG,
+[
+  AC_CACHE_CHECK([for unsigned long long], bash_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;],
+      bash_cv_type_unsigned_long_long='unsigned long long',
+      bash_cv_type_unsigned_long_long='unsigned long')])
+  if test "$bash_cv_type_unsigned_long_long" = 'unsigned long long'; then
+    AC_DEFINE(HAVE_UNSIGNED_LONG_LONG, 1)
+  fi
+])
+
+AC_DEFUN(BASH_CHECK_DECL,
+[
+  AC_REQUIRE([AC_HEADER_STDC])
+  AC_REQUIRE([BASH_HEADER_INTTYPES])
+  AC_CACHE_CHECK([for $1 declaration], bash_cv_decl_$1,
+    [AC_TRY_LINK(
+       [
+#      if STDC_HEADERS
+#       include <stdlib.h>
+#      endif
+#      if HAVE_INTTYPES_H
+#       include <inttypes.h>
+#      endif
+       ],
+       [return !$1;],
+       bash_cv_decl_$1=yes,
+       bash_cv_decl_$1=no)])
+  bash_tr_func=HAVE_DECL_`echo $1 | tr 'abcdefghijklmnopqrstuvwxyz' 
'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
+  if test $bash_cv_decl_$1 = yes; then
+    AC_DEFINE_UNQUOTED($bash_tr_func, 1)
+  else
+    AC_DEFINE_UNQUOTED($bash_tr_func, 0)
+  fi
+])
+
 dnl
 dnl AC_SYS_RESTARTABLE_SYSCALLS tests only for restarted system calls
 dnl after a signal handler has been installed with signal().  Since
===================================================================
RCS file: array.c,v
retrieving revision 2.5.0.1
retrieving revision 2.5.0.2
diff -pu -r2.5.0.1 -r2.5.0.2
--- array.c     2001/04/29 23:39:20     2.5.0.1
+++ array.c     2001/05/01 01:04:15     2.5.0.2
@@ -578,7 +578,7 @@ int mflags;
 print_element(ae)
 ARRAY_ELEMENT  *ae;
 {
-       printf("array[%ld] = %s\n", element_index(ae), element_value(ae));
+       printf("array[%jd] = %s\n", element_index(ae), element_value(ae));
 }
 
 print_array(a)
===================================================================
RCS file: array.h,v
retrieving revision 2.5.0.1
retrieving revision 2.5.0.2
diff -pu -r2.5.0.1 -r2.5.0.2
--- array.h     2001/04/29 23:39:20     2.5.0.1
+++ array.h     2001/05/01 01:04:15     2.5.0.2
@@ -24,7 +24,7 @@
 
 #include "stdc.h"
 
-typedef long arrayind_t;
+typedef intmax_t arrayind_t;
 
 enum atype {array_indexed, array_assoc};
 
===================================================================
RCS file: bashtypes.h,v
retrieving revision 2.5
retrieving revision 2.5.0.1
diff -pu -r2.5 -r2.5.0.1
--- bashtypes.h 1999/08/05 11:02:34     2.5
+++ bashtypes.h 2001/05/01 01:00:09     2.5.0.1
@@ -1,4 +1,4 @@
-/* bashtypes.h -- <sys/types.h> with special handling for crays. */
+/* bashtypes.h -- Bash system types.  */
 
 /* Copyright (C) 1993 Free Software Foundation, Inc.
 
@@ -31,4 +31,8 @@
 #  undef word
 #endif
 
+#if defined (HAVE_INTTYPES_H)
+#  include <inttypes.h>
+#endif
+
 #endif /* _BASHTYPES_H_ */
===================================================================
RCS file: builtins/bashgetopt.c,v
retrieving revision 2.5
retrieving revision 2.5.0.1
diff -pu -r2.5 -r2.5.0.1
--- builtins/bashgetopt.c       1999/08/05 11:39:28     2.5
+++ builtins/bashgetopt.c       2001/05/01 01:00:09     2.5.0.1
@@ -130,7 +130,7 @@ char                *opts;
                        } else
                                list_optarg = (char *)NULL;
                } else {
-                       if (lcurrent->next && 
legal_number(lcurrent->next->word->word, (long *)0)) {
+                       if (lcurrent->next && legal_number 
(lcurrent->next->word->word, NULL)) {
                                lcurrent = lcurrent->next;
                                list_optarg = lcurrent->word->word;
                                lcurrent = lcurrent->next;
===================================================================
RCS file: builtins/break.def,v
retrieving revision 2.5.0.1
retrieving revision 2.5.0.2
diff -pu -r2.5.0.1 -r2.5.0.2
--- builtins/break.def  2001/04/29 00:22:00     2.5.0.1
+++ builtins/break.def  2001/05/01 01:06:58     2.5.0.2
@@ -59,7 +59,7 @@ int
 break_builtin (list)
      WORD_LIST *list;
 {
-  long newbreak;
+  intmax_t newbreak;
 
   if (check_loop_level () == 0)
     return (EXECUTION_SUCCESS);
@@ -94,7 +94,7 @@ int
 continue_builtin (list)
      WORD_LIST *list;
 {
-  long newcont;
+  intmax_t newcont;
 
   if (check_loop_level () == 0)
     return (EXECUTION_SUCCESS);
===================================================================
RCS file: builtins/common.c,v
retrieving revision 2.5.0.1
retrieving revision 2.5.0.2
diff -pu -r2.5.0.1 -r2.5.0.2
--- builtins/common.c   2001/04/29 00:22:00     2.5.0.1
+++ builtins/common.c   2001/05/01 01:06:58     2.5.0.2
@@ -337,12 +337,12 @@ set_dollar_vars_changed ()
    follow.  If FATAL is true, call throw_to_top_level, which exits the
    shell; if not, call jump_to_top_level (DISCARD), which aborts the
    current command. */
-long
+intmax_t
 get_numeric_arg (list, fatal)
      WORD_LIST *list;
      int fatal;
 {
-  long count = 1;
+  intmax_t count = 1;
 
   if (list)
     {
@@ -527,7 +527,7 @@ display_signal_list (list, forcecols)
   register int i, column;
   char *name;
   int result;
-  long signum;
+  int signum;
 
   result = EXECUTION_SUCCESS;
   if (!list)
@@ -562,13 +562,10 @@ display_signal_list (list, forcecols)
   /* List individual signal names or numbers. */
   while (list)
     {
-      if (legal_number (list->word->word, &signum))
+      intmax_t value;
+      if (legal_number (list->word->word, &value))
        {
-         /* This is specified by Posix.2 so that exit statuses can be
-            mapped into signal numbers. */
-         if (signum > 128)
-           signum -= 128;
-         if (signum < 0 || signum >= NSIG)
+         if (! (0 <= value && value < NSIG + 128))
            {
              builtin_error ("bad signal number: %s", list->word->word);
              result = EXECUTION_FAILURE;
@@ -576,6 +573,10 @@ display_signal_list (list, forcecols)
              continue;
            }
 
+         /* This is specified by Posix.2 so that exit statuses can be
+            mapped into signal numbers. */
+         signum = value <= 128 ? value : value - 128;
+
          name = signal_name (signum);
          if (STREQN (name, "SIGJUNK", 7) || STREQN (name, "Unknown", 7))
            {
@@ -600,7 +601,7 @@ display_signal_list (list, forcecols)
              list = list->next;
              continue;
            }
-         printf ("%ld\n", signum);
+         printf ("%d\n", signum);
        }
       list = list->next;
     }
===================================================================
RCS file: builtins/common.h,v
retrieving revision 2.5.0.1
retrieving revision 2.5.0.2
diff -pu -r2.5.0.1 -r2.5.0.2
--- builtins/common.h   2001/04/29 00:22:00     2.5.0.1
+++ builtins/common.h   2001/05/01 01:06:58     2.5.0.2
@@ -49,7 +49,7 @@ extern int dollar_vars_changed __P((void
 extern void set_dollar_vars_unchanged __P((void));
 extern void set_dollar_vars_changed __P((void));
 
-extern long get_numeric_arg __P((WORD_LIST *, int));
+extern intmax_t get_numeric_arg __P((WORD_LIST *, int));
 extern int read_octal __P((char *));
 
 /* Keeps track of the current working directory. */
@@ -93,8 +93,8 @@ extern void set_var_attribute __P((char 
 
 /* Functions from pushd.def */
 extern char *get_dirstack_from_string __P((char *));
-extern char *get_dirstack_element __P((long, int));
-extern void set_dirstack_element __P((long, int, char *));
+extern char *get_dirstack_element __P((intmax_t, int));
+extern void set_dirstack_element __P((intmax_t, int, char *));
 extern WORD_LIST *get_directory_stack __P((void));
 
 /* Functions from evalstring.c */
===================================================================
RCS file: builtins/fc.def,v
retrieving revision 2.5
retrieving revision 2.5.0.1
diff -pu -r2.5 -r2.5.0.1
--- builtins/fc.def     2001/01/17 16:51:50     2.5
+++ builtins/fc.def     2001/05/01 01:00:09     2.5.0.1
@@ -403,7 +403,7 @@ fc_number (list)
   s = list->word->word;
   if (*s == '-')
     s++;
-  return (legal_number (s, (long *)NULL));
+  return (legal_number (s, NULL));
 }
 
 /* Return an absolute index into HLIST which corresponds to COMMAND.  If
===================================================================
RCS file: builtins/history.def,v
retrieving revision 2.5.0.1
retrieving revision 2.5.0.2
diff -pu -r2.5.0.1 -r2.5.0.2
--- builtins/history.def        2001/04/29 00:22:00     2.5.0.1
+++ builtins/history.def        2001/05/01 01:11:04     2.5.0.2
@@ -90,7 +90,7 @@ history_builtin (list)
 {
   int flags, opt, result;
   char *filename, *delete_arg;
-  long delete_offset;
+  intmax_t delete_offset;
 
   flags = 0;
   reset_internal_getopt ();
@@ -214,7 +214,7 @@ display_history (list)
      WORD_LIST *list;
 {
   register int i;
-  long limit;
+  intmax_t limit;
   HIST_ENTRY **hlist;
 
   if (list)
===================================================================
RCS file: builtins/jobs.def,v
retrieving revision 2.5.0.1
retrieving revision 2.5.0.2
diff -pu -r2.5.0.1 -r2.5.0.2
--- builtins/jobs.def   2001/04/30 01:17:51     2.5.0.1
+++ builtins/jobs.def   2001/05/01 01:11:04     2.5.0.2
@@ -256,7 +256,7 @@ disown_builtin (list)
 
   do
     {
-      long value;
+      intmax_t value;
       BLOCK_CHILD (set, oset);
       job = (list && legal_number (list->word->word, &value)
             && value == (pid_t) value)
===================================================================
RCS file: builtins/kill.def,v
retrieving revision 2.5.0.1
retrieving revision 2.5.0.2
diff -pu -r2.5.0.1 -r2.5.0.2
--- builtins/kill.def   2001/04/30 01:17:51     2.5.0.1
+++ builtins/kill.def   2001/05/01 01:11:04     2.5.0.2
@@ -78,7 +78,7 @@ kill_builtin (list)
   int signal, any_succeeded, listing, saw_signal;
   char *sigspec, *word;
   pid_t pid;
-  long value;
+  intmax_t value;
 
   if (list == 0)
     {
===================================================================
RCS file: builtins/let.def,v
retrieving revision 2.5
retrieving revision 2.5.0.1
diff -pu -r2.5 -r2.5.0.1
--- builtins/let.def    1999/08/05 11:43:19     2.5
+++ builtins/let.def    2001/05/01 01:00:09     2.5.0.1
@@ -77,7 +77,7 @@ int
 let_builtin (list)
      WORD_LIST *list;
 {
-  long ret;
+  intmax_t ret;
   int expok;
 
   if (list == 0)
@@ -93,7 +93,7 @@ let_builtin (list)
        return (EXECUTION_FAILURE);
     }
 
-  return ((ret == 0L) ? EXECUTION_FAILURE : EXECUTION_SUCCESS);
+  return ((ret == 0) ? EXECUTION_FAILURE : EXECUTION_SUCCESS);
 }
 
 #ifdef INCLUDE_UNUSED
@@ -102,7 +102,8 @@ exp_builtin (list)
      WORD_LIST *list;
 {
   char *exp;
-  int ret, expok;
+  int expok;
+  intmax_t ret;
 
   if (list == 0)
     {
@@ -113,6 +114,6 @@ exp_builtin (list)
   exp = string_list (list);
   ret = evalexp (exp, &expok);
   (void)free (exp);
-  return (((ret == 0L) || (expok == 0)) ? EXECUTION_FAILURE : 
EXECUTION_SUCCESS);
+  return (((ret == 0) || (expok == 0)) ? EXECUTION_FAILURE : 
EXECUTION_SUCCESS);
 }
 #endif
===================================================================
RCS file: builtins/printf.def,v
retrieving revision 2.5.0.7
retrieving revision 2.5.0.8
diff -pu -r2.5.0.7 -r2.5.0.8
--- builtins/printf.def 2001/04/27 19:02:40     2.5.0.7
+++ builtins/printf.def 2001/05/01 01:13:01     2.5.0.8
@@ -42,9 +42,7 @@ $END
 #if defined (HAVE_LIMITS_H)
 #  include <limits.h>
 #else
-   /* Assume 32-bit ints and longs. */
-#  define LONG_MAX             2147483647L
-#  define LONG_MIN             (-2147483647L-1)
+   /* Assume 32-bit ints.  */
 #  define INT_MAX              2147483647
 #  define INT_MIN              (-2147483647-1)
 #endif
@@ -61,6 +59,51 @@ $END
 extern int errno;
 #endif
 
+#ifndef PRIdMAX
+# if SIZEOF_LONG < SIZEOF_LONG_LONG
+#  define PRIdMAX "lld"
+# else
+#  define PRIdMAX "ld"
+# endif
+#endif
+
+#ifndef PRIuMAX
+# if SIZEOF_LONG < SIZEOF_LONG_LONG
+#  define PRIuMAX "llu"
+# else
+#  define PRIuMAX "lu"
+# endif
+#endif
+
+#ifndef PRIoMAX
+# if SIZEOF_LONG < SIZEOF_LONG_LONG
+#  define PRIoMAX "llo"
+# else
+#  define PRIoMAX "lo"
+# endif
+#endif
+
+#ifndef PRIxMAX
+# if SIZEOF_LONG < SIZEOF_LONG_LONG
+#  define PRIxMAX "llx"
+# else
+#  define PRIxMAX "lx"
+# endif
+#endif
+
+#ifndef PRIXMAX
+# if SIZEOF_LONG < SIZEOF_LONG_LONG
+#  define PRIXMAX "llX"
+# else
+#  define PRIXMAX "lX"
+# endif
+#endif
+
+#ifdef max
+#  undef max
+#endif
+#define max(a, b) (((a) < (b)) ? (b) : (a))
+
 #define PF(f, func) \
   do { \
     if (have_fieldwidth && have_precision) \
@@ -85,8 +128,8 @@ static char *bexpand __P((char *, int, i
 static int getchr __P((void));
 static char *getstr __P((void));
 static int  getint __P((void));
-static int getlong __P((long *));
-static int getulong __P((unsigned long *));
+static int getlong __P((intmax_t *));
+static int getulong __P((uintmax_t *));
 static int getdouble __P((double *));
 static int asciicode __P((void));
 
@@ -134,7 +177,13 @@ printf_builtin (list)
   if (format == 0 || *format == 0)
     return (EXECUTION_SUCCESS);
 
-  conv = xmalloc (strlen (format) + sizeof ("ld") - 1);
+  conv = xmalloc (strlen (format)
+                 + max (sizeof (PRIdMAX),
+                        max (sizeof (PRIuMAX),
+                             max (sizeof (PRIoMAX),
+                                  max (sizeof (PRIxMAX),
+                                       sizeof (PRIXMAX)))))
+                 - 1);
          
   /* Basic algorithm is to scan the format string for conversion
      specifications -- once one is found, find out if the field
@@ -281,31 +330,31 @@ printf_builtin (list)
            case 'd':
            case 'i':
              {
-               long p;
+               intmax_t p;
 
                if (getlong (&p))
                  PRETURN (EXECUTION_FAILURE);
-               strcpy (cv - 1, "ld");
+               strcpy (cv - 1, PRIdMAX);
                PF (conv, p);
                break;
              }
 
            case 'o':
-             priconv = "lo";
+             priconv = PRIoMAX;
              goto unsigned_argument;
            case 'u':
-             priconv = "lu";
+             priconv = PRIuMAX;
              goto unsigned_argument;
            case 'x':
-             priconv = "lx";
+             priconv = PRIxMAX;
              goto unsigned_argument;
            case 'X':
-             priconv = "lX";
+             priconv = PRIXMAX;
              goto unsigned_argument;
 
            unsigned_argument:
              {
-               unsigned long p;
+               uintmax_t p;
 
                if (getulong (&p))
                  PRETURN (EXECUTION_FAILURE);
@@ -636,7 +685,7 @@ getstr ()
 static int
 getint ()
 {
-  long ret;
+  intmax_t ret;
 
   if (getlong (&ret))
     return (0);
@@ -657,20 +706,20 @@ getint ()
 
 static int
 getlong (lp)
-     long *lp;
+     intmax_t *lp;
 {
-  long ret;
+  intmax_t ret;
   char *ep;
 
   if (garglist == 0)
     {
-      *lp = 0L;
+      *lp = 0;
       return (0);
     }
 
   if (garglist->word->word[0] == '\'' || garglist->word->word[0] == '"')
     {
-      *lp =  (long)asciicode ();
+      *lp = asciicode ();
       return (0);
     }
 
@@ -679,7 +728,7 @@ getlong (lp)
      legal_number does not.  (This was
          if (legal_number (garglist->word->word, &ret) == 0)
      ) */
-  ret = strtol (garglist->word->word, &ep, 0);
+  ret = strtoimax (garglist->word->word, &ep, 0);
   if (*ep != '\0')
     {
       builtin_error ("%s: invalid number", garglist->word->word);
@@ -695,25 +744,25 @@ getlong (lp)
 
 static int
 getulong (ulp)
-     unsigned long *ulp;
+     uintmax_t *ulp;
 {
-  unsigned long ret;
+  uintmax_t ret;
   char *ep;
 
   if (garglist == 0)
     {
-      *ulp = (unsigned long)0;
+      *ulp = 0;
       return (0);
     }
 
   if (garglist->word->word[0] == '\'' || garglist->word->word[0] == '"')
     {
-      *ulp =  (unsigned long)asciicode ();
+      *ulp = asciicode ();
       return (0);
     }
 
   errno = 0;
-  ret = strtoul (garglist->word->word, &ep, 0);
+  ret = strtoumax (garglist->word->word, &ep, 0);
   
   if (*ep)
     {
===================================================================
RCS file: builtins/pushd.def,v
retrieving revision 2.5.0.1
retrieving revision 2.5.0.2
diff -pu -r2.5.0.1 -r2.5.0.2
--- builtins/pushd.def  2001/04/29 00:22:00     2.5.0.1
+++ builtins/pushd.def  2001/05/01 01:13:01     2.5.0.2
@@ -154,7 +154,7 @@ pushd_builtin (list)
 {
   char *temp, *current_directory, *top;
   int j, flags;
-  long num;
+  intmax_t num;
   char direction;
 
   /* If there is no argument list then switch current and
@@ -287,13 +287,13 @@ popd_builtin (list)
      WORD_LIST *list;
 {
   register int i;
-  long which;
+  intmax_t which;
   int flags;
   char direction;
   char *which_word;
 
   which_word = (char *)NULL;
-  for (flags = 0, which = 0L, direction = '+'; list; list = list->next)
+  for (flags = 0, which = 0, direction = '+'; list; list = list->next)
     {
       if (ISOPTION (list->word->word, 'n'))
        {
@@ -364,7 +364,7 @@ dirs_builtin (list)
      WORD_LIST *list;
 {
   int flags, desired_index, index_flag, vflag;
-  long i;
+  intmax_t i;
   char *temp, *w;
 
   for (flags = vflag = index_flag = 0, desired_index = -1, w = ""; list; list 
= list->next)
@@ -537,7 +537,7 @@ add_dirstack_element (dir)
 
 static int
 get_dirstack_index (ind, sign, indexp)
-     long ind;
+     intmax_t ind;
      int sign, *indexp;
 {
   if (indexp)
@@ -565,7 +565,7 @@ get_dirstack_from_string (string)
      char *string;
 {
   int ind, sign, index_flag;
-  long i;
+  intmax_t i;
 
   sign = 1;
   if (*string == '-' || *string == '+')
@@ -589,7 +589,7 @@ get_dirstack_from_string (string)
 #ifdef INCLUDE_UNUSED
 char *
 get_dirstack_element (ind, sign)
-     long ind;
+     intmax_t ind;
      int sign;
 {
   int i;
@@ -602,7 +602,7 @@ get_dirstack_element (ind, sign)
 
 void
 set_dirstack_element (ind, sign, value)
-     long ind;
+     intmax_t ind;
      int sign;
      char *value;
 {
===================================================================
RCS file: builtins/read.def,v
retrieving revision 2.5.0.1
retrieving revision 2.5.0.2
diff -pu -r2.5.0.1 -r2.5.0.2
--- builtins/read.def   2001/04/30 01:44:39     2.5.0.1
+++ builtins/read.def   2001/05/01 01:13:01     2.5.0.2
@@ -122,7 +122,7 @@ read_builtin (list)
   int input_is_tty, input_is_pipe, unbuffered_read;
   int raw, edit, nchars, silent, have_timeout;
   unsigned tmout;
-  long timeoutval, ncharsval;
+  intmax_t timeoutval, ncharsval;
   char c;
   char *input_string, *orig_input_string, *ifs_chars, *prompt, *arrayname;
   char *e, *t, *t1;
===================================================================
RCS file: builtins/shift.def,v
retrieving revision 2.5.0.1
retrieving revision 2.5.0.2
diff -pu -r2.5.0.1 -r2.5.0.2
--- builtins/shift.def  2001/04/29 00:22:00     2.5.0.1
+++ builtins/shift.def  2001/05/01 01:13:01     2.5.0.2
@@ -52,7 +52,7 @@ int
 shift_builtin (list)
      WORD_LIST *list;
 {
-  long times;
+  intmax_t times;
   register int count;
   WORD_LIST *temp;
 
===================================================================
RCS file: builtins/wait.def,v
retrieving revision 2.5.0.1
retrieving revision 2.5.0.2
diff -pu -r2.5.0.1 -r2.5.0.2
--- builtins/wait.def   2001/04/30 01:17:51     2.5.0.1
+++ builtins/wait.def   2001/05/01 01:13:01     2.5.0.2
@@ -120,7 +120,7 @@ wait_builtin (list)
     {
       pid_t pid;
       char *w;
-      long value;
+      intmax_t value;
 
       w = list->word->word;
       if (digit (*w))
===================================================================
RCS file: config.h.in,v
retrieving revision 2.5.0.2
retrieving revision 2.5.0.3
diff -pu -r2.5.0.2 -r2.5.0.3
--- config.h.in 2001/04/13 08:30:59     2.5.0.2
+++ config.h.in 2001/05/01 01:00:09     2.5.0.3
@@ -171,6 +171,9 @@
 /* The number of bytes in a long.  */
 #undef SIZEOF_LONG
 
+/* The number of bytes in a long long.  */
+#undef SIZEOF_LONG_LONG
+
 /* The number of bytes in a pointer to char.  */
 #undef SIZEOF_CHAR_P
 
@@ -231,6 +234,19 @@
 /* Define to `int' if <sys/types.h> doesn't define.  */
 #undef gid_t
 
+/* Define to `long' or `long long' if <inttypes.h> doesn't define.  */
+#undef intmax_t
+
+/* Define to `unsigned long' or `unsigned long long' if <inttypes.h>
+   doesn't define.  */
+#undef uintmax_t
+
+/* Define if you have `long long'.  */
+#undef HAVE_LONG_LONG
+
+/* Define if you have `unsigned long long'.  */
+#undef HAVE_UNSIGNED_LONG_LONG
+
 /* Define if you have quad_t in <sys/types.h>. */
 #undef HAVE_QUAD_T
 
@@ -315,6 +331,13 @@
 
 #undef PRINTF_DECLARED
 
+#undef HAVE_DECL_STRTOIMAX
+#undef HAVE_DECL_STRTOL
+#undef HAVE_DECL_STRTOLL
+#undef HAVE_DECL_STRTOUL
+#undef HAVE_DECL_STRTOULL
+#undef HAVE_DECL_STRTOUMAX
+
 /* Characteristics of system calls and C library functions. */
 
 /* Define if the `getpgrp' function takes no argument.  */
@@ -519,12 +542,6 @@
 /* Define if you have the strtod function. */
 #undef HAVE_STRTOD
 
-/* Define if you have the strtol function. */
-#undef HAVE_STRTOL
-
-/* Define if you have the strtoul function. */
-#undef HAVE_STRTOUL
-
 /* Define if you have the strsignal function or macro. */
 #undef HAVE_STRSIGNAL
 
@@ -576,6 +593,9 @@
 /* Define if you have the <dlfcn.h> header file.  */
 #undef HAVE_DLFCN_H
 
+/* Define if you have the <inttypes.h> header file. */
+#undef HAVE_INTTYPES_H
+
 /* Define if you have the <libintl.h> header file. */
 #undef HAVE_LIBINTL_H
 
===================================================================
RCS file: configure.in,v
retrieving revision 2.5.0.2
retrieving revision 2.5.0.3
diff -pu -r2.5.0.2 -r2.5.0.3
--- configure.in        2001/04/13 08:30:59     2.5.0.2
+++ configure.in        2001/05/01 01:00:09     2.5.0.3
@@ -477,11 +477,20 @@ AC_CHECK_FUNCS(dup2 select getdtablesize
 
 dnl checks for c library functions
 AC_CHECK_FUNCS(bcopy bzero confstr getcwd strcasecmp setenv putenv \
-               setlinebuf setlocale strchr strerror strtod strtol \
-               strtoul tcgetattr uname sysconf ulimit times tzset \
+               setlinebuf setlocale strchr strerror strtod \
+               tcgetattr uname sysconf ulimit times tzset \
                siginterrupt memmove ttyname gethostbyname getservbyname \
                inet_aton strpbrk setvbuf pathconf)
 
+AC_REPLACE_FUNCS(strtoimax strtol strtoll strtoul strtoull strtoumax)
+
+BASH_CHECK_DECL(strtoimax)
+BASH_CHECK_DECL(strtol)
+BASH_CHECK_DECL(strtoll)
+BASH_CHECK_DECL(strtoul)
+BASH_CHECK_DECL(strtoull)
+BASH_CHECK_DECL(strtoumax)
+
 dnl checks for locale functions
 AC_CHECK_HEADERS(libintl.h)
 AC_CHECK_FUNCS(gettext textdomain bindtextdomain)
@@ -552,6 +561,7 @@ AC_CHECK_SIZEOF(char, 1)
 AC_CHECK_SIZEOF(short, 2)
 AC_CHECK_SIZEOF(int, 4)
 AC_CHECK_SIZEOF(long, 4)
+AC_CHECK_SIZEOF(long long, 8)
 AC_CHECK_SIZEOF(char *, 4)
 AC_CHECK_SIZEOF(double, 8)
 
@@ -606,6 +616,12 @@ BASH_CHECK_TYPE(sigset_t, [#include <sig
 BASH_CHECK_TYPE(quad_t, , long, HAVE_QUAD_T)
 BASH_RLIMIT_TYPE
 
+BASH_TYPE_LONG_LONG
+BASH_CHECK_TYPE(intmax_t, , $bash_cv_type_long_long)
+
+BASH_TYPE_UNSIGNED_LONG_LONG
+BASH_CHECK_TYPE(uintmax_t, , $bash_cv_type_unsigned_long_long)
+
 dnl presence and contents of structures used by system calls
 BASH_STRUCT_TERMIOS_LDISC
 BASH_STRUCT_TERMIO_LDISC
===================================================================
RCS file: execute_cmd.c,v
retrieving revision 2.5.0.4
retrieving revision 2.5.0.5
diff -pu -r2.5.0.4 -r2.5.0.5
--- execute_cmd.c       2001/04/30 02:06:02     2.5.0.4
+++ execute_cmd.c       2001/05/01 01:21:56     2.5.0.5
@@ -1599,13 +1599,13 @@ execute_for_command (for_command)
                eval \(\( step \)\)
        done
 */
-static long
+static intmax_t
 eval_arith_for_expr (l, okp)
      WORD_LIST *l;
      int *okp;
 {
   WORD_LIST *new;
-  long expresult;
+  intmax_t expresult;
 
   new = expand_words_no_vars (l);
   if (echo_command_at_execute)
@@ -1619,7 +1619,7 @@ static int
 execute_arith_for_command (arith_for_command)
      ARITH_FOR_COM *arith_for_command;
 {
-  long expresult;
+  intmax_t expresult;
   int expok, result, body_status;
 
   body_status = EXECUTION_SUCCESS;
@@ -1794,7 +1794,7 @@ select_query (list, list_len, prompt)
      char *prompt;
 {
   int max_elem_len, indices_len, len;
-  long reply;
+  intmax_t reply;
   WORD_LIST *l;
   char *repl_string, *t;
 
@@ -2144,7 +2144,7 @@ static int
 execute_arith_command (arith_command)
      ARITH_COM *arith_command;
 {
-  long result;
+  intmax_t result;
   int expok;
   WORD_LIST *new, *p, *printit;
   WORD_DESC *w;
===================================================================
RCS file: expr.c,v
retrieving revision 2.5.0.3
retrieving revision 2.5.0.4
diff -pu -r2.5.0.3 -r2.5.0.4
--- expr.c      2001/04/30 05:12:13     2.5.0.3
+++ expr.c      2001/05/01 05:10:28     2.5.0.4
@@ -142,23 +142,23 @@ static int        curtok;         /* the current token
 static int     lasttok;        /* the previous token */
 static int     assigntok;      /* the OP in OP= */
 static char    *tokstr;        /* current token string */
-static long    tokval;         /* current token value */
+static intmax_t        tokval;         /* current token value */
 static int     noeval;         /* set to 1 if no assignment to be done */
 static procenv_t evalbuf;
 
 static void    readtok ();     /* lexical analyzer */
-static long    subexpr (), expassign (), exp0 (), exp1 (), exp2 (), exp3 (),
+static intmax_t        subexpr (), expassign (), exp0 (), exp1 (), exp2 (), 
exp3 (),
                exp4 (), exp5 (), expshift (), expland (), explor (),
                expband (), expbor (), expbxor (), expcond (), exppower (),
                expcomma ();
-static long    strlong ();
+static intmax_t        strlong ();
 static void    evalerror ();
 
 /* A structure defining a single expression context. */
 typedef struct {
   int curtok, lasttok;
   char *expression, *tp, *lasttp;
-  long tokval;
+  intmax_t tokval;
   char *tokstr;
   int noeval;
 } EXPR_CONTEXT;
@@ -248,17 +248,17 @@ popexp ()
    were assigned at program startup or by the compiler.  Therefore, it is
    safe to let the loop terminate when expr_depth == 0, without freeing up
    any of the expr_depth[0] stuff. */
-long
+intmax_t
 evalexp (expr, validp)
      char *expr;
      int *validp;
 {
-  long val;
+  intmax_t val;
 #if 0
   procenv_t old_evalbuf;
 #endif
 
-  val = 0L;
+  val = 0;
 
 #if 0
   /* Save the value of evalbuf to protect it around possible recursive
@@ -286,7 +286,7 @@ evalexp (expr, validp)
 
       if (validp)
        *validp = 0;
-      return (0L);
+      return (0);
     }
 
   val = subexpr (expr);
@@ -303,18 +303,18 @@ evalexp (expr, validp)
   return (val);
 }
 
-static long
+static intmax_t
 subexpr (expr)
      char *expr;
 {
-  long val;
+  intmax_t val;
   char *p;
 
   for (p = expr; p && *p && cr_whitespace (*p); p++)
     ;
 
   if (p == NULL || *p == '\0')
-    return (0L);
+    return (0);
 
   pushexp ();
   curtok = lasttok = 0;
@@ -322,7 +322,7 @@ subexpr (expr)
   tp = expression;
 
   tokstr = (char *)NULL;
-  tokval = 0L;
+  tokval = 0;
 
   readtok ();
 
@@ -339,10 +339,10 @@ subexpr (expr)
   return val;
 }
 
-static long
+static intmax_t
 expcomma ()
 {
-  register long value;
+  register intmax_t value;
 
   value = expassign ();
   while (curtok == COMMA)
@@ -354,17 +354,17 @@ expcomma ()
   return value;
 }
   
-static long
+static intmax_t
 expassign ()
 {
-  register long        value;
+  register intmax_t value;
   char *lhs, *rhs;
 
   value = expcond ();
   if (curtok == EQ || curtok == OP_ASSIGN)
     {
       int special, op;
-      long lvalue;
+      intmax_t lvalue;
 
       special = curtok == OP_ASSIGN;
 
@@ -435,10 +435,10 @@ expassign ()
 }
 
 /* Conditional expression (expr?expr:expr) */
-static long
+static intmax_t
 expcond ()
 {
-  long cval, val1, val2, rval;
+  intmax_t cval, val1, val2, rval;
   int set_noeval;
 
   set_noeval = 0;
@@ -481,10 +481,10 @@ expcond ()
 }
 
 /* Logical OR. */
-static long
+static intmax_t
 explor ()
 {
-  register long val1, val2;
+  register intmax_t val1, val2;
   int set_noeval;
 
   val1 = expland ();
@@ -509,10 +509,10 @@ explor ()
 }
 
 /* Logical AND. */
-static long
+static intmax_t
 expland ()
 {
-  register long val1, val2;
+  register intmax_t val1, val2;
   int set_noeval;
 
   val1 = expbor ();
@@ -537,10 +537,10 @@ expland ()
 }
 
 /* Bitwise OR. */
-static long
+static intmax_t
 expbor ()
 {
-  register long val1, val2;
+  register intmax_t val1, val2;
 
   val1 = expbxor ();
 
@@ -555,10 +555,10 @@ expbor ()
 }
 
 /* Bitwise XOR. */
-static long
+static intmax_t
 expbxor ()
 {
-  register long val1, val2;
+  register intmax_t val1, val2;
 
   val1 = expband ();
 
@@ -573,10 +573,10 @@ expbxor ()
 }
 
 /* Bitwise AND. */
-static long
+static intmax_t
 expband ()
 {
-  register long val1, val2;
+  register intmax_t val1, val2;
 
   val1 = exp5 ();
 
@@ -590,10 +590,10 @@ expband ()
   return (val1);
 }
 
-static long
+static intmax_t
 exp5 ()
 {
-  register long val1, val2;
+  register intmax_t val1, val2;
 
   val1 = exp4 ();
 
@@ -611,10 +611,10 @@ exp5 ()
   return (val1);
 }
 
-static long
+static intmax_t
 exp4 ()
 {
-  register long val1, val2;
+  register intmax_t val1, val2;
 
   val1 = expshift ();
   while ((curtok == LEQ) ||
@@ -640,10 +640,10 @@ exp4 ()
 }
 
 /* Left and right shifts. */
-static long
+static intmax_t
 expshift ()
 {
-  register long val1, val2;
+  register intmax_t val1, val2;
 
   val1 = exp3 ();
 
@@ -663,10 +663,10 @@ expshift ()
   return (val1);
 }
 
-static long
+static intmax_t
 exp3 ()
 {
-  register long val1, val2;
+  register intmax_t val1, val2;
 
   val1 = exp2 ();
 
@@ -685,10 +685,10 @@ exp3 ()
   return (val1);
 }
 
-static long
+static intmax_t
 exp2 ()
 {
-  register long val1, val2;
+  register intmax_t val1, val2;
 
   val1 = exppower ();
 
@@ -715,10 +715,10 @@ exp2 ()
   return (val1);
 }
 
-static long
+static intmax_t
 exppower ()
 {
-  register long val1, val2, c;
+  register intmax_t val1, val2, c;
 
   val1 = exp1 ();
   if (curtok == POWER)
@@ -726,7 +726,7 @@ exppower ()
       readtok ();
       val2 = exp1 ();
       if (val2 == 0)
-       return (1L);
+       return (1);
       if (val2 < 0)
        evalerror ("exponent less than 0");
       for (c = 1; val2--; c *= val1)
@@ -736,10 +736,10 @@ exppower ()
   return (val1);
 }
 
-static long
+static intmax_t
 exp1 ()
 {
-  register long val;
+  register intmax_t val;
 
   if (curtok == NOT)
     {
@@ -757,10 +757,10 @@ exp1 ()
   return (val);
 }
 
-static long
+static intmax_t
 exp0 ()
 {
-  register long val = 0L, v2;
+  register intmax_t val = 0, v2;
   char *vincdec;
   int stok;
 
@@ -1019,14 +1019,14 @@ evalerror (msg)
    from [0-9][a-z][A-Z]_@ (a = 10, z = 35, A = 36, Z = 61, _ = 62, @ = 63 --
    you get the picture). */
 
-static long
+static intmax_t
 strlong (num)
      char *num;
 {
   register char *s;
   register int c;
   int base, foundbase;
-  long val = 0L;
+  intmax_t val = 0;
 
   s = num;
   base = 10;
@@ -1036,7 +1036,7 @@ strlong (num)
       s++;
 
       if (*s == '\0')
-       return 0L;
+       return 0;
 
        /* Base 16? */
       if (*s == 'x' || *s == 'X')
@@ -1061,7 +1061,7 @@ strlong (num)
            evalerror ("illegal arithmetic base");
 
          base = val;
-         val = 0L;
+         val = 0;
          foundbase++;
        }
       else if (isletter(c) || digit(c) || (c == '_') || (c == '@'))
@@ -1116,7 +1116,7 @@ main (argc, argv)
      char **argv;
 {
   register int i;
-  long v;
+  intmax_t v;
   int expok;
 
   if (setjmp (top_level))
@@ -1128,7 +1128,7 @@ main (argc, argv)
       if (expok == 0)
        fprintf (stderr, "%s: expression error\n", argv[i]);
       else
-       printf ("'%s' -> %ld\n", argv[i], v);
+       printf ("'%s' -> %jd\n", argv[i], v);
     }
   exit (0);
 }
@@ -1145,7 +1145,7 @@ builtin_error (format, arg1, arg2, arg3,
 
 char *
 itos (n)
-     long n;
+     intmax_t n;
 {
   return ("42");
 }
===================================================================
RCS file: externs.h,v
retrieving revision 2.5.0.2
retrieving revision 2.5.0.3
diff -pu -r2.5.0.2 -r2.5.0.3
--- externs.h   2001/04/13 08:30:59     2.5.0.2
+++ externs.h   2001/05/01 17:14:41     2.5.0.3
@@ -27,7 +27,7 @@
 #include "stdc.h"
 
 /* Functions from expr.c. */
-extern long evalexp __P((char *, int *));
+extern intmax_t evalexp __P((char *, int *));
 
 /* Functions from print_cmd.c. */
 extern char *make_command_string __P((COMMAND *));
@@ -122,8 +122,8 @@ extern char *getcwd __P((char *, size_t)
 #endif
 
 /* Declarations for functions defined in lib/sh/itos.c */
-extern char *inttostr __P((long, char *, size_t));
-extern char *itos __P((long));
+extern char *inttostr __P((intmax_t, char *, size_t));
+extern char *itos __P((intmax_t));
 
 /* declarations for functions defined in lib/sh/makepath.c */
 #define MP_DOTILDE     0x01
@@ -224,14 +224,14 @@ extern void sort_char_array __P((char **
 extern double strtod __P((const char *, char **));
 #endif
 
-/* declarations for functions defined in lib/sh/strtol.c */
-#if !defined (HAVE_STRTOL)
-extern long strtol __P((const char *, char **, int));
+/* declarations for functions defined in lib/sh/strtoimax.c */
+#if !HAVE_DECL_STRTOIMAX
+extern intmax_t strtoimax __P((const char *, char **, int));
 #endif
 
-/* declarations for functions defined in lib/sh/strtoul.c */
-#if !defined (HAVE_STRTOUL)
-extern unsigned long strtoul __P((const char *, char **, int));
+/* declarations for functions defined in lib/sh/strtoumax.c */
+#if !HAVE_DECL_STRTOUMAX
+extern uintmax_t strtoumax __P((const char *, char **, int));
 #endif
 
 /* declarations for functions defined in lib/sh/strtrans.c */
===================================================================
RCS file: general.c,v
retrieving revision 2.5.0.3
retrieving revision 2.5.0.4
diff -pu -r2.5.0.3 -r2.5.0.4
--- general.c   2001/04/30 13:21:08     2.5.0.3
+++ general.c   2001/05/01 17:16:04     2.5.0.4
@@ -158,24 +158,24 @@ all_digits (string)
 
 /* Return non-zero if the characters pointed to by STRING constitute a
    valid number.  Stuff the converted number into RESULT if RESULT is
-   a non-null pointer to a long. */
+   not null.  */
 int
 legal_number (string, result)
      char *string;
-     long *result;
+     intmax_t *result;
 {
-  long value;
+  intmax_t value;
   char *ep;
 
   if (result)
     *result = 0;
 
   errno = 0;
-  value = strtol (string, &ep, 10);
+  value = strtoimax (string, &ep, 10);
   if (errno != 0)
     return (0);
 
-  /* Skip any trailing whitespace, since strtol does not. */
+  /* Skip any trailing whitespace, since strtoimax does not. */
   while (whitespace (*ep))
     ep++;
 
===================================================================
RCS file: general.h,v
retrieving revision 2.5.0.1
retrieving revision 2.5.0.2
diff -pu -r2.5.0.1 -r2.5.0.2
--- general.h   2001/04/13 08:15:26     2.5.0.1
+++ general.h   2001/05/01 17:14:41     2.5.0.2
@@ -233,7 +233,7 @@ extern void print_rlimtype __P((RLIMTYPE
 #endif
 
 extern int all_digits __P((char *));
-extern int legal_number __P((char *, long *));
+extern int legal_number __P((char *, intmax_t *));
 extern int legal_identifier __P((char *));
 extern int check_identifier __P((WORD_DESC *, int));
 
===================================================================
RCS file: include/ansi_stdlib.h,v
retrieving revision 2.5
retrieving revision 2.5.0.1
diff -pu -r2.5 -r2.5.0.1
--- include/ansi_stdlib.h       2000/09/07 16:07:49     2.5
+++ include/ansi_stdlib.h       2001/05/01 17:14:41     2.5.0.1
@@ -25,7 +25,6 @@
 
 /* String conversion functions. */
 extern int atoi ();
-extern long int atol ();
 
 extern double atof ();
 extern double strtod ();
===================================================================
RCS file: lib/sh/itos.c,v
retrieving revision 2.5.0.2
retrieving revision 2.5.0.3
diff -pu -r2.5.0.2 -r2.5.0.3
--- lib/sh/itos.c       2001/04/13 08:15:26     2.5.0.2
+++ lib/sh/itos.c       2001/05/01 17:14:41     2.5.0.3
@@ -32,12 +32,12 @@
    does not. */
 char *
 inttostr (i, buf, len)
-     long i;
+     intmax_t i;
      char *buf;
      size_t len;
 {
   char *p;
-  unsigned long ui = i;
+  uintmax_t ui = i;
 
   if (i < 0)
     ui = -ui;
@@ -59,9 +59,9 @@ inttostr (i, buf, len)
    caller should free it. */
 char *
 itos (i)
-     long i;
+     intmax_t i;
 {
-  char *p, lbuf[INT_STRLEN_BOUND (long) + 1];
+  char *p, lbuf[INT_STRLEN_BOUND (intmax_t) + 1];
 
   p = inttostr (i, lbuf, sizeof(lbuf));
   return (savestring (p));
===================================================================
RCS file: lib/sh/Makefile.in,v
retrieving revision 2.5
retrieving revision 2.5.0.1
diff -pu -r2.5 -r2.5.0.1
--- lib/sh/Makefile.in  2000/10/14 21:35:54     2.5
+++ lib/sh/Makefile.in  2001/05/01 17:14:41     2.5.0.1
@@ -25,6 +25,8 @@ BUILD_DIR = @BUILD_DIR@
 
 BASHINCDIR = ${topdir}/include
 
+LIBOBJS = @LIBOBJS@
+
 INSTALL = @INSTALL@
 INSTALL_PROGRAM = @INSTALL_PROGRAM@
 INSTALL_DATA = @INSTALL_DATA@
@@ -62,7 +64,8 @@ LIBRARY_NAME = libsh.a
 
 # The C code source files for this library.
 CSOURCES = clktck.c clock.c getcwd.c getenv.c oslib.c setlinebuf.c \
-          strcasecmp.c strerror.c strtod.c strtol.c strtoul.c \
+          strcasecmp.c strerror.c strtod.c \
+          strtoimax.c strtol.c strtoll.c strtoul.c strtoull.c strtoumax.c \
           vprint.c itos.c rename.c zread.c zwrite.c shtty.c \
           inet_aton.c netopen.c strpbrk.c timeval.c makepath.c pathcanon.c \
           pathphys.c tmpfile.c stringlist.c stringvec.c spell.c \
@@ -73,11 +76,11 @@ HSOURCES = 
 
 # The object files contained in $(LIBRARY_NAME)
 OBJECTS = clktck.o clock.o getcwd.o getenv.o oslib.o setlinebuf.o \
-         strcasecmp.o strerror.o strtod.o strtol.o strtoul.o \
+         strcasecmp.o strerror.o strtod.o \
          vprint.o itos.o rename.o zread.o zwrite.o shtty.o \
          inet_aton.o netopen.o strpbrk.o timeval.o makepath.o pathcanon.o \
          pathphys.o tmpfile.o stringlist.o stringvec.o spell.o shquote.o \
-         strtrans.o strindex.o
+         strtrans.o strindex.o $(LIBOBJS)
 
 SUPPORT = Makefile
 
@@ -129,8 +132,12 @@ stringlist.o: stringlist.c
 stringvec.o: stringvec.c
 strpbrk.o: strpbrk.c
 strtod.o: strtod.c
+strtoimax.o: strtoimax.c
 strtol.o: strtol.c
+strtoll.o: strtoll.c
 strtoul.o: strtoul.c
+strtoull.o: strtoull.c
+strtoumax.o: strtoumax.c
 strtrans.o: strtrans.c
 times.o: times.c
 timeval.o: timeval.c
@@ -163,8 +170,12 @@ stringlist.o: ${BUILD_DIR}/config.h
 stringvec.o: ${BUILD_DIR}/config.h
 strpbrk.o: ${BUILD_DIR}/config.h
 strtod.o: ${BUILD_DIR}/config.h
+strtoimax.o: ${BUILD_DIR}/config.h
 strtol.o: ${BUILD_DIR}/config.h
+strtoll.o: ${BUILD_DIR}/config.h
 strtoul.o: ${BUILD_DIR}/config.h
+strtoull.o: ${BUILD_DIR}/config.h
+strtoumax.o: ${BUILD_DIR}/config.h
 strtrans.o: ${BUILD_DIR}/config.h
 times.o: ${BUILD_DIR}/config.h
 timeval.o: ${BUILD_DIR}/config.h
@@ -291,11 +302,11 @@ strpbrk.o: ${BASHINCDIR}/stdc.h
 strtod.o: ${topdir}/bashansi.h
 strtod.o: ${BASHINCDIR}/ansi_stdlib.h
 
-strtol.o: ${topdir}/bashansi.h
-strtol.o: ${BASHINCDIR}/ansi_stdlib.h
+strtoll.o: strtol.c
+
+strtoul.o: strtol.c
 
-strtoul.o: ${topdir}/bashansi.h
-strtoul.o: ${BASHINCDIR}/ansi_stdlib.h
+strtoull.o: strtol.c strtoul.c
 
 strtrans.o: ${topdir}/bashansi.h
 strtrans.o: ${BASHINCDIR}/ansi_stdlib.h
===================================================================
RCS file: lib/sh/netopen.c,v
retrieving revision 2.5.0.1
retrieving revision 2.5.0.2
diff -pu -r2.5.0.1 -r2.5.0.2
--- lib/sh/netopen.c    2001/04/30 13:33:45     2.5.0.1
+++ lib/sh/netopen.c    2001/05/01 17:20:17     2.5.0.2
@@ -102,7 +102,7 @@ _getserv (serv, proto, pp)
      int proto;
      unsigned short *pp;
 {
-  long l;
+  intmax_t l;
   unsigned short s;
 
   if (legal_number (serv, &l))
===================================================================
RCS file: lib/sh/strtol.c,v
retrieving revision 2.5
retrieving revision 2.5.0.1
diff -pu -r2.5 -r2.5.0.1
--- lib/sh/strtol.c     2001/02/14 22:03:24     2.5
+++ lib/sh/strtol.c     2000/08/07 15:44:09     2.5.0.1
@@ -1,5 +1,7 @@
-/* strtol - Convert string representation of a number into an integer value.
-   Copyright (C) 1997 Free Software Foundation, Inc.
+/* 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
@@ -15,59 +17,236 @@
    along with this program; if not, write to the Free Software Foundation,
    Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 
-#include <config.h>
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif
 
-#if !defined (HAVE_STRTOL)
+#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)
+# define __set_errno(Val) errno = (Val)
 #endif
 
 #ifdef HAVE_LIMITS_H
-#  include <limits.h>
+# include <limits.h>
 #endif
 
-#include <stdc.h>
-#include <bashansi.h>
-
-#ifndef NULL
+#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', operating on unsigned integers.  */
+/* Nonzero if we are defining `strtoul' or `strtoull', operating on
+   unsigned integers.  */
 #ifndef UNSIGNED
 # define UNSIGNED 0
-# define RETTYPE long
+# define INT LONG int
 #else
-# define RETTYPE unsigned long
+# define INT unsigned LONG int
 #endif
 
 /* Determine the name.  */
-#if UNSIGNED
-#  define strtol strtoul
+#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
 
-#ifndef CHAR_BIT
-#  define CHAR_BIT 8
+#if defined _LIBC || defined HAVE_WCHAR_H
+# include <wchar.h>
 #endif
 
-#ifndef ULONG_MAX
-#  define ULONG_MAX ((unsigned long) ~(unsigned long) 0)
-#  define ULONG_MIN ((unsigned long) 0 - ULONG_MAX)
+#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
 
-#ifndef LONG_MAX
-#  define LONG_MAX ((long) (ULONG_MAX >> 1))
-#  define LONG_MIN ((long) (0 - LONG_MAX))
+#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.
@@ -75,89 +254,141 @@ extern int errno;
    If ENDPTR is not NULL, a pointer to the character after the last
    one converted is stored in *ENDPTR.  */
 
-RETTYPE
-strtol (nptr, endptr, base)
-     const char *nptr;
-     char **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 cutoff, i;
+  register unsigned LONG int cutoff;
   register unsigned int cutlim;
-  register const char *s;
-  register unsigned char c;
-  const char *save, *end;
+  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)
-    base = 10;
+    {
+      __set_errno (EINVAL);
+      return 0;
+    }
 
   save = s = nptr;
 
   /* Skip white space.  */
-  while (isspace (*s))
+  while (ISSPACE (*s))
     ++s;
-  if (*s == '\0')
+  if (*s == L_('\0'))
     goto noconv;
 
   /* Check for a sign.  */
-  if (*s == '-' || *s == '+')
+  if (*s == L_('-'))
     {
-      negative = (*s == '-');
+      negative = 1;
+      ++s;
+    }
+  else if (*s == L_('+'))
+    {
+      negative = 0;
       ++s;
     }
   else
     negative = 0;
 
-  if (base == 16 && *s == '0' && toupper (s[1]) == 'X')
-    s += 2;
-
-  /* If BASE is zero, figure it out ourselves.  */
-  if (base == 0)
-    if (*s == '0')
-      {
-       if (toupper (s[1]) == 'X')
-         {
-           s += 2;
-           base = 16;
-         }
-       else
-         base = 8;
-      }
-    else
-      base = 10;
+  /* 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;
 
-  end = NULL;
+#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 = ULONG_MAX / (unsigned long int) base;
-  cutlim = ULONG_MAX % (unsigned long int) base;
+  cutoff = STRTOL_ULONG_MAX / (unsigned LONG int) base;
+  cutlim = STRTOL_ULONG_MAX % (unsigned LONG int) base;
 
   overflow = 0;
   i = 0;
-  for (c = *s; c != '\0'; c = *++s)
+  for (c = *s; c != L_('\0'); c = *++s)
     {
       if (s == end)
        break;
-
-      if (c >= '0' && c <= '9')
-       c -= '0';
-      else if (isalpha (c))
-       c = toupper (c) - 'A' + 10;
+      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 *= (unsigned LONG int) base;
          i += c;
        }
     }
@@ -169,15 +400,15 @@ strtol (nptr, endptr, base)
   /* Store in ENDPTR the address of one character
      past the last character we converted.  */
   if (endptr != NULL)
-    *endptr = (char *) s;
+    *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'.  */
+     `unsigned LONG int', but outside the range of `LONG int'.  */
   if (overflow == 0
       && i > (negative
-             ? -((unsigned long) (LONG_MIN + 1)) + 1
-             : (unsigned long) LONG_MAX))
+             ? -((unsigned LONG int) (STRTOL_LONG_MIN + 1)) + 1
+             : (unsigned LONG int) STRTOL_LONG_MAX))
     overflow = 1;
 #endif
 
@@ -185,30 +416,57 @@ strtol (nptr, endptr, base)
     {
       __set_errno (ERANGE);
 #if UNSIGNED
-      return ULONG_MAX;
+      return STRTOL_ULONG_MAX;
 #else
-      return negative ? LONG_MIN : LONG_MAX;
+      return negative ? STRTOL_LONG_MIN : STRTOL_LONG_MAX;
 #endif
     }
 
-  /* Return the result with the appropriate sign.  */
-  return (negative ? -i : i);
+  /* 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'.  */
+     ENDPTR points to the `x`.  */
   if (endptr != NULL)
     {
-      if (save - nptr >= 2 && toupper (save[-1]) == 'X' && save[-2] == '0')
-       *endptr = (char *) &save[-1];
+      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 = (char *) nptr;
+       *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
 
-#endif /* !HAVE_STRTOL */
+/* 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);
+}
===================================================================
RCS file: lib/sh/strtoul.c,v
retrieving revision 2.5
retrieving revision 2.5.0.1
diff -pu -r2.5 -r2.5.0.1
--- lib/sh/strtoul.c    1997/10/09 15:38:08     2.5
+++ lib/sh/strtoul.c    2001/02/17 16:58:01     2.5.0.1
@@ -1,4 +1,7 @@
-/* Copyright (C) 1997 Free Software Foundation, Inc.
+/* Copyright (C) 1991, 1999, 2001 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
@@ -14,13 +17,6 @@ You should have received a copy of the G
 along with this program; if not, write to the Free Software Foundation,
 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 
-#include <config.h>
-
-#ifndef HAVE_STRTOUL
-
-#define        UNSIGNED        1
-#undef HAVE_STRTOL
-
-#include <strtol.c>
+#define UNSIGNED       1
 
-#endif /* !HAVE_STRTOUL */
+#include "strtol.c"
===================================================================
RCS file: mailcheck.c,v
retrieving revision 2.5.0.1
retrieving revision 2.5.0.2
diff -pu -r2.5.0.1 -r2.5.0.2
--- mailcheck.c 2001/04/13 00:46:05     2.5.0.1
+++ mailcheck.c 2001/05/01 17:14:41     2.5.0.2
@@ -67,7 +67,7 @@ time_to_check_mail ()
 {
   char *temp;
   time_t now;
-  long seconds;
+  intmax_t seconds;
 
   temp = get_string_value ("MAILCHECK");
 
===================================================================
RCS file: parse.y,v
retrieving revision 2.5.0.1
retrieving revision 2.5.0.2
diff -pu -r2.5.0.1 -r2.5.0.2
--- parse.y     2001/04/11 05:56:29     2.5.0.1
+++ parse.y     2001/05/01 17:14:41     2.5.0.2
@@ -3161,7 +3161,7 @@ got_token:
                    last_read_token == LESS_AND ||
                    last_read_token == GREATER_AND))
       {
-       long value;
+       intmax_t value;
        if (legal_number (token, &value) && (int) value == value)
          yylval.number = value;
        else
===================================================================
RCS file: redir.c,v
retrieving revision 2.5.0.2
retrieving revision 2.5.0.3
diff -pu -r2.5.0.2 -r2.5.0.3
--- redir.c     2001/04/27 00:42:04     2.5.0.2
+++ redir.c     2001/05/01 17:22:02     2.5.0.3
@@ -402,7 +402,7 @@ redir_special_open (spec, filename, flag
      enum r_instruction ri;
 {
   int fd;
-  long lfd;
+  intmax_t lfd;
 
   fd = -1;
   switch (spec)
@@ -572,7 +572,7 @@ do_redirection_internal (redirect, for_r
        }
       else if (all_digits (redirectee_word))
        {
-         long value;
+         intmax_t value;
          if (legal_number (redirectee_word, &value) && value == (int) value)
            rd.dest = value;
          else
===================================================================
RCS file: subst.c,v
retrieving revision 2.5.0.7
retrieving revision 2.5.0.8
diff -pu -r2.5.0.7 -r2.5.0.8
--- subst.c     2001/04/30 00:20:51     2.5.0.7
+++ subst.c     2001/05/01 17:22:02     2.5.0.8
@@ -386,7 +386,7 @@ sub_append_string (source, target, indx,
    INDX and SIZE are as in SUB_APPEND_STRING. */
 char *
 sub_append_number (number, target, indx, size)
-     long number;
+     intmax_t number;
      int *indx, *size;
      char *target;
 {
@@ -1896,7 +1896,7 @@ number_of_args ()
 /* Return the value of a positional parameter.  This handles values > 10. */
 char *
 get_dollar_var_value (ind)
-     long ind;
+     intmax_t ind;
 {
   char *temp;
   WORD_LIST *p;
@@ -3872,7 +3872,7 @@ parameter_brace_expand_word (name, var_i
      int var_is_special, quoted;
 {
   char *temp, *tt;
-  long arg_index;
+  intmax_t arg_index;
   SHELL_VAR *var;
   WORD_LIST *l;
 
@@ -4069,13 +4069,13 @@ valid_length_expression (name)
 
 /* Handle the parameter brace expansion that requires us to return the
    length of a parameter. */
-static long
+static intmax_t
 parameter_brace_expand_length (name)
      char *name;
 {
   char *t, *newname;
-  long number;
-  long arg_index;
+  intmax_t number;
+  intmax_t arg_index;
   WORD_LIST *list;
 #if defined (ARRAY_VARS)
   SHELL_VAR *var;
@@ -4209,7 +4209,7 @@ static int
 verify_substring_values (value, substr, vtype, e1p, e2p)
      char *value, *substr;
      int vtype;
-     long *e1p, *e2p;
+     intmax_t *e1p, *e2p;
 {
   char *t, *temp1, *temp2;
   arrayind_t len;
@@ -4352,7 +4352,7 @@ parameter_brace_substring (varname, valu
      char *varname, *value, *substr;
      int quoted;
 {
-  long e1, e2;
+  intmax_t e1, e2;
   int vtype, r;
   char *temp, *val;
   SHELL_VAR *v;
@@ -4629,7 +4629,7 @@ parameter_brace_expand (string, indexp, 
   int want_substring, want_indir, want_patsub;
   char *name, *value, *temp, *temp1;
   int t_index, sindex, c;
-  long number;
+  intmax_t number;
 
   value = (char *)NULL;
   var_is_set = var_is_null = var_is_special = check_nullness = 0;
@@ -4988,7 +4988,7 @@ param_expand (string, sindex, quoted, ex
 {
   char *temp, *temp1;
   int zindex, c, t_index, expok;
-  long number;
+  intmax_t number;
   SHELL_VAR *var;
   WORD_LIST *list, *tlist;
 
===================================================================
RCS file: subst.h,v
retrieving revision 2.5.0.3
retrieving revision 2.5.0.4
diff -pu -r2.5.0.3 -r2.5.0.4
--- subst.h     2001/04/30 00:20:51     2.5.0.3
+++ subst.h     2001/05/01 17:22:02     2.5.0.4
@@ -103,7 +103,7 @@ extern char *sub_append_string __P((char
 
 /* Append the textual representation of NUMBER to TARGET.
    INDEX and SIZE are as in SUB_APPEND_STRING. */
-extern char *sub_append_number __P((long, char *, int *, int *));
+extern char *sub_append_number __P((intmax_t, char *, int *, int *));
 
 /* Return the word list that corresponds to `$*'. */
 extern WORD_LIST *list_rest_of_args __P((void));
@@ -147,7 +147,7 @@ extern WORD_LIST *expand_word_unsplit __
 extern WORD_LIST *expand_word_leave_quoted __P((WORD_DESC *, int));
 
 /* Return the value of a positional parameter.  This handles values > 10. */
-extern char *get_dollar_var_value __P((long));
+extern char *get_dollar_var_value __P((intmax_t));
 
 /* Quote a string to protect it from word splitting. */
 extern char *quote_string __P((char *));
===================================================================
RCS file: test.c,v
retrieving revision 2.5.0.3
retrieving revision 2.5.0.4
diff -pu -r2.5.0.3 -r2.5.0.4
--- test.c      2001/04/30 13:42:15     2.5.0.3
+++ test.c      2001/05/01 17:22:02     2.5.0.4
@@ -175,7 +175,7 @@ test_stat (path, finfo)
   if (path[0] == '/' && path[1] == 'd' && strncmp (path, "/dev/fd/", 8) == 0)
     {
 #if !defined (HAVE_DEV_FD)
-      long fd;
+      intmax_t fd;
       if (legal_number (path + 8, &fd) && fd == (int) fd)
        {
          int r = fstat ((int) fd, finfo);
@@ -415,7 +415,7 @@ arithcomp (s, t, op, flags)
      char *s, *t;
      int op, flags;
 {
-  long l, r;
+  intmax_t l, r;
   int expok;
 
   if (flags & TEST_ARITHEXP)
@@ -550,7 +550,7 @@ static int
 unary_operator ()
 {
   char *op, *arg;
-  long r;
+  intmax_t r;
 
   op = argv[pos];
   if (test_unop (op) == 0)
@@ -586,7 +586,7 @@ int
 unary_test (op, arg)
      char *op, *arg;
 {
-  long r;
+  intmax_t r;
   struct stat stat_buf;
      
   switch (op[1])
===================================================================
RCS file: trap.c,v
retrieving revision 2.5
retrieving revision 2.5.0.1
diff -pu -r2.5 -r2.5.0.1
--- trap.c      2001/02/14 22:00:48     2.5
+++ trap.c      2001/05/01 17:14:41     2.5.0.1
@@ -182,7 +182,7 @@ int
 decode_signal (string)
      char *string;
 {
-  long sig;
+  intmax_t sig;
 
   if (legal_number (string, &sig))
     return ((sig >= 0 && sig <= NSIG) ? (int)sig : NO_SIG);
===================================================================
RCS file: variables.c,v
retrieving revision 2.5.0.4
retrieving revision 2.5.0.5
diff -pu -r2.5.0.4 -r2.5.0.5
--- variables.c 2001/04/29 23:39:20     2.5.0.4
+++ variables.c 2001/05/01 17:36:09     2.5.0.5
@@ -135,7 +135,7 @@ static void initialize_shell_level ();
 static void uidset ();
 static void initialize_dynamic_variables ();
 static void make_vers_array ();
-static void sbrand __P((unsigned long));
+static void sbrand __P((uintmax_t));
 static int qsort_var_comp ();
 static SHELL_VAR *bind_tempenv_variable ();
 
@@ -982,14 +982,14 @@ null_array_assign (self, ind, value)
 /* The value of $SECONDS.  This is the number of seconds since shell
    invocation, or, the number of seconds since the last assignment + the
    value of the last assignment. */
-static long seconds_value_assigned;
+static intmax_t seconds_value_assigned;
 
 static SHELL_VAR *
 assign_seconds (self, value)
      SHELL_VAR *self;
      char *value;
 {
-  seconds_value_assigned = strtol (value, (char **)NULL, 10);
+  seconds_value_assigned = strtoimax (value, (char **)NULL, 10);
   shell_start_time = NOW;
   return (self);
 }
@@ -1012,7 +1012,7 @@ get_seconds (var)
 }
 
 /* The random number seed.  You can change this by setting RANDOM. */
-static unsigned long rseed = 1;
+static uintmax_t rseed = 1;
 static int last_random_value;
 
 /* A linear congruential random number generator based on the ANSI
@@ -1030,7 +1030,7 @@ brand ()
 /* Set the random number generator seed to SEED. */
 static void
 sbrand (seed)
-     unsigned long seed;
+     uintmax_t seed;
 {
   rseed = seed;
   last_random_value = 0;
@@ -1041,7 +1041,7 @@ assign_random (self, value)
      SHELL_VAR *self;
      char *value;
 {
-  sbrand (strtoul (value, (char **) NULL, 10));
+  sbrand (strtoumax (value, (char **) NULL, 10));
   return (self);
 }
 
@@ -1485,7 +1485,7 @@ make_variable_value (var, value)
      char *value;
 {
   char *retval;
-  long lval;
+  intmax_t lval;
   int expok;
 
   /* If this variable has had its type set to integer (via `declare -i'),
@@ -3299,7 +3299,7 @@ sv_histsize (name)
      char *name;
 {
   char *temp;
-  long num;
+  intmax_t num;
 
   temp = get_string_value (name);
 
--- /dev/null   Tue May  1 17:27:01 2001
+++ lib/sh/strtoimax.c  Fri Apr 27 23:43:03 2001
@@ -0,0 +1,81 @@
+/* Convert string representation of a number into an intmax_t value.
+   Copyright 1999, 2001 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_STRTOL
+"this configure-time declaration test was not run"
+#endif
+#if !HAVE_DECL_STRTOL
+long strtol PARAMS ((char const *, char **, int));
+#endif
+
+#ifndef HAVE_DECL_STRTOLL
+"this configure-time declaration test was not run"
+#endif
+#if !HAVE_DECL_STRTOLL && HAVE_LONG_LONG
+long long strtoll PARAMS ((char const *, char **, int));
+#endif
+
+intmax_t
+strtoimax (char const *ptr, char **endptr, int base)
+{
+#define USE_IF_EQUIVALENT(function) \
+    if (sizeof (intmax_t) == sizeof function (ptr, endptr, base)) \
+      return function (ptr, endptr, base);
+
+#if HAVE_LONG_LONG
+    USE_IF_EQUIVALENT (strtoll)
+#endif
+
+  USE_IF_EQUIVALENT (strtol)
+
+  abort ();
+}
+
+#ifdef TESTING
+# include <stdio.h>
+int
+main ()
+{
+  char *p, *endptr;
+  printf ("sizeof intmax_t: %d\n", sizeof (intmax_t));
+  printf ("sizeof strtoll(): %d\n", sizeof strtoll(p, &endptr, 10));
+  printf ("sizeof strtol(): %d\n", sizeof strtol(p, &endptr, 10));
+  exit (0);
+}
+#endif
--- /dev/null   Tue May  1 17:27:01 2001
+++ lib/sh/strtoll.c    Sat Apr  7 21:02:37 2001
@@ -0,0 +1,34 @@
+/* Function to parse a `long long int' from text.
+   Copyright (C) 1995, 1996, 1997, 1999, 2001 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#define        QUAD    1
+
+#include <strtol.c>
+
+#ifdef _LIBC
+# ifdef SHARED
+#  include <shlib-compat.h>
+
+#  if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_2)
+compat_symbol (libc, __strtoll_internal, __strtoq_internal, GLIBC_2_0);
+#  endif
+
+# endif
+weak_alias (strtoll, strtoq)
+#endif
--- /dev/null   Tue May  1 17:27:01 2001
+++ lib/sh/strtoull.c   Mon Aug  7 15:44:09 2000
@@ -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
--- /dev/null   Tue May  1 17:27:01 2001
+++ lib/sh/strtoumax.c  Mon Aug  7 15:44:09 2000
@@ -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



reply via email to

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