Change 30058 by [EMAIL PROTECTED] on 2007/01/29 16:46:38

        Integrate:
        [ 28917]
        Subject: [perl #40427] Segfault in pack 
        From: [EMAIL PROTECTED] (via RT) <[EMAIL PROTECTED]>
        Date: Thu, 28 Sep 2006 17:30:37 -0700
        Message-ID: <[EMAIL PROTECTED]>
        
        [ 28975]
        fix bad free in do_exec3()
        
        [ 28985]
        Subject: [perl #40473] sprintf width+precision fails on wide chars 
        From: Anatoly Vorobey (via RT) <[EMAIL PROTECTED]>
        Date: Sun, 08 Oct 2006 17:58:16 -0700
        Message-ID: <[EMAIL PROTECTED]>
        
        [ 28993]
        Missing % in format string
        
        [ 29016]
        Avoid undefined behaviour for -DPERL_MEM_LOG by not using a direct
        dereference of member of the structure being reallocated as part of
        the size calculation. (There may be other similar bugs).
        
        [ 29025]
        Subject: [PATCH] Re: sprintf 64 test
        From: SADAHIRO Tomoyuki <[EMAIL PROTECTED]>
        Date: Sun, 15 Oct 2006 16:51:34 +0900
        Message-Id: <[EMAIL PROTECTED]>
        
        1. nullify 0 flag in integer conversions when precision is given
        2. ignore space after a plus sign as a sign for a nonnegative number
        3. make a negative precision through * working as if the precision
           is omitted

Affected files ...

... //depot/maint-5.8/perl/doio.c#103 integrate
... //depot/maint-5.8/perl/perl.h#150 integrate
... //depot/maint-5.8/perl/pod/perlfunc.pod#89 integrate
... //depot/maint-5.8/perl/pp_pack.c#56 integrate
... //depot/maint-5.8/perl/regcomp.c#96 integrate
... //depot/maint-5.8/perl/sv.c#330 integrate
... //depot/maint-5.8/perl/t/op/sprintf.t#18 integrate
... //depot/maint-5.8/perl/t/op/sprintf2.t#7 integrate

Differences ...

==== //depot/maint-5.8/perl/doio.c#103 (text) ====
Index: perl/doio.c
--- perl/doio.c#102~30057~      2007-01-29 07:55:07.000000000 -0800
+++ perl/doio.c 2007-01-29 08:46:38.000000000 -0800
@@ -1425,11 +1425,13 @@
 {
     register char **a;
     register char *s;
+    char *buf;
     char *cmd;
 
     /* Make a copy so we can change it */
     const Size_t cmdlen = strlen(incmd) + 1;
-    Newx(cmd, cmdlen, char);
+    Newx(buf, cmdlen, char);
+    cmd = buf;
     my_strlcpy(cmd, incmd, cmdlen);
 
     while (*cmd && isSPACE(*cmd))
@@ -1464,7 +1466,7 @@
                  PERL_FPU_POST_EXEC
                  *s = '\'';
                  S_exec_failed(aTHX_ PL_cshname, fd, do_report);
-                 Safefree(cmd);
+                 Safefree(buf);
                  return FALSE;
              }
          }
@@ -1512,7 +1514,7 @@
            PerlProc_execl(PL_sh_path, "sh", "-c", cmd, (char *)NULL);
            PERL_FPU_POST_EXEC
            S_exec_failed(aTHX_ PL_sh_path, fd, do_report);
-           Safefree(cmd);
+           Safefree(buf);
            return FALSE;
        }
     }
@@ -1542,7 +1544,7 @@
        S_exec_failed(aTHX_ PL_Argv[0], fd, do_report);
     }
     do_execfree();
-    Safefree(cmd);
+    Safefree(buf);
     return FALSE;
 }
 

