[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;
}
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- Bash 2.05a fix for printf and integer values wider than 32 bits,
Paul Eggert <=