Unicode data updated to be the latest beta of the Unicode 3.0.
[p5sagit/p5-mst-13.2.git] / pp.c
diff --git a/pp.c b/pp.c
index e688848..a020f54 100644 (file)
--- a/pp.c
+++ b/pp.c
@@ -900,7 +900,7 @@ PP(pp_postinc)
 PP(pp_postdec)
 {
     djSP; dTARGET;
-    if(SvREADONLY(TOPs) || SvTYPE(TOPs) > SVt_PVLV)
+    if (SvREADONLY(TOPs) || SvTYPE(TOPs) > SVt_PVLV)
        Perl_croak(aTHX_ PL_no_modify);
     sv_setsv(TARG, TOPs);
     if (SvIOK_notUV(TOPs) && !SvNOK(TOPs) && !SvPOK(TOPs) &&
@@ -1885,14 +1885,14 @@ PP(pp_hex)
     STRLEN n_a;
 
     tmps = POPpx;
-    XPUSHu(scan_hex(tmps, 99, &argtype));
+    XPUSHn(scan_hex(tmps, 99, &argtype));
     RETURN;
 }
 
 PP(pp_oct)
 {
     djSP; dTARGET;
-    UV value;
+    NV value;
     I32 argtype;
     char *tmps;
     STRLEN n_a;
@@ -1908,7 +1908,7 @@ PP(pp_oct)
        value = scan_bin(++tmps, 99, &argtype);
     else
        value = scan_oct(tmps, 99, &argtype);
-    XPUSHu(value);
+    XPUSHn(value);
     RETURN;
 }
 
@@ -2631,7 +2631,7 @@ PP(pp_aslice)
 
 PP(pp_each)
 {
-    djSP; dTARGET;
+    djSP;
     HV *hash = (HV*)POPs;
     HE *entry;
     I32 gimme = GIMME_V;
@@ -2646,12 +2646,13 @@ PP(pp_each)
     if (entry) {
        PUSHs(hv_iterkeysv(entry));     /* won't clobber stack_sp */
        if (gimme == G_ARRAY) {
+           SV *val;
            PUTBACK;
            /* might clobber stack_sp */
-           sv_setsv(TARG, realhv ?
-                    hv_iterval(hash, entry) : avhv_iterval((AV*)hash, entry));
+           val = realhv ?
+                 hv_iterval(hash, entry) : avhv_iterval((AV*)hash, entry);
            SPAGAIN;
-           PUSHs(TARG);
+           PUSHs(val);
        }
     }
     else if (gimme == G_SCALAR)
@@ -3199,7 +3200,9 @@ PP(pp_reverse)
                        s += UTF8SKIP(s);
                        down = (char*)(s - 1);
                        if (s > send || !((*down & 0xc0) == 0x80)) {
-                           Perl_warn(aTHX_ "Malformed UTF-8 character");
+                           if (ckWARN_d(WARN_UTF8))
+                               Perl_warner(aTHX_ WARN_UTF8,
+                                           "Malformed UTF-8 character");
                            break;
                        }
                        while (down > up) {
@@ -3347,8 +3350,11 @@ PP(pp_unpack)
        }
        else if (isDIGIT(*pat)) {
            len = *pat++ - '0';
-           while (isDIGIT(*pat))
+           while (isDIGIT(*pat)) {
                len = (len * 10) + (*pat++ - '0');
+               if (len < 0)
+                   Perl_croak(aTHX_ "Repeat count in unpack overflows");
+           }
        }
        else
            len = (datumtype != '@');
@@ -3383,6 +3389,18 @@ PP(pp_unpack)
                DIE(aTHX_ "x outside of string");
            s += len;
            break;
+       case '#':
+           if (oldsp >= SP)
+               DIE(aTHX_ "# must follow a numeric type");
+           if (*pat != 'a' && *pat != 'A' && *pat != 'Z')
+               DIE(aTHX_ "# must be followed by a, A or Z");
+           datumtype = *pat++;
+           if (*pat == '*')
+               pat++;          /* ignore '*' for compatibility with pack */
+           if (isDIGIT(*pat))
+               DIE(aTHX_ "# cannot take a count" );
+           len = POPi;
+           /* drop through */
        case 'A':
        case 'Z':
        case 'a':
@@ -4353,7 +4371,8 @@ PP(pp_pack)
     MARK++;
     sv_setpvn(cat, "", 0);
     while (pat < patend) {
-#define NEXTFROM (items-- > 0 ? *MARK++ : &PL_sv_no)
+       SV *lengthcode = Nullsv;
+#define NEXTFROM ( lengthcode ? lengthcode : items-- > 0 ? *MARK++ : &PL_sv_no)
        datumtype = *pat++ & 0xFF;
 #ifdef PERL_NATINT_PACK
        natint = 0;
@@ -4378,17 +4397,28 @@ PP(pp_pack)
        }
        else if (isDIGIT(*pat)) {
            len = *pat++ - '0';
-           while (isDIGIT(*pat))
+           while (isDIGIT(*pat)) {
                len = (len * 10) + (*pat++ - '0');
+               if (len < 0)
+                   Perl_croak(aTHX_ "Repeat count in pack overflows");
+           }
        }
        else
            len = 1;
+       if (*pat == '#') {
+           ++pat;
+           if (*pat != 'a' && *pat != 'A' && *pat != 'Z' || pat[1] != '*')
+               DIE(aTHX_ "# must be followed by a*, A* or Z*");
+           lengthcode = sv_2mortal(newSViv(sv_len(items > 0
+                                                  ? *MARK : &PL_sv_no)));
+       }
        switch(datumtype) {
        default:
            Perl_croak(aTHX_ "Invalid type in pack: '%c'", (int)datumtype);
        case ',': /* grandfather in commas but with a warning */
            if (commas++ == 0 && ckWARN(WARN_UNSAFE))
-               Perl_warner(aTHX_ WARN_UNSAFE, "Invalid type in pack: '%c'", (int)datumtype);
+               Perl_warner(aTHX_ WARN_UNSAFE,
+                           "Invalid type in pack: '%c'", (int)datumtype);
            break;
        case '%':
            DIE(aTHX_ "%% may only be used in unpack");
@@ -4983,7 +5013,14 @@ PP(pp_split)
                ++s;
        }
     }
-    else if (strEQ("^", rx->precomp)) {
+    else if (rx->prelen == 1 && *rx->precomp == '^') {
+       if (!(pm->op_pmflags & PMf_MULTILINE)
+           && !(pm->op_pmregexp->reganch & ROPT_WARNED)) {
+           if (ckWARN(WARN_DEPRECATED))
+               Perl_warner(aTHX_ WARN_DEPRECATED,
+                           "split /^/ better written as split /^/m");
+           pm->op_pmregexp->reganch |= ROPT_WARNED;
+       }       
        while (--limit) {
            /*SUPPRESS 530*/
            for (m = s; m < strend && *m != '\n'; m++) ;
@@ -4998,17 +5035,19 @@ PP(pp_split)
            s = m;
        }
     }
-    else if (rx->check_substr && !rx->nparens
+    else if ((rx->reganch & RE_USE_INTUIT) && !rx->nparens
             && (rx->reganch & ROPT_CHECK_ALL)
             && !(rx->reganch & ROPT_ANCH)) {
-       int tail = SvTAIL(rx->check_substr) != 0;
+       int tail = (rx->reganch & RE_INTUIT_TAIL);
+       SV *csv = CALLREG_INTUIT_STRING(aTHX_ rx);
+       char c;
 
-       i = SvCUR(rx->check_substr);
-       if (i == 1 && !tail) {
-           i = *SvPVX(rx->check_substr);
+       len = rx->minlen;
+       if (len == 1 && !tail) {
+           c = *SvPV(csv,len);
            while (--limit) {
                /*SUPPRESS 530*/
-               for (m = s; m < strend && *m != i; m++) ;
+               for (m = s; m < strend && *m != c; m++) ;
                if (m >= strend)
                    break;
                dstr = NEWSV(30, m-s);
@@ -5022,8 +5061,8 @@ PP(pp_split)
        else {
 #ifndef lint
            while (s < strend && --limit &&
-             (m=fbm_instr((unsigned char*)s, (unsigned char*)strend,
-                   rx->check_substr, PL_multiline ? FBMrf_MULTILINE : 0)) )
+             (m = fbm_instr((unsigned char*)s, (unsigned char*)strend,
+                            csv, PL_multiline ? FBMrf_MULTILINE : 0)) )
 #endif
            {
                dstr = NEWSV(31, m-s);
@@ -5031,14 +5070,18 @@ PP(pp_split)
                if (make_mortal)
                    sv_2mortal(dstr);
                XPUSHs(dstr);
-               s = m + i - tail;       /* Fake \n at the end */
+               s = m + len;            /* Fake \n at the end */
            }
        }
     }
     else {
        maxiters += (strend - s) * rx->nparens;
-       while (s < strend && --limit &&
-              CALLREGEXEC(aTHX_ rx, s, strend, orig, 1, sv, NULL, 0))
+       while (s < strend && --limit
+/*            && (!rx->check_substr 
+                  || ((s = CALLREG_INTUIT_START(aTHX_ rx, sv, s, strend,
+                                                0, NULL))))
+*/            && CALLREGEXEC(aTHX_ rx, s, strend, orig,
+                             1 /* minend */, sv, NULL, 0))
        {
            TAINT_IF(RX_MATCH_TAINTED(rx));
            if (RX_MATCH_COPIED(rx) && rx->subbeg != orig) {
@@ -5178,7 +5221,7 @@ PP(pp_lock)
        DEBUG_S(PerlIO_printf(PerlIO_stderr(), "0x%lx: pp_lock lock 0x%lx\n",
                              (unsigned long)thr, (unsigned long)sv);)
        MUTEX_UNLOCK(MgMUTEXP(mg));
-       save_destructor(Perl_unlock_condpair, sv);
+       SAVEDESTRUCTOR(Perl_unlock_condpair, sv);
     }
 #endif /* USE_THREADS */
     if (SvTYPE(retsv) == SVt_PVAV || SvTYPE(retsv) == SVt_PVHV