==== //depot/maint-5.8/perl/perl.h#150 (text) ====
Index: perl/perl.h
--- perl/perl.h#149~30057~      2007-01-29 07:55:07.000000000 -0800
+++ perl/perl.h 2007-01-29 08:46:38.000000000 -0800
@@ -3891,7 +3891,7 @@
 EXTCONST char PL_no_helem[]
   INIT("Modification of non-creatable hash value attempted, subscript \"%s\"");
 EXTCONST char PL_no_helem_sv[]
-  INIT("Modification of non-creatable hash value attempted, subscript 
\""SVf"\"");
+  INIT("Modification of non-creatable hash value attempted, subscript 
\"%"SVf"\"");
 EXTCONST char PL_no_modify[]
   INIT("Modification of a read-only value attempted");
 EXTCONST char PL_no_mem[]

==== //depot/maint-5.8/perl/pod/perlfunc.pod#89 (text) ====
Index: perl/pod/perlfunc.pod
--- perl/pod/perlfunc.pod#88~29754~     2007-01-11 05:30:43.000000000 -0800
+++ perl/pod/perlfunc.pod       2007-01-29 08:46:38.000000000 -0800
@@ -5431,6 +5431,12 @@
   printf '<%06s>', 12;  # prints "<000012>"
   printf '<%#x>', 12;   # prints "<0xc>"
 
+When a space and a plus sign are given as the flags at once,
+a plus sign is used to prefix a positive number.
+
+  printf '<%+ d>', 12;   # prints "<+12>"
+  printf '<% +d>', 12;   # prints "<+12>"
+
 =item vector flag
 
 This flag tells perl to interpret the supplied string as a vector of
@@ -5497,11 +5503,22 @@
   printf '<%.4g>', 100.01; # prints "<100>"
 
 For integer conversions, specifying a precision implies that the
-output of the number itself should be zero-padded to this width:
+output of the number itself should be zero-padded to this width,
+where the 0 flag is ignored:
+
+  printf '<%.6d>', 1;      # prints "<000001>"
+  printf '<%+.6d>', 1;     # prints "<+000001>"
+  printf '<%-10.6d>', 1;   # prints "<000001    >"
+  printf '<%10.6d>', 1;    # prints "<    000001>"
+  printf '<%010.6d>', 1;   # prints "<    000001>"
+  printf '<%+10.6d>', 1;   # prints "<   +000001>"
 
   printf '<%.6x>', 1;      # prints "<000001>"
   printf '<%#.6x>', 1;     # prints "<0x000001>"
   printf '<%-10.6x>', 1;   # prints "<000001    >"
+  printf '<%10.6x>', 1;    # prints "<    000001>"
+  printf '<%010.6x>', 1;   # prints "<    000001>"
+  printf '<%#10.6x>', 1;   # prints "<  0x000001>"
 
 For string conversions, specifying a precision truncates the string
 to fit in the specified width:
@@ -5514,6 +5531,18 @@
   printf '<%.6x>', 1;       # prints "<000001>"
   printf '<%.*x>', 6, 1;    # prints "<000001>"
 
+If a precision obtained through C<*> is negative, it has the same
+effect as no precision.
+
+  printf '<%.*s>',  7, "string";   # prints "<string>"
+  printf '<%.*s>',  3, "string";   # prints "<str>"
+  printf '<%.*s>',  0, "string";   # prints "<>"
+  printf '<%.*s>', -1, "string";   # prints "<string>"
+
+  printf '<%.*d>',  1, 0;   # prints "<0>"
+  printf '<%.*d>',  0, 0;   # prints "<>"
+  printf '<%.*d>', -1, 0;   # prints "<0>"
+
 You cannot currently get the precision from a specified number,
 but it is intended that this will be possible in the future using
 e.g. C<.*2$>:

