This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Perl_sv_vcatpvfn_flags: move %c handling to ints
authorDavid Mitchell <davem@iabyn.com>
Fri, 26 May 2017 15:39:30 +0000 (16:39 +0100)
committerDavid Mitchell <davem@iabyn.com>
Wed, 7 Jun 2017 08:11:04 +0000 (09:11 +0100)
%c is in some ways like integer formats - we treat the arg as an integer
(with '0+' overloading and Inf/Nan handling), but then at the end convert
it into a 1 char string rather than sequence of 0..9's.

Move the %c code partially into the main integer handling block of
code; this will shortly allow us to unify the SV-as-integer handling code.

sv.c

diff --git a/sv.c b/sv.c
index 98179fe..91098b4 100644 (file)
--- a/sv.c
+++ b/sv.c
@@ -12229,26 +12229,6 @@ Perl_sv_vcatpvfn_flags(pTHX_ SV *const sv, const char *const pat, const STRLEN p
 
            /* STRINGS */
 
-       case 'c':
-           if (vectorize)
-               goto unknown;
-           uv = (args) ? va_arg(*args, int) : SvIV_nomg(argsv);
-           if ((uv > 255 ||
-                (!UVCHR_IS_INVARIANT(uv) && SvUTF8(sv)))
-               && !IN_BYTES)
-            {
-                assert(sizeof(ebuf) >= UTF8_MAXBYTES + 1);
-               eptr = ebuf;
-               elen = uvchr_to_utf8((U8*)eptr, uv) - (U8*)ebuf;
-               is_utf8 = TRUE;
-           }
-           else {
-               c = (char)uv;
-               eptr = &c;
-               elen = 1;
-           }
-           goto string;
-
        case 's':
            if (vectorize)
                goto unknown;
@@ -12367,6 +12347,13 @@ Perl_sv_vcatpvfn_flags(pTHX_ SV *const sv, const char *const pat, const STRLEN p
            base = 16;
            goto integer;
 
+       case 'c':
+           if (vectorize)
+               goto unknown;
+           uv = (args) ? va_arg(*args, int) : SvIV_nomg(argsv);
+            base = 1; /* special value that indicates we're doing a 'c' */
+            goto integer;
+
        case 'D':
 #ifdef IV_IS_QUAD
            intsize = 'q';
@@ -12599,6 +12586,28 @@ Perl_sv_vcatpvfn_flags(pTHX_ SV *const sv, const char *const pat, const STRLEN p
                        esignbuf[esignlen++] = c;
                    }
                    break;
+
+               case 1:
+                    /* special-case: base 1 indicates a 'c' format:
+                     * we use the common code for extracting a uv,
+                     * but handle that value differently here than
+                     * all the other int types */
+                    if ((uv > 255 ||
+                         (!UVCHR_IS_INVARIANT(uv) && SvUTF8(sv)))
+                        && !IN_BYTES)
+                    {
+                        assert(sizeof(ebuf) >= UTF8_MAXBYTES + 1);
+                        eptr = ebuf;
+                        elen = uvchr_to_utf8((U8*)eptr, uv) - (U8*)ebuf;
+                        is_utf8 = TRUE;
+                    }
+                    else {
+                        c = (char)uv;
+                        eptr = &c;
+                        elen = 1;
+                    }
+                    goto string;
+
                default:                /* it had better be ten or less */
                    do {
                        dig = uv % base;