Re: [ID 20020713.008] %vd eats two arguments
Hugo van der Sanden [Sun, 14 Jul 2002 19:00:12 +0000 (20:00 +0100)]
Message-Id: <200207141800.g6EI0CA14256@crypt.compulink.co.uk>

p4raw-id: //depot/perl@17538

sv.c
t/op/sprintf.t

diff --git a/sv.c b/sv.c
index 9a287af..dd44025 100644 (file)
--- a/sv.c
+++ b/sv.c
@@ -7959,7 +7959,9 @@ Perl_sv_vcatpvfn(pTHX_ SV *sv, const char *pat, STRLEN patlen, va_list *args, SV
            goto string;
        }
 
-       if (!args)
+       if (vectorize)
+           argsv = vecsv;
+       else if (!args)
            argsv = (efix ? efix <= svmax : svix < svmax) ?
                    svargs[efix ? efix-1 : svix++] : &PL_sv_undef;
 
@@ -7968,7 +7970,7 @@ Perl_sv_vcatpvfn(pTHX_ SV *sv, const char *pat, STRLEN patlen, va_list *args, SV
            /* STRINGS */
 
        case 'c':
-           uv = args ? va_arg(*args, int) : SvIVx(argsv);
+           uv = (args && !vectorize) ? va_arg(*args, int) : SvIVx(argsv);
            if ((uv > 255 ||
                 (!UNI_IS_INVARIANT(uv) && SvUTF8(sv)))
                && !IN_BYTES) {
@@ -7984,7 +7986,7 @@ Perl_sv_vcatpvfn(pTHX_ SV *sv, const char *pat, STRLEN patlen, va_list *args, SV
            goto string;
 
        case 's':
-           if (args) {
+           if (args && !vectorize) {
                eptr = va_arg(*args, char*);
                if (eptr)
 #ifdef MACOS_TRADITIONAL
@@ -8021,7 +8023,7 @@ Perl_sv_vcatpvfn(pTHX_ SV *sv, const char *pat, STRLEN patlen, va_list *args, SV
             * if ISO or ANSI decide to use '_' for something.
             * So we keep it hidden from users' code.
             */
-           if (!args)
+           if (!args || vectorize)
                goto unknown;
            argsv = va_arg(*args, SV*);
            eptr = SvPVx(argsv, elen);
@@ -8037,7 +8039,7 @@ Perl_sv_vcatpvfn(pTHX_ SV *sv, const char *pat, STRLEN patlen, va_list *args, SV
            /* INTEGERS */
 
        case 'p':
-           if (alt)
+           if (alt || vectorize)
                goto unknown;
            uv = PTR2UV(args ? va_arg(*args, void*) : argsv);
            base = 16;
@@ -8252,7 +8254,6 @@ Perl_sv_vcatpvfn(pTHX_ SV *sv, const char *pat, STRLEN patlen, va_list *args, SV
 
            /* This is evil, but floating point is even more evil */
 
-           vectorize = FALSE;
            /* for SV-style calling, we can only get NV
               for C-style calling, we assume %f is double;
               for simplicity we allow any of %Lf, %llf, %qf for long double
@@ -8281,7 +8282,7 @@ Perl_sv_vcatpvfn(pTHX_ SV *sv, const char *pat, STRLEN patlen, va_list *args, SV
            }
 
            /* now we need (long double) if intsize == 'q', else (double) */
-           nv = args ?
+           nv = (args && !vectorize) ?
 #if LONG_DOUBLESIZE > DOUBLESIZE
                intsize == 'q' ?
                    va_arg(*args, long double) :
@@ -8292,6 +8293,7 @@ Perl_sv_vcatpvfn(pTHX_ SV *sv, const char *pat, STRLEN patlen, va_list *args, SV
                : SvNVx(argsv);
 
            need = 0;
+           vectorize = FALSE;
            if (c != 'e' && c != 'E') {
                i = PERL_INT_MIN;
                /* FIXME: if HAS_LONG_DOUBLE but not USE_LONG_DOUBLE this
@@ -8365,9 +8367,8 @@ Perl_sv_vcatpvfn(pTHX_ SV *sv, const char *pat, STRLEN patlen, va_list *args, SV
            /* SPECIAL */
 
        case 'n':
-           vectorize = FALSE;
            i = SvCUR(sv) - origlen;
-           if (args) {
+           if (args && !vectorize) {
                switch (intsize) {
                case 'h':       *(va_arg(*args, short*)) = i; break;
                default:        *(va_arg(*args, int*)) = i; break;
@@ -8380,6 +8381,7 @@ Perl_sv_vcatpvfn(pTHX_ SV *sv, const char *pat, STRLEN patlen, va_list *args, SV
            }
            else
                sv_setuv_mg(argsv, (UV)i);
+           vectorize = FALSE;
            continue;   /* not "break" */
 
            /* UNKNOWN */
index 01b36fe..c67e65e 100755 (executable)
@@ -361,3 +361,9 @@ __END__
 >%*2$*2$d<     >[12, 3]<       >%*2$*2$d INVALID<
 >%*2*2$d<      >[12, 3]<       >%*2*2$d INVALID<
 >%0v2.2d<      >''<    ><
+>%vc,%d<       >[63, 64, 65]<  >?,64<
+>%vd,%d<       >[1, 2, 3]<     >49,2<
+>%vf,%d<       >[1, 2, 3]<     >1.000000,2<
+>%vp<  >''<    >%vp INVALID<
+>%vs,%d<       >[1, 2, 3]<     >1,2<
+>%v_<  >''<    >%v_ INVALID<