==== //depot/maint-5.8/perl/pp_pack.c#56 (text) ====
Index: perl/pp_pack.c
--- perl/pp_pack.c#55~30051~    2007-01-28 13:56:48.000000000 -0800
+++ perl/pp_pack.c      2007-01-29 08:46:38.000000000 -0800
@@ -2729,6 +2729,7 @@
                if (savsym.howlen == e_star && beglist == endlist)
                    break;              /* No way to continue */
            }
+           items = endlist - beglist;
            lookahead.flags  = symptr->flags & ~group_modifiers;
            goto no_change;
        }

==== //depot/maint-5.8/perl/regcomp.c#96 (text) ====
Index: perl/regcomp.c
--- perl/regcomp.c#95~30033~    2007-01-27 08:40:35.000000000 -0800
+++ perl/regcomp.c      2007-01-29 08:46:38.000000000 -0800
@@ -1666,10 +1666,11 @@
 S_add_data(RExC_state_t *pRExC_state, I32 n, const char *s)
 {
     if (RExC_rx->data) {
+       const U32 count = RExC_rx->data->count;
        Renewc(RExC_rx->data,
-              sizeof(*RExC_rx->data) + sizeof(void*) * (RExC_rx->data->count + 
n - 1),
+              sizeof(*RExC_rx->data) + sizeof(void*) * (count + n - 1),
               char, struct reg_data);
-       Renew(RExC_rx->data->what, RExC_rx->data->count + n, U8);
+       Renew(RExC_rx->data->what, count + n, U8);
        RExC_rx->data->count += n;
     }
     else {

==== //depot/maint-5.8/perl/sv.c#330 (text) ====
Index: perl/sv.c
--- perl/sv.c#329~30057~        2007-01-29 07:55:07.000000000 -0800
+++ perl/sv.c   2007-01-29 08:46:38.000000000 -0800
@@ -8040,7 +8040,10 @@
            switch (*q) {
            case ' ':
            case '+':
-               plus = *q++;
+               if (plus == '+' && *q == ' ') /* '+' over ' ' */
+                   q++;
+               else
+                   plus = *q++;
                continue;
 
            case '-':
@@ -8162,14 +8165,15 @@
                else
                    i = (ewix ? ewix <= svmax : svix < svmax)
                        ? SvIVx(svargs[ewix ? ewix-1 : svix++]) : 0;
-               precis = (i < 0) ? 0 : i;
+               precis = i;
+               has_precis = !(i < 0);
            }
            else {
                precis = 0;
                while (isDIGIT(*q))
                    precis = precis * 10 + (*q++ - '0');
+               has_precis = TRUE;
            }
-           has_precis = TRUE;
        }
 
        /* SIZE */
@@ -8285,13 +8289,17 @@
            else {
                eptr = SvPVx_const(argsv, elen);
                if (DO_UTF8(argsv)) {
+                   I32 old_precis = precis;
                    if (has_precis && precis < elen) {
                        I32 p = precis;
                        sv_pos_u2b(argsv, &p, 0); /* sticks at end */
                        precis = p;
                    }
                    if (width) { /* fudge width (can't fudge elen) */
-                       width += elen - sv_len_utf8(argsv);
+                       if (has_precis && precis < elen)
+                           width += precis - old_precis;
+                       else
+                           width += elen - sv_len_utf8(argsv);
                    }
                    is_utf8 = TRUE;
                }
@@ -8543,6 +8551,10 @@
                        zeros = precis - elen;
                    else if (precis == 0 && elen == 1 && *ptr == '0')
                        elen = 0;
+
+               /* a precision nullifies the 0 flag. */
+                   if (fill == '0')
+                       fill = ' ';
                }
            }
            break;

==== //depot/maint-5.8/perl/t/op/sprintf.t#18 (xtext) ====
Index: perl/t/op/sprintf.t
--- perl/t/op/sprintf.t#17~30003~       2007-01-26 03:36:22.000000000 -0800
+++ perl/t/op/sprintf.t 2007-01-29 08:46:38.000000000 -0800
@@ -209,6 +209,13 @@
 >%034b<     >2**32-1<     >0011111111111111111111111111111111<
 >%-34b<     >2**32-1<     >11111111111111111111111111111111  <
 >%-034b<    >2**32-1<     >11111111111111111111111111111111  <
