INSTALL patches
[p5sagit/p5-mst-13.2.git] / pp.c
diff --git a/pp.c b/pp.c
index 985a3ed..e6a2e11 100644 (file)
--- a/pp.c
+++ b/pp.c
@@ -1,6 +1,6 @@
 /*    pp.c
  *
- *    Copyright (c) 1991-1997, Larry Wall
+ *    Copyright (c) 1991-1999, Larry Wall
  *
  *    You may distribute under the terms of either the GNU General Public
  *    License or the Artistic License, as specified in the README file.
@@ -78,6 +78,13 @@ typedef unsigned UBW;
 #define SIZE16 2
 #define SIZE32 4
 
+/* CROSSCOMPILE and MULTIARCH are going to affect pp_pack() and pp_unpack().
+   --jhi Feb 1999 */
+
+#if SHORTSIZE != SIZE16 || LONGSIZE != SIZE32
+#   define PERL_NATINT_PACK
+#endif
+
 #if BYTEORDER > 0xFFFF && defined(_CRAY) && !defined(_CRAYMPP)
 #  if BYTEORDER == 0x12345678
 #    define OFF16(p)   (char*)(p)
@@ -441,7 +448,7 @@ PP(pp_prototype)
                    oa = oa >> 4;
                }
                str[n++] = '\0';
-               ret = sv_2mortal(newSVpv(str, n - 1));
+               ret = sv_2mortal(newSVpvn(str, n - 1));
            }
            else if (code)              /* Non-Overridable */
                goto set;
@@ -453,7 +460,7 @@ PP(pp_prototype)
     }
     cv = sv_2cv(TOPs, &stash, &gv, FALSE);
     if (cv && SvPOK(cv))
-       ret = sv_2mortal(newSVpv(SvPVX(cv), SvCUR(cv)));
+       ret = sv_2mortal(newSVpvn(SvPVX(cv), SvCUR(cv)));
   set:
     SETs(ret);
     RETURN;
@@ -505,6 +512,8 @@ refto(SV *sv)
            vivify_defelem(sv);
        if (!(sv = LvTARG(sv)))
            sv = &PL_sv_undef;
+       else
+           SvREFCNT_inc(sv);
     }
     else if (SvPADTMP(sv))
        sv = newSVsv(sv);
@@ -602,7 +611,7 @@ PP(pp_gelem)
        break;
     case 'N':
        if (strEQ(elem, "NAME"))
-           sv = newSVpv(GvNAME(gv), GvNAMELEN(gv));
+           sv = newSVpvn(GvNAME(gv), GvNAMELEN(gv));
        break;
     case 'P':
        if (strEQ(elem, "PACKAGE"))
@@ -785,15 +794,8 @@ PP(pp_undef)
     if (!sv)
        RETPUSHUNDEF;
 
-    if (SvTHINKFIRST(sv)) {
-       if (SvREADONLY(sv)) {
-           dTHR;
-           if (PL_curcop != &PL_compiling)
-               croak(PL_no_modify);
-       }
-       if (SvROK(sv))
-           sv_unref(sv);
-    }
+    if (SvTHINKFIRST(sv))
+       sv_force_normal(sv);
 
     switch (SvTYPE(sv)) {
     case SVt_NULL:
@@ -810,9 +812,12 @@ PP(pp_undef)
                 CvANON((CV*)sv) ? "(anonymous)" : GvENAME(CvGV((CV*)sv)));
        /* FALL THROUGH */
     case SVt_PVFM:
-       { GV* gv = (GV*)SvREFCNT_inc(CvGV((CV*)sv));
-         cv_undef((CV*)sv);
-         CvGV((CV*)sv) = gv; }   /* let user-undef'd sub keep its identity */
+       {
+           /* let user-undef'd sub keep its identity */
+           GV* gv = (GV*)SvREFCNT_inc(CvGV((CV*)sv));
+           cv_undef((CV*)sv);
+           CvGV((CV*)sv) = gv;
+       }
        break;
     case SVt_PVGV:
        if (SvFAKE(sv))
@@ -1030,12 +1035,6 @@ PP(pp_repeat)
        STRLEN len;
 
        tmpstr = POPs;
