bug-bash
[Top][All Lists]
Advanced

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

Bash 2.05a fix for printf and integer values wider than 32 bits


From: Paul Eggert
Subject: Bash 2.05a fix for printf and integer values wider than 32 bits
Date: Mon, 19 Nov 2001 10:16:59 -0800 (PST)

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 
-g -O2
uname output: SunOS sic.twinsun.com 5.8 Generic_108528-12 sun4u sparc 
SUNW,UltraSPARC-IIi-Engine
Machine Type: sparc-sun-solaris2.8

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

Description:
        bash-2.05a-rc1 introduced some support for printing 64-bit
        ints on 32-bit OSes like 32-bit Solaris and GNU/Linux x86, but
        this support is incomplete and is hard to write portable
        programs for.

        The old tradition in Bash is that the following code can be
        used to print an integer:

                foo=[the result of some integer computation]
                printf '%d\n' $foo

        However, this tradition no longer holds in bash-2.05a-rc1 or
        bash-2.05a if $foo is a file size, because '%d' rejects integers
        that are wider than 'long'.

        I suppose scripts could use %jd or %lld instead of %d, but
        that sort of code won't run correctly on older systems.  It's
        nicer to fix '%d' so that it just works.

Repeat-By:
        $ printf '%d\n' 10000000000
        bash: printf: warning: 10000000000: Result too large
        2147483647

        The output should be 10000000000 on a large-file host.

Fix:

This patch assume the patch I sent in earlier today.

2001-11-19  Paul Eggert  <eggert@twinsun.com>

        * builtins/printf.def (getlong, getulong, getllong, getullong):
        Remove; no longer needed.
        (printf_builtin): To print an integer with %d, use %ld if the integer
        fits in long, %PRIdMAX otherwise.  Similarly for the other integer
        formats like %x.  This lets us print file sizes with %d
        without worrying about portability hassles.
        (getint): Use getintmax instead of getlong.