+>%6b<       >12<          >  1100<
+>%6.5b<     >12<          > 01100<
+>%-6.5b<    >12<          >01100 <
+>%+6.5b<    >12<          > 01100<
+>% 6.5b<    >12<          > 01100<
+>%06.5b<    >12<          > 01100<         >0 flag with precision: no effect<
+>%.5b<      >12<          >01100<
 >%c<        >ord('A')<    >A<
 >%10c<      >ord('A')<    >         A<
 >%#10c<     >ord('A')<    >         A<     ># modifier: no effect<
@@ -220,20 +227,53 @@
 >%d<        >123456.789<  >123456<
 >%d<        >-123456.789< >-123456<
 >%d<        >0<           >0<
+>%-d<       >0<           >0<
 >%+d<       >0<           >+0<
+>% d<       >0<           > 0<
 >%0d<       >0<           >0<
+>%-3d<      >1<           >1  <
+>%+3d<      >1<           > +1<
+>% 3d<      >1<           >  1<
+>%03d<      >1<           >001<
+>%+ 3d<     >1<           > +1<
+>% +3d<     >1<           > +1<
 >%.0d<      >0<           ><
 >%+.0d<     >0<           >+<
+>% .0d<     >0<           > <
+>%-.0d<     >0<           ><
+>%#.0d<     >0<           ><
 >%.0d<      >1<           >1<
 >%d<        >1<           >1<
 >%+d<       >1<           >+1<
 >%#3.2d<    >1<           > 01<            ># modifier: no effect<
 >%3.2d<     >1<           > 01<
->%03.2d<    >1<           >001<
+>%03.2d<    >1<           > 01<            >0 flag with precision: no effect<
 >%-3.2d<    >1<           >01 <
+>%+3.2d<    >1<           >+01<
+>% 3.2d<    >1<           > 01<
 >%-03.2d<   >1<           >01 <            >zero pad + left just.: no effect<
+>%3.*d<     >[2,1]<       > 01<
+>%3.*d<     >[1,1]<       >  1<
+>%3.*d<     >[0,1]<       >  1<
+>%3.*d<     >[-1,1]<      >  1<
+>%.*d<      >[0,0]<       ><
+>%-.*d<     >[0,0]<       ><
+>%+.*d<     >[0,0]<       >+<
+>% .*d<     >[0,0]<       > <
+>%0.*d<     >[0,0]<       ><
+>%.*d<      >[-2,0]<      >0<
+>%-.*d<     >[-2,0]<      >0<
+>%+.*d<     >[-2,0]<      >+0<
+>% .*d<     >[-2,0]<      > 0<
+>%0.*d<     >[-2,0]<      >0<
 >%d<        >-1<          >-1<
+>%-d<       >-1<          >-1<
 >%+d<       >-1<          >-1<
+>% d<       >-1<          >-1<
+>%-3d<      >-1<          >-1 <
+>%+3d<      >-1<          > -1<
+>% 3d<      >-1<          > -1<
+>%03d<      >-1<          >-01<
 >%hd<       >1<           >1<              >More extensive testing of<
 >%ld<       >1<           >1<              >length modifiers would be<
 >%Vd<       >1<           >1<              >platform-specific<
@@ -247,14 +287,14 @@
 >%-v3d<     >"\01\02\03"< >1  .2  .3  <
 >%+-v3d<    >"\01\02\03"< >+1 .2  .3  <
 >%v4.3d<    >"\01\02\03"< > 001. 002. 003<
