Your change is ok for my original test case. But I have realized that
there are several other problems. Please see attached new version of the
patch.
Problem 1:
==========
bash -c 'printf "x%-010.0fx\n" 123'
x1230000000x
where it should be:
x123 x
Fixed in chunk #6.
Problem 2:
==========
bash -c 'printf "x%+010.0fx\n" 123'
x000000+123x
where it should be:
x+000000123x
Fixed in chunk #3 (but the problem is there also for other types!).
Problem 3:
==========
bash -c 'printf "x%-+10.0fx\n" 123'
x +123x
where it should be:
x+123 x
Fixed in chunk #5 and #1.
Problem 4:
==========
bash -c 'printf "%f\n" -123'
-inf
where it should be:
-123.000000
Fixed in chunk #2.
--
Petr
On 04/13/12 02:27 AM, Chet Ramey wrote:
On 4/12/12 12:25 PM, Petr Sumbera wrote:
Hi,
we are running Bash 3.2.38 on Solaris 10 where asprintf() isn't available.
Thus code in snprintf.c is used.
There is a problem with following command:
bash -c 'printf "x%10.0fx\n" 123'
x0000000123x
Where correct output should be:
x 123x
It seems that '0' after '.' enables zero padding. Please see proposed patch
bellow:
--- bash-3.2.48/lib/sh/snprintf.c Tue Dec 12 12:10:18 2006
+++ bash-3.2.48/lib/sh/snprintf.c Thu Apr 12 08:55:44 2012
@@ -1277,6 +1277,8 @@
data->flags |= PF_ALTFORM;
continue;
case '0':
+ if (data->flags& PF_DOT)
+ continue;
data->flags |= PF_ZEROPAD;
data->pad = '0';
continue;
The same code seems to be also in Bash 4.1 so I guess the problem is still
there.
Any comments?
Thanks for the report. Try this slightly improved patch; yours (and the
original code) doesn't treat a precision specifier beginning with a `0'
correctly. (And the test has to use `printf -v' to exercise the right
code in bash-4.0 and later.)
Chet
--- bash-3.2.48/lib/sh/snprintf.c.orig Tue Dec 12 12:10:18 2006
+++ bash-3.2.48/lib/sh/snprintf.c Fri Apr 13 05:30:04 2012
@@ -352,7 +352,7 @@
while (0)
#define PUT_PLUS(d, p, zero) \
- if ((d) > zero && (p)->justify == RIGHT) \
+ if (((p)->flags & PF_PLUS) && (d) > zero) \
PUT_CHAR('+', p)
#define PUT_SPACE(d, p, zero) \
@@ -907,7 +907,7 @@
double d;
{
#ifdef DBL_MAX
- if (d < DBL_MIN)
+ if (d < -DBL_MAX)
return -1;
else if (d > DBL_MAX)
return 1;
@@ -994,8 +994,10 @@
((p->flags & PF_SPACE) ? 1:0) -
strlen(tmp) - p->precision -
((p->precision != 0 || (p->flags & PF_ALTFORM)) ? 1 : 0); /*
radix char */
- PAD_RIGHT(p);
+ if (*tmp == '-')
+ PUT_CHAR(*tmp++, p);
PUT_PLUS(d, p, 0.);
+ PAD_RIGHT(p);
PUT_SPACE(d, p, 0.);
while (*tmp)
@@ -1276,10 +1278,6 @@
case '#':
data->flags |= PF_ALTFORM;
continue;
- case '0':
- data->flags |= PF_ZEROPAD;
- data->pad = '0';
- continue;
case '*':
if (data->flags & PF_DOT)
data->flags |= PF_STAR_P;
@@ -1303,7 +1301,8 @@
if ((data->flags & PF_DOT) == 0)
{
data->flags |= PF_PLUS;
- data->justify = RIGHT;
+ if ((data->flags & PF_LADJUST) == 0)
+ data->justify = RIGHT;
}
continue;
case '\'':
@@ -1310,6 +1309,13 @@
data->flags |= PF_THOUSANDS;
continue;
+ case '0':
+ if ((data->flags & (PF_DOT|PF_LADJUST)) == 0)
+ {
+ data->flags |= PF_ZEROPAD;
+ data->pad = '0';
+ continue;
+ }
case '1': case '2': case '3':
case '4': case '5': case '6':
case '7': case '8': case '9':