Re: [perl #34493] h2ph `extern inline' problems
[p5sagit/p5-mst-13.2.git] / pp.c
diff --git a/pp.c b/pp.c
index f960c37..7185f03 100644 (file)
--- a/pp.c
+++ b/pp.c
@@ -3344,7 +3344,7 @@ PP(pp_ord)
     }
 
     XPUSHu(DO_UTF8(argsv) ?
-          utf8n_to_uvchr(s, UTF8_MAXLEN, 0, UTF8_ALLOW_ANYUV) :
+          utf8n_to_uvchr(s, UTF8_MAXBYTES, 0, UTF8_ALLOW_ANYUV) :
           (*s & 0xff));
 
     RETURN;
@@ -3454,7 +3454,7 @@ PP(pp_ucfirst)
     if (DO_UTF8(sv) &&
        (s = (U8*)SvPV_nomg(sv, slen)) && slen &&
        UTF8_IS_START(*s)) {
-       U8 tmpbuf[UTF8_MAXLEN_UCLC+1];
+       U8 tmpbuf[UTF8_MAXBYTES_CASE+1];
        STRLEN ulen;
        STRLEN tculen;
 
@@ -3517,7 +3517,7 @@ PP(pp_lcfirst)
        (s = (U8*)SvPV_nomg(sv, slen)) && slen &&
        UTF8_IS_START(*s)) {
        STRLEN ulen;
-       U8 tmpbuf[UTF8_MAXLEN_UCLC+1];
+       U8 tmpbuf[UTF8_MAXBYTES_CASE+1];
        U8 *tend;
        UV uv;
 
@@ -3574,7 +3574,7 @@ PP(pp_uc)
        STRLEN ulen;
        register U8 *d;
        U8 *send;
-       U8 tmpbuf[UTF8_MAXLEN_UCLC+1];
+       U8 tmpbuf[UTF8_MAXBYTES+1];
 
        s = (U8*)SvPV_nomg(sv,len);
        if (!len) {
@@ -3583,18 +3583,32 @@ PP(pp_uc)
            SETs(TARG);
        }
        else {
-           STRLEN nchar = utf8_length(s, s + len);
+           STRLEN min = len + 1;
 
            (void)SvUPGRADE(TARG, SVt_PV);
-           SvGROW(TARG, (nchar * UTF8_MAXLEN_UCLC) + 1);
+           SvGROW(TARG, min);
            (void)SvPOK_only(TARG);
            d = (U8*)SvPVX(TARG);
            send = s + len;
            while (s < send) {
+               STRLEN u = UTF8SKIP(s);
+
                toUPPER_utf8(s, tmpbuf, &ulen);
+               if (ulen > u && (SvLEN(TARG) < (min += ulen - u))) {
+                   /* If the eventually required minimum size outgrows
+                    * the available space, we need to grow. */
+                   UV o = d - (U8*)SvPVX(TARG);
+
+                   /* If someone uppercases one million U+03B0s we
+                    * SvGROW() one million times.  Or we could try
+                    * guessing how much to allocate without allocating
+                    * too much. Such is life. */
+                   SvGROW(TARG, min);
+                   d = (U8*)SvPVX(TARG) + o;
+               }
                Copy(tmpbuf, d, ulen, U8);
                d += ulen;
-               s += UTF8SKIP(s);
+               s += u;
            }
            *d = '\0';
            SvUTF8_on(TARG);
@@ -3643,7 +3657,7 @@ PP(pp_lc)
        STRLEN ulen;
        register U8 *d;
        U8 *send;
-       U8 tmpbuf[UTF8_MAXLEN_UCLC+1];
+       U8 tmpbuf[UTF8_MAXBYTES_CASE+1];
 
        s = (U8*)SvPV_nomg(sv,len);
        if (!len) {
@@ -3652,16 +3666,18 @@ PP(pp_lc)
            SETs(TARG);
        }
        else {
-           STRLEN nchar = utf8_length(s, s + len);
+           STRLEN min = len + 1;
 
            (void)SvUPGRADE(TARG, SVt_PV);
-           SvGROW(TARG, (nchar * UTF8_MAXLEN_UCLC) + 1);
+           SvGROW(TARG, min);
            (void)SvPOK_only(TARG);
            d = (U8*)SvPVX(TARG);
            send = s + len;
            while (s < send) {
+               STRLEN u = UTF8SKIP(s);
                UV uv = toLOWER_utf8(s, tmpbuf, &ulen);
-#define GREEK_CAPITAL_LETTER_SIGMA 0x03A3 /* Unicode */
+
+#define GREEK_CAPITAL_LETTER_SIGMA 0x03A3 /* Unicode U+03A3 */
                if (uv == GREEK_CAPITAL_LETTER_SIGMA) {
                     /*
                      * Now if the sigma is NOT followed by
@@ -3675,12 +3691,26 @@ PP(pp_lc)
                      * then it should be mapped to 0x03C2,
                      * (GREEK SMALL LETTER FINAL SIGMA),
                      * instead of staying 0x03A3.
-                     * See lib/unicore/SpecCase.txt.
+                     * "should be": in other words,
+                     * this is not implemented yet.
+                     * See lib/unicore/SpecialCasing.txt.
                      */
                }
+               if (ulen > u && (SvLEN(TARG) < (min += ulen - u))) {
+                   /* If the eventually required minimum size outgrows
+                    * the available space, we need to grow. */
+                   UV o = d - (U8*)SvPVX(TARG);
+
+                   /* If someone lowercases one million U+0130s we
+                    * SvGROW() one million times.  Or we could try
+                    * guessing how much to allocate without allocating.
+                    * too much.  Such is life. */
+                   SvGROW(TARG, min);
+                   d = (U8*)SvPVX(TARG) + o;
+               }
                Copy(tmpbuf, d, ulen, U8);
                d += ulen;
-               s += UTF8SKIP(s);
+               s += u;
            }
            *d = '\0';
            SvUTF8_on(TARG);
@@ -4186,8 +4216,7 @@ PP(pp_splice)
     /* make new elements SVs now: avoid problems if they're from the array */
     for (dst = MARK, i = newlen; i; i--) {
         SV *h = *dst;
-       *dst = NEWSV(46, 0);
-       sv_setsv(*dst++, h);
+       *dst++ = newSVsv(h);
     }
 
     if (diff < 0) {                            /* shrinking the area */
@@ -4395,8 +4424,7 @@ PP(pp_unshift)
     else {
        av_unshift(ary, SP - MARK);
        while (MARK < SP) {
-           sv = NEWSV(27, 0);
-           sv_setsv(sv, *++MARK);
+           sv = newSVsv(*++MARK);
            (void)av_store(ary, i++, sv);
        }
     }
@@ -4581,8 +4609,7 @@ PP(pp_split)
            if (m >= strend)
                break;
 
-           dstr = NEWSV(30, m-s);
-           sv_setpvn(dstr, s, m-s);
+           dstr = newSVpvn(s, m-s);
            if (make_mortal)
                sv_2mortal(dstr);
            if (do_utf8)
@@ -4603,8 +4630,7 @@ PP(pp_split)
            m++;
            if (m >= strend)
                break;
-           dstr = NEWSV(30, m-s);
-           sv_setpvn(dstr, s, m-s);
+           dstr = newSVpvn(s, m-s);
            if (make_mortal)
                sv_2mortal(dstr);
            if (do_utf8)
@@ -4629,8 +4655,7 @@ PP(pp_split)
                for (m = s; m < strend && *m != c; m++) ;
                if (m >= strend)
                    break;
-               dstr = NEWSV(30, m-s);
-               sv_setpvn(dstr, s, m-s);
+               dstr = newSVpvn(s, m-s);
                if (make_mortal)
                    sv_2mortal(dstr);
                if (do_utf8)
@@ -4651,8 +4676,7 @@ PP(pp_split)
                             csv, multiline ? FBMrf_MULTILINE : 0)) )
 #endif
            {
-               dstr = NEWSV(31, m-s);
-               sv_setpvn(dstr, s, m-s);
+               dstr = newSVpvn(s, m-s);
                if (make_mortal)
                    sv_2mortal(dstr);
                if (do_utf8)
@@ -4685,8 +4709,7 @@ PP(pp_split)
                strend = s + (strend - m);
            }
            m = rx->startp[0] + orig;
-           dstr = NEWSV(32, m-s);
-           sv_setpvn(dstr, s, m-s);
+           dstr = newSVpvn(s, m-s);
            if (make_mortal)
                sv_2mortal(dstr);
            if (do_utf8)
@@ -4701,8 +4724,7 @@ PP(pp_split)
                       parens that didn't match -- they should be set to
                       undef, not the empty string */
                    if (m >= orig && s >= orig) {
-                       dstr = NEWSV(33, m-s);
-                       sv_setpvn(dstr, s, m-s);
+                       dstr = newSVpvn(s, m-s);
                    }
                    else
                        dstr = &PL_sv_undef;  /* undef, not "" */
@@ -4724,8 +4746,7 @@ PP(pp_split)
     /* keep field after final delim? */
     if (s < strend || (iters && origlimit)) {
         STRLEN l = strend - s;
-       dstr = NEWSV(34, l);
-       sv_setpvn(dstr, s, l);
+       dstr = newSVpvn(s, l);
        if (make_mortal)
            sv_2mortal(dstr);
        if (do_utf8)
@@ -4812,5 +4833,5 @@ PP(pp_threadsv)
  * indent-tabs-mode: t
  * End:
  *
- * vim: expandtab shiftwidth=4:
+ * vim: shiftwidth=4:
 */