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':

Reply via email to