===================================================================
RCS file: builtins/printf.def,v
retrieving revision 2.5.1.4.0.1
retrieving revision 2.5.1.4.0.2
diff -pc -r2.5.1.4.0.1 -r2.5.1.4.0.2
*** builtins/printf.def 2001/11/19 06:00:59     2.5.1.4.0.1
--- builtins/printf.def 2001/11/19 18:06:21     2.5.1.4.0.2
*************** static char *mklong __P((char *, char *,
*** 110,121 ****
  static int getchr __P((void));
  static char *getstr __P((void));
  static int  getint __P((void));
- static long getlong __P((void));
- static unsigned long getulong __P((void));
- #if defined (HAVE_LONG_LONG)
- static long long getllong __P((void));
- static unsigned long long getullong __P((void));
- #endif
  static intmax_t getintmax __P((void));
  static uintmax_t getuintmax __P((void));
  static double getdouble __P((void));
--- 110,115 ----
*************** printf_builtin (list)
*** 335,366 ****
            case 'i':
              {
                char *f;
! #if defined (HAVE_LONG_LONG)
!               if (thisch == 'l' && nextch == 'l')
!                 {
!                   long long p;
  
!                   p = getllong ();
!                   f = mklong (start, "ll", 2);
!                   PF(f, p);
!                 }
!               else
! #endif
!               if (thisch == 'j')
                  {
-                   intmax_t p;
- 
-                   p = getintmax ();
                    f = mklong (start, PRIdMAX, sizeof PRIdMAX - 2);
!                   PF(f, p);
                  }
                else
                  {
!                   long p;
! 
!                   p = getlong ();
                    f = mklong (start, "l", 1);
!                   PF(f, p);
                  }
                break;
              }
--- 329,351 ----
            case 'i':
              {
                char *f;
!               long p;
!               intmax_t pp;
  
!               p = pp = getintmax ();
!               if (p != pp)
                  {
                    f = mklong (start, PRIdMAX, sizeof PRIdMAX - 2);
!                   PF (f, pp);
                  }
                else
                  {
!                   /* Optimize the common case where the integer fits
!                      in "long".  This also works around some long
!                      long and/or intmax_t library bugs in the common
!                      case, e.g. glibc 2.2 x86.  */
                    f = mklong (start, "l", 1);
!                   PF (f, p);
                  }
                break;
              }
*************** printf_builtin (list)
*** 371,400 ****
            case 'X':
              {
                char *f;
! #if defined (HAVE_LONG_LONG)
!               if (thisch == 'l' && nextch == 'l')
!                 {
!                   unsigned long long p;
  
!                   p = getullong ();
!                   f = mklong (start, "ll", 2);
!                   PF(f, p);
!                 }
!               else
! #endif
!               if (thisch == 'j')
                  {
-                   uintmax_t p;
- 
-                   p = getuintmax ();
                    f = mklong (start, PRIdMAX, sizeof PRIdMAX - 2);
!                   PF(f, p);
                  }
                else
                  {
!                   unsigned long p;
! 
!                   p = getulong ();
                    f = mklong (start, "l", 1);
                    PF (f, p);
                  }
--- 356,373 ----
            case 'X':
              {
                char *f;
!               unsigned long p;
!               uintmax_t pp;
  
!               p = pp = getuintmax ();
!               if (p != pp)
                  {
                    f = mklong (start, PRIdMAX, sizeof PRIdMAX - 2);
!                   PF (f, pp);
                  }
                else
                  {
!                   /* Optimize like case 'd'.  */
                    f = mklong (start, "l", 1);
                    PF (f, p);
                  }
*************** getstr ()
*** 758,766 ****
  static int
  getint ()
  {
!   long ret;
  
!   ret = getlong ();
  
    if (ret > INT_MAX)
      {
--- 731,739 ----
  static int
  getint ()
  {
!   intmax_t ret;
  
!   ret = getintmax ();
  
    if (ret > INT_MAX)
      {
*************** getint ()
*** 776,909 ****
    return ((int)ret);
  }
  
- static long
- getlong ()
- {
-   long ret;
-   char *ep;
- 
-   if (garglist == 0)
-     return (0);
- 
-   if (garglist->word->word[0] == '\'' || garglist->word->word[0] == '"')
-     return asciicode ();
- 
-   errno = 0;
-   ret = strtol (garglist->word->word, &ep, 0);
- 
-   if (*ep)
-     {
-       builtin_error ("%s: invalid number", garglist->word->word);
-       /* POSIX.2 says ``...a diagnostic message shall be written to standard
-        error, and the utility shall not exit with a zero exit status, but
-        shall continue processing any remaining operands and shall write the
-          value accumulated at the time the error was detected to standard
-        output.''  Yecch. */
-       ret = 0;
-       conversion_error = 1;
-     }
-   else if (errno == ERANGE)
-     builtin_error ("warning: %s: %s", garglist->word->word, strerror(ERANGE));
- 
-   garglist = garglist->next;
-   return (ret);
- }
- 
- static unsigned long
- getulong ()
- {
-   unsigned long ret;
-   char *ep;
- 
-   if (garglist == 0)
-     return (0);
- 
-   if (garglist->word->word[0] == '\'' || garglist->word->word[0] == '"')
-     return asciicode ();
- 
-   errno = 0;
-   ret = strtoul (garglist->word->word, &ep, 0);
-   
-   if (*ep)
-     {
-       builtin_error ("%s: invalid number", garglist->word->word);
-       /* Same thing about POSIX.2 conversion error requirements as getlong(). 
*/
-       ret = 0;
-       conversion_error = 1;
-     }
-   else if (errno == ERANGE)
-     builtin_error ("warning: %s: %s", garglist->word->word, strerror(ERANGE));
- 
-   garglist = garglist->next;
-   return (ret);
- }
- 
- #if defined (HAVE_LONG_LONG)
- 
- static long long
- getllong ()
- {
-   long long ret;
-   char *ep;
- 
-   if (garglist == 0)
-     return (0);
- 
-   if (garglist->word->word[0] == '\'' || garglist->word->word[0] == '"')
-     return asciicode ();
- 
-   errno = 0;
-   ret = strtoll (garglist->word->word, &ep, 0);
- 
-   if (*ep)
-     {
-       builtin_error ("%s: invalid number", garglist->word->word);
-       /* POSIX.2 says ``...a diagnostic message shall be written to standard
-        error, and the utility shall not exit with a zero exit status, but
-        shall continue processing any remaining operands and shall write the
-          value accumulated at the time the error was detected to standard
-        output.''  Yecch. */
-       ret = 0;
-       conversion_error = 1;
-     }
-   else if (errno == ERANGE)
-     builtin_error ("warning: %s: %s", garglist->word->word, strerror(ERANGE));
- 
-   garglist = garglist->next;
-   return (ret);
- }
- 
- static unsigned long long
- getullong ()
- {
-   unsigned long long ret;
-   char *ep;
- 
-   if (garglist == 0)
-     return (0);
- 
-   if (garglist->word->word[0] == '\'' || garglist->word->word[0] == '"')
-     return asciicode ();
- 
-   errno = 0;
-   ret = strtoull (garglist->word->word, &ep, 0);
-   
-   if (*ep)
-     {
-       builtin_error ("%s: invalid number", garglist->word->word);
-       /* Same thing about POSIX.2 conversion error requirements as getlong(). 
*/
-       ret = 0;
-       conversion_error = 1;
-     }
-   else if (errno == ERANGE)
-     builtin_error ("warning: %s: %s", garglist->word->word, strerror(ERANGE));
- 
-   garglist = garglist->next;
-   return (ret);
- }
- 
- #endif /* HAVE_LONG_LONG */
- 
  static intmax_t
  getintmax ()
  {
--- 749,754 ----
*************** getuintmax ()
*** 955,961 ****
    if (*ep)
      {
        builtin_error ("%s: invalid number", garglist->word->word);
!       /* Same thing about POSIX.2 conversion error requirements as getlong(). 
*/
        ret = 0;
        conversion_error = 1;
      }
--- 800,807 ----
    if (*ep)
      {
        builtin_error ("%s: invalid number", garglist->word->word);
!       /* Same thing about POSIX.2 conversion error requirements as
!        getintmax().  */
        ret = 0;
        conversion_error = 1;
      }



reply via email to

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