-       if (TARG == tmpstr && SvTHINKFIRST(tmpstr)) {
-           if (SvREADONLY(tmpstr) && PL_curcop != &PL_compiling)
-               DIE("Can't x= to readonly value");
-           if (SvROK(tmpstr))
-               sv_unref(tmpstr);
-       }
        SvSetSV(TARG, tmpstr);
        SvPV_force(TARG, len);
        if (count != 1) {
@@ -3174,7 +3173,7 @@ mul128(SV *sv, U8 m)
   U32             i = 0;
 
   if (!strnEQ(s, "0000", 4)) {  /* need to grow sv */
-    SV             *tmpNew = newSVpv("0000000000", 10);
+    SV             *tmpNew = newSVpvn("0000000000", 10);
 
     sv_catsv(tmpNew, sv);
     SvREFCNT_dec(sv);          /* free old sv */
@@ -3243,8 +3242,10 @@ PP(pp_unpack)
     register U32 culong;
     double cdouble;
     int commas = 0;
+#ifdef PERL_NATINT_PACK
     int natint;                /* native integer */
     int unatint;       /* unsigned native integer */
+#endif
 
     if (gimme != G_ARRAY) {            /* arrange to do first one only */
        /*SUPPRESS 530*/
@@ -3260,18 +3261,22 @@ PP(pp_unpack)
     while (pat < patend) {
       reparse:
        datumtype = *pat++ & 0xFF;
+#ifdef PERL_NATINT_PACK
        natint = 0;
+#endif
        if (isSPACE(datumtype))
            continue;
-       if (*pat == '_') {
+       if (*pat == '!') {
            char *natstr = "sSiIlL";
 
            if (strchr(natstr, datumtype)) {
+#ifdef PERL_NATINT_PACK
                natint = 1;
+#endif
                pat++;
            }
            else
-               croak("'_' allowed only after types %s", natstr);
+               croak("'!' allowed only after types %s", natstr);
        }
        if (pat >= patend)
            len = 1;
@@ -3517,10 +3522,15 @@ PP(pp_unpack)
            }
            break;
        case 's':
+#if SHORTSIZE == SIZE16
+           along = (strend - s) / SIZE16;
+#else
            along = (strend - s) / (natint ? sizeof(short) : SIZE16);
+#endif
            if (len > along)
                len = along;
            if (checksum) {
+#if SHORTSIZE != SIZE16
                if (natint) {
                    while (len-- > 0) {
                        COPYNN(s, &ashort, sizeof(short));
@@ -3529,9 +3539,15 @@ PP(pp_unpack)
 
                    }
                }
-               else {
+               else
+#endif
+                {
                    while (len-- > 0) {
                        COPY16(s, &ashort);
+#if SHORTSIZE > SIZE16
+                       if (ashort > 32767)
+                         ashort -= 65536;
+#endif
                        s += SIZE16;
                        culong += ashort;
                    }
@@ -3540,6 +3556,7 @@ PP(pp_unpack)
            else {
                EXTEND(SP, len);
                EXTEND_MORTAL(len);
+#if SHORTSIZE != SIZE16
                if (natint) {
                    while (len-- > 0) {
                        COPYNN(s, &ashort, sizeof(short));
@@ -3549,9 +3566,15 @@ PP(pp_unpack)
                        PUSHs(sv_2mortal(sv));
                    }
                }
-               else {
+               else
+#endif
+                {
                    while (len-- > 0) {
                        COPY16(s, &ashort);
+#if SHORTSIZE > SIZE16
+                       if (ashort > 32767)
+                         ashort -= 65536;
+#endif
                        s += SIZE16;
                        sv = NEWSV(38, 0);
                        sv_setiv(sv, (IV)ashort);
@@ -3563,11 +3586,16 @@ PP(pp_unpack)
        case 'v':
        case 'n':
        case 'S':
+#if SHORTSIZE == SIZE16
+           along = (strend - s) / SIZE16;
+#else
            unatint = natint && datumtype == 'S';
            along = (strend - s) / (unatint ? sizeof(unsigned short) : SIZE16);
+#endif
            if (len > along)
                len = along;
            if (checksum) {
+#if SHORTSIZE != SIZE16
                if (unatint) {
                    while (len-- > 0) {
                        COPYNN(s, &aushort, sizeof(unsigned short));
@@ -3575,7 +3603,9 @@ PP(pp_unpack)
                        culong += aushort;
                    }
                }
-               else {
+               else
+#endif
+                {
                    while (len-- > 0) {
                        COPY16(s, &aushort);
                        s += SIZE16;
@@ -3594,16 +3624,19 @@ PP(pp_unpack)
            else {
                EXTEND(SP, len);
                EXTEND_MORTAL(len);
+#if SHORTSIZE != SIZE16
                if (unatint) {
                    while (len-- > 0) {
                        COPYNN(s, &aushort, sizeof(unsigned short));
                        s += sizeof(unsigned short);
                        sv = NEWSV(39, 0);
-                       sv_setiv(sv, (IV)aushort);
+                       sv_setiv(sv, (UV)aushort);
                        PUSHs(sv_2mortal(sv));
                    }
                }
-               else {
+               else
+#endif
+                {
                    while (len-- > 0) {
                        COPY16(s, &aushort);
                        s += SIZE16;
@@ -3616,7 +3649,7 @@ PP(pp_unpack)
                        if (datumtype == 'v')
                            aushort = vtohs(aushort);
 #endif
-                       sv_setiv(sv, (IV)aushort);
+                       sv_setiv(sv, (UV)aushort);
                        PUSHs(sv_2mortal(sv));
                    }
                }
@@ -3646,7 +3679,25 @@ PP(pp_unpack)
 #ifdef __osf__
                     /* Without the dummy below unpack("i", pack("i",-1))
                      * return 0xFFffFFff instead of -1 for Digital Unix V4.0
-                     * cc with optimization turned on */
+                     * cc with optimization turned on.
+                    *
+                    * The bug was detected in
+                    * DEC C V5.8-009 on Digital UNIX V4.0 (Rev. 1091) (V4.0E)
+                    * with optimization (-O4) turned on.
+                    * DEC C V5.2-040 on Digital UNIX V4.0 (Rev. 564) (V4.0B)
+                    * does not have this problem even with -O4.
+                    *
+                    * This bug was reported as DECC_BUGS 1431
+                    * and tracked internally as GEM_BUGS 7775.
+                    *
+                    * The bug is fixed in
+                    * Tru64 UNIX V5.0:      Compaq C V6.1-006 or later
+                    * UNIX V4.0F support:   DEC C V5.9-006 or later
+                    * UNIX V4.0E support:   DEC C V5.8-011 or later
+                    * and also in DTK.
+                    *
+                    * See also few lines later for the same bug.
+                    */
                     (aint) ?
                        sv_setiv(sv, (IV)aint) :
 #endif
@@ -3678,12 +3729,8 @@ PP(pp_unpack)
                    sv = NEWSV(41, 0);
 #ifdef __osf__
                     /* Without the dummy below unpack("I", pack("I",0xFFFFFFFF))
-                     * returns 1.84467440737096e+19 instead of 0xFFFFFFFF for
-                    * DEC C V5.8-009 on Digital UNIX V4.0 (Rev. 1091) (aka V4.0D)
-                    * with optimization turned on.
-                    * (DEC C V5.2-040 on Digital UNIX V4.0 (Rev. 564) (aka V4.0B)
-                    * does not have this problem even with -O4)
-                    */
+                     * returns 1.84467440737096e+19 instead of 0xFFFFFFFF.
+                    * See details few lines earlier. */
                     (auint) ?
                        sv_setuv(sv, (UV)auint) :
 #endif
@@ -3693,10 +3740,15 @@ PP(pp_unpack)
            }
            break;
        case 'l':
+#if LONGSIZE == SIZE32
+           along = (strend - s) / SIZE32;
+#else
            along = (strend - s) / (natint ? sizeof(long) : SIZE32);
+#endif
            if (len > along)
                len = along;
            if (checksum) {
+#if LONGSIZE != SIZE32
                if (natint) {
                    while (len-- > 0) {
                        COPYNN(s, &along, sizeof(long));
@@ -3707,9 +3759,15 @@ PP(pp_unpack)
                            culong += along;
                    }
                }
-               else {
+               else
+#endif
+                {
                    while (len-- > 0) {
                        COPY32(s, &along);
+#if LONGSIZE > SIZE32
+                       if (along > 2147483647)
+                         along -= 4294967296;
+#endif
                        s += SIZE32;
                        if (checksum > 32)
                            cdouble += (double)along;
@@ -3721,6 +3779,7 @@ PP(pp_unpack)
            else {
                EXTEND(SP, len);
                EXTEND_MORTAL(len);
+#if LONGSIZE != SIZE32
                if (natint) {
                    while (len-- > 0) {
                        COPYNN(s, &along, sizeof(long));
@@ -3730,9 +3789,15 @@ PP(pp_unpack)
                        PUSHs(sv_2mortal(sv));
                    }
                }
-               else {
+               else
+#endif
+                {
                    while (len-- > 0) {
                        COPY32(s, &along);
+#if LONGSIZE > SIZE32
+                       if (along > 2147483647)
+                         along -= 4294967296;
+#endif
                        s += SIZE32;
                        sv = NEWSV(42, 0);
                        sv_setiv(sv, (IV)along);
@@ -3744,11 +3809,16 @@ PP(pp_unpack)
        case 'V':
        case 'N':
        case 'L':
-           unatint = natint && datumtype;
+#if LONGSIZE == SIZE32
+           along = (strend - s) / SIZE32;
+#else
+           unatint = natint && datumtype == 'L';
            along = (strend - s) / (unatint ? sizeof(unsigned long) : SIZE32);
+#endif
            if (len > along)
                len = along;
            if (checksum) {
+#if LONGSIZE != SIZE32
                if (unatint) {
                    while (len-- > 0) {
                        COPYNN(s, &aulong, sizeof(unsigned long));
@@ -3759,7 +3829,9 @@ PP(pp_unpack)
                            culong += aulong;
                    }
                }
-               else {
+               else
+#endif
+                {
                    while (len-- > 0) {
                        COPY32(s, &aulong);
                        s += SIZE32;
@@ -3781,6 +3853,7 @@ PP(pp_unpack)
            else {
                EXTEND(SP, len);
                EXTEND_MORTAL(len);
+#if LONGSIZE != SIZE32
                if (unatint) {
                    while (len-- > 0) {
                        COPYNN(s, &aulong, sizeof(unsigned long));
@@ -3790,7 +3863,9 @@ PP(pp_unpack)
                        PUSHs(sv_2mortal(sv));
                    }
                }
-               else {
+               else
+#endif
+                {
                    while (len-- > 0) {
                        COPY32(s, &aulong);
                        s += SIZE32;
@@ -4102,11 +4177,11 @@ doencodes(register SV *sv, register char *s, register I32 len)
     sv_catpvn(sv, "\n", 1);
 }
 
-STATIC SV      *
+STATIC SV *
 is_an_int(char *s, STRLEN l)
 {
   STRLEN        n_a;
-  SV             *result = newSVpv("", l);
+  SV             *result = newSVpvn(s, l);
   char           *result_c = SvPV(result, n_a);        /* convenience */
   char           *out = result_c;
   bool            skip = 1;
@@ -4210,7 +4285,9 @@ PP(pp_pack)
     float afloat;
     double adouble;
     int commas = 0;
+#ifdef PERL_NATINT_PACK
     int natint;                /* native integer */
+#endif
 
     items = SP - MARK;
     MARK++;
@@ -4218,18 +4295,22 @@ PP(pp_pack)
     while (pat < patend) {
 #define NEXTFROM (items-- > 0 ? *MARK++ : &PL_sv_no)
        datumtype = *pat++ & 0xFF;
+#ifdef PERL_NATINT_PACK
        natint = 0;
+#endif
        if (isSPACE(datumtype))
            continue;
-        if (*pat == '_') {
+        if (*pat == '!') {
            char *natstr = "sSiIlL";
 
            if (strchr(natstr, datumtype)) {
+#ifdef PERL_NATINT_PACK
                natint = 1;
+#endif
                pat++;
            }
            else
-               croak("'_' allowed only after types %s", natstr);
+               croak("'!' allowed only after types %s", natstr);
        }
        if (*pat == '*') {
            len = strchr("@Xxu", datumtype) ? 0 : items;
@@ -4475,6 +4556,7 @@ PP(pp_pack)
            }
            break;
        case 'S':
+#if SHORTSIZE != SIZE16
            if (natint) {
                unsigned short aushort;
 
@@ -4484,17 +4566,21 @@ PP(pp_pack)
                    sv_catpvn(cat, (char *)&aushort, sizeof(unsigned short));
                }
            }
-           else {
+           else
+#endif
+            {
                U16 aushort;
 
                while (len-- > 0) {
                    fromstr = NEXTFROM;
-                   aushort = (U16)SvIV(fromstr);
+                   aushort = (U16)SvUV(fromstr);
                    CAT16(cat, &aushort);
                }
+
            }
            break;
        case 's':
+#if SHORTSIZE != SIZE16
            if (natint) {
                while (len-- > 0) {
                    fromstr = NEXTFROM;
@@ -4502,7 +4588,9 @@ PP(pp_pack)
                    sv_catpvn(cat, (char *)&ashort, sizeof(short));
                }
            }
-           else {
+           else
+#endif
+            {
                while (len-- > 0) {
                    fromstr = NEXTFROM;
                    ashort = (I16)SvIV(fromstr);
@@ -4615,6 +4703,7 @@ PP(pp_pack)
            }
            break;
        case 'L':
+#if LONGSIZE != SIZE32
            if (natint) {
                while (len-- > 0) {
                    fromstr = NEXTFROM;
@@ -4622,7 +4711,9 @@ PP(pp_pack)
                    sv_catpvn(cat, (char *)&aulong, sizeof(unsigned long));
                }
            }
-           else {
+           else
+#endif
+            {
                while (len-- > 0) {
                    fromstr = NEXTFROM;
                    aulong = SvUV(fromstr);
@@ -4631,6 +4722,7 @@ PP(pp_pack)
            }
            break;
        case 'l':
+#if LONGSIZE != SIZE32
            if (natint) {
                while (len-- > 0) {
                    fromstr = NEXTFROM;
@@ -4638,7 +4730,9 @@ PP(pp_pack)
                    sv_catpvn(cat, (char *)&along, sizeof(long));
                }
            }
-           else {
+           else
+#endif
+            {
                while (len-- > 0) {
                    fromstr = NEXTFROM;
                    along = SvIV(fromstr);