->%0v4.3d<   >"\01\02\03"< >0001.0002.0003<
+>%0v4.3d<   >"\01\02\03"< > 001. 002. 003<
 >%0*v2d<    >['-', "\0\7\14"]< >00-07-12<
 >%v.*d<     >["\01\02\03", 3]< >001.002.003<
 >%0v*d<     >["\01\02\03", 3]< >001.002.003<
 >%-v*d<     >["\01\02\03", 3]< >1  .2  .3  <
 >%+-v*d<    >["\01\02\03", 3]< >+1 .2  .3  <
 >%v*.*d<    >["\01\02\03", 4, 3]< > 001. 002. 003<
->%0v*.*d<   >["\01\02\03", 4, 3]< >0001.0002.0003<
+>%0v*.*d<   >["\01\02\03", 4, 3]< > 001. 002. 003<
 >%0*v*d<    >['-', "\0\7\13", 2]< >00-07-11<
 >%e<        >1234.875<    >1.234875e+03<
 >%e<        >0.000012345< >1.234500e-05<
@@ -355,7 +395,44 @@
 >%#o<       >2**32-1<     >037777777777<
 >%o<        >642<         >1202<          >check smaller octals across 
 >platforms<
 >%+o<       >642<         >1202<
+>% o<       >642<         >1202<
 >%#o<       >642<         >01202<
+>%4o<       >18<          >  22<
+>%4.3o<     >18<          > 022<
+>%-4.3o<    >18<          >022 <
+>%+4.3o<    >18<          > 022<
+>% 4.3o<    >18<          > 022<
+>%04.3o<    >18<          > 022<          >0 flag with precision: no effect<
+>%4.o<      >36<          >  44<
+>%-4.o<     >36<          >44  <
+>%+4.o<     >36<          >  44<
+>% 4.o<     >36<          >  44<
+>%04.o<     >36<          >  44<          >0 flag with precision: no effect<
+>%.3o<      >18<          >022<
+>%#4o<      >17<          > 021<
+>%#-4o<     >17<          >021 <
+>%-#4o<     >17<          >021 <
+>%#+4o<     >17<          > 021<
+>%# 4o<     >17<          > 021<
+>%#04o<     >17<          >0021<
+>%#4.o<     >16<          > 020<
+>%#-4.o<    >16<          >020 <
+>%-#4.o<    >16<          >020 <
+>%#+4.o<    >16<          > 020<
+>%# 4.o<    >16<          > 020<
+>%#04.o<    >16<          > 020<          >0 flag with precision: no effect<
+>%#4.3o<    >18<          > 022<
+>%#-4.3o<   >18<          >022 <
+>%-#4.3o<   >18<          >022 <
+>%#+4.3o<   >18<          > 022<
+>%# 4.3o<   >18<          > 022<
+>%#04.3o<   >18<          > 022<          >0 flag with precision: no effect<
+>%#6.4o<    >18<          >  0022<
+>%#-6.4o<   >18<          >0022  <
+>%-#6.4o<   >18<          >0022  <
+>%#+6.4o<   >18<          >  0022<
+>%# 6.4o<   >18<          >  0022<
+>%#06.4o<   >18<          >  0022<        >0 flag with precision: no effect<
 >%d< >$p=sprintf('%p',$p);$p=~/^[0-9a-f]+$/< >1< >Coarse hack: hex from %p?<
 >%d< >$p=sprintf('%-8p',$p);$p=~/^[0-9a-f]+\s*$/< >1< >Coarse hack: hex from 
 >%p?<
 >%#p<       >''<          >%#p INVALID<
@@ -371,6 +448,15 @@
 >%3s<       >'string'<    >string<
 >%.3s<      >'string'<    >str<
 >%.*s<      >[3, 'string']< >str<
+>%.*s<      >[2, 'string']< >st<
+>%.*s<      >[1, 'string']< >s<
+>%.*s<      >[0, 'string']< ><
+>%.*s<      >[-1,'string']< >string<  >negative precision to be ignored<
+>%3.*s<     >[3, 'string']< >str<
+>%3.*s<     >[2, 'string']< > st<
+>%3.*s<     >[1, 'string']< >  s<
+>%3.*s<     >[0, 'string']< >   <
+>%3.*s<     >[-1,'string']< >string<  >negative precision to be ignored<
 >%t<        >''<          >%t INVALID<
 >%u<        >2**32-1<     >4294967295<
 >%+u<       >2**32-1<     >4294967295<
@@ -379,6 +465,13 @@
 >%012u<     >2**32-1<     >004294967295<
 >%-12u<     >2**32-1<     >4294967295  <
 >%-012u<    >2**32-1<     >4294967295  <
+>%4u<       >18<          >  18<
+>%4.3u<     >18<          > 018<
+>%-4.3u<    >18<          >018 <
+>%+4.3u<    >18<          > 018<
+>% 4.3u<    >18<          > 018<
+>%04.3u<    >18<          > 018<         >0 flag with precision: no effect<
+>%.3u<      >18<          >018<
 >%v<        >''<          >%v INVALID<
 >%w<        >''<          >%w INVALID<
 >%x<        >2**32-1<     >ffffffff<
@@ -389,7 +482,60 @@
 >%-10x<     >2**32-1<     >ffffffff  <
 >%-010x<    >2**32-1<     >ffffffff  <
 >%0-10x<    >2**32-1<     >ffffffff  <
+>%4x<       >18<          >  12<
+>%4.3x<     >18<          > 012<
+>%-4.3x<    >18<          >012 <
+>%+4.3x<    >18<          > 012<
+>% 4.3x<    >18<          > 012<
+>%04.3x<    >18<          > 012<         >0 flag with precision: no effect<
+>%.3x<      >18<          >012<
+>%4X<       >28<          >  1C<
+>%4.3X<     >28<          > 01C<
+>%-4.3X<    >28<          >01C <
+>%+4.3X<    >28<          > 01C<
+>% 4.3X<    >28<          > 01C<
+>%04.3X<    >28<          > 01C<         >0 flag with precision: no effect<
+>%.3X<      >28<          >01C<
+>%.0x<      >0<           ><
+>%+.0x<     >0<           ><
+>% .0x<     >0<           ><
+>%-.0x<     >0<           ><
+>%#.0x<     >0<           ><
+>%#4x<      >28<          >0x1c<
+>%#4.3x<    >28<          >0x01c<
+>%#-4.3x<   >28<          >0x01c<
+>%#+4.3x<   >28<          >0x01c<
+>%# 4.3x<   >28<          >0x01c<
+>%#04.3x<   >28<          >0x01c<         >0 flag with precision: no effect<
+>%#.3x<     >28<          >0x01c<
+>%#6.3x<    >28<          > 0x01c<
+>%#-6.3x<   >28<          >0x01c <
+>%-#6.3x<   >28<          >0x01c <
+>%#+6.3x<   >28<          > 0x01c<
+>%+#6.3x<   >28<          > 0x01c<
+>%# 6.3x<   >28<          > 0x01c<
+>% #6.3x<   >28<          > 0x01c<
 >%0*x<      >[-10, ,2**32-1]< >ffffffff  <
+>%.*x<      >[0,0]<       ><
+>%-.*x<     >[0,0]<       ><
+>%+.*x<     >[0,0]<       ><
+>% .*x<     >[0,0]<       ><
+>%0.*x<     >[0,0]<       ><
+>%.*x<      >[-3,0]<      >0<
+>%-.*x<     >[-3,0]<      >0<
+>%+.*x<     >[-3,0]<      >0<
+>% .*x<     >[-3,0]<      >0<
+>%0.*x<     >[-3,0]<      >0<
+>%#.*x<     >[0,0]<       ><
+>%#-.*x<    >[0,0]<       ><
+>%#+.*x<    >[0,0]<       ><
+>%# .*x<    >[0,0]<       ><
+>%#0.*x<    >[0,0]<       ><
+>%#.*x<     >[-1,0]<      >0<
+>%#-.*x<    >[-1,0]<      >0<
+>%#+.*x<    >[-1,0]<      >0<
+>%# .*x<    >[-1,0]<      >0<
+>%#0.*x<    >[-1,0]<      >0<
 >%y<        >''<          >%y INVALID<
 >%z<        >''<          >%z INVALID<
 >%2$d %1$d<    >[12, 34]<      >34 12<

==== //depot/maint-5.8/perl/t/op/sprintf2.t#7 (text) ====
Index: perl/t/op/sprintf2.t
--- perl/t/op/sprintf2.t#6~29995~       2007-01-26 01:31:24.000000000 -0800
+++ perl/t/op/sprintf2.t        2007-01-29 08:46:38.000000000 -0800
@@ -6,7 +6,7 @@
     require './test.pl';
 }   
 
-plan tests => 280;
+plan tests => 1292;
 
 is(
     sprintf("%.40g ",0.01),
@@ -28,6 +28,15 @@
        "width calculation under utf8 upgrade, length=$i");
 }
 
+# check simultaneous width & precision with wide characters
+for my $i (1, 3, 5, 10) {
+    my $string = "\x{0410}"x($i+10);   # cyrillic capital A
+    my $expect = "\x{0410}"x$i;        # cut down to exactly $i characters
+    my $format = "%$i.${i}s";
+    is(sprintf($format, $string), $expect,
+       "width & precision interplay with utf8 strings, length=$i");
+}
+
 # Used to mangle PL_sv_undef
 fresh_perl_is(
     'print sprintf "xxx%n\n"; print undef',
@@ -77,3 +86,52 @@
        is ($bad, 0, "pattern '%v' . chr $ord");
     }
 }
+
+sub mysprintf_int_flags {
+    my ($fmt, $num) = @_;
+    die "wrong format $fmt" if $fmt !~ /^%([-+ 0]+)([1-9][0-9]*)d\z/;
+    my $flag  = $1;
+    my $width = $2;
+    my $sign  = $num < 0 ? '-' :
+               $flag =~ /\+/ ? '+' :
+               $flag =~ /\ / ? ' ' :
+               '';
+    my $abs   = abs($num);
+    my $padlen = $width - length($sign.$abs);
+    return
+       $flag =~ /0/ && $flag !~ /-/ # do zero padding
+           ? $sign . '0' x $padlen . $abs
+           : $flag =~ /-/ # left or right
+               ? $sign . $abs . ' ' x $padlen
+               : ' ' x $padlen . $sign . $abs;
+}
+
+# Whole tests for "%4d" with 2 to 4 flags;
+# total counts: 3 * (4**2 + 4**3 + 4**4) == 1008
+
+my @flags = ("-", "+", " ", "0");
+for my $num (0, -1, 1) {
+    for my $f1 (@flags) {
+       for my $f2 (@flags) {
+           for my $f3 ('', @flags) { # '' for doubled flags
+               my $flag = $f1.$f2.$f3;
+               my $width = 4;
+               my $fmt   = '%'."${flag}${width}d";
+               my $result = sprintf($fmt, $num);
+               my $expect = mysprintf_int_flags($fmt, $num);
+               is($result, $expect, qq/sprintf("$fmt",$num)/);
+
+               next if $f3 eq '';
+
+               for my $f4 (@flags) { # quadrupled flags
+                   my $flag = $f1.$f2.$f3.$f4;
+                   my $fmt   = '%'."${flag}${width}d";
+                   my $result = sprintf($fmt, $num);
+                   my $expect = mysprintf_int_flags($fmt, $num);
+                   is($result, $expect, qq/sprintf("$fmt",$num)/);
+               }
+           }
+       }
+    }
+}
+
End of Patch.

Reply via email to