per Larry's idea, parse 1.2.3 as v1.2.3; C<require 5.6.0> and
[p5sagit/p5-mst-13.2.git] / doop.c
diff --git a/doop.c b/doop.c
index b064838..34cc0e3 100644 (file)
--- a/doop.c
+++ b/doop.c
@@ -1,6 +1,6 @@
 /*    doop.c
  *
- *    Copyright (c) 1991-1999, Larry Wall
+ *    Copyright (c) 1991-2000, 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.
@@ -704,8 +704,10 @@ Perl_do_vecget(pTHX_ SV *sv, I32 offset, I32 size)
     unsigned char *s = (unsigned char *) SvPV(sv, srclen);
     UV retnum = 0;
 
-    if (offset < 0 || size < 1)
+    if (offset < 0)
        return retnum;
+    if (size < 1 || (size & (size-1))) /* size < 1 or not a power of two */ 
+       Perl_croak(aTHX_ "Illegal number of bits in vec");
     offset *= size;    /* turn into bit offset */
     len = (offset + size + 7) / 8;     /* required number of bytes */
     if (len > srclen) {
@@ -717,7 +719,7 @@ Perl_do_vecget(pTHX_ SV *sv, I32 offset, I32 size)
                if (offset >= srclen)
                    retnum = 0;
                else
-                   retnum = (UV) s[offset] << 8;
+                   retnum = (UV) s[offset] <<  8;
            }
            else if (size == 32) {
                if (offset >= srclen)
@@ -735,8 +737,58 @@ Perl_do_vecget(pTHX_ SV *sv, I32 offset, I32 size)
                        ((UV) s[offset + 1] << 16) +
                        (     s[offset + 2] <<  8);
            }
-           else
-               Perl_croak(aTHX_ "Illegal number of bits in vec");
+#ifdef UV_IS_QUAD
+           else if (size == 64) {
+               dTHR;
+               if (ckWARN(WARN_PORTABLE))
+                   Perl_warner(aTHX_ WARN_PORTABLE,
+                               "Bit vector size > 32 non-portable");
+               if (offset >= srclen)
+                   retnum = 0;
+               else if (offset + 1 >= srclen)
+                   retnum =
+                       (UV) s[offset     ] << 56;
+               else if (offset + 2 >= srclen)
+                   retnum =
+                       ((UV) s[offset    ] << 56) +
+                       ((UV) s[offset + 1] << 48);
+               else if (offset + 3 >= srclen)
+                   retnum =
+                       ((UV) s[offset    ] << 56) +
+                       ((UV) s[offset + 1] << 48) +
+                       ((UV) s[offset + 2] << 40);
+               else if (offset + 4 >= srclen)
+                   retnum =
+                       ((UV) s[offset    ] << 56) +
+                       ((UV) s[offset + 1] << 48) +
+                       ((UV) s[offset + 2] << 40) +
+                       ((UV) s[offset + 3] << 32);
+               else if (offset + 5 >= srclen)
+                   retnum =
+                       ((UV) s[offset    ] << 56) +
+                       ((UV) s[offset + 1] << 48) +
+                       ((UV) s[offset + 2] << 40) +
+                       ((UV) s[offset + 3] << 32) +
+                       (     s[offset + 4] << 24);
+               else if (offset + 6 >= srclen)
+                   retnum =
+                       ((UV) s[offset    ] << 56) +
+                       ((UV) s[offset + 1] << 48) +
+                       ((UV) s[offset + 2] << 40) +
+                       ((UV) s[offset + 3] << 32) +
+                       ((UV) s[offset + 4] << 24) +
+                       ((UV) s[offset + 5] << 16);
+               else
+                   retnum = 
+                       ((UV) s[offset    ] << 56) +
+                       ((UV) s[offset + 1] << 48) +
+                       ((UV) s[offset + 2] << 40) +
+                       ((UV) s[offset + 3] << 32) +
+                       ((UV) s[offset + 4] << 24) +
+                       ((UV) s[offset + 5] << 16) +
+                       (     s[offset + 6] <<  8);
+           }
+#endif
        }
     }
     else if (size < 8)
@@ -747,7 +799,7 @@ Perl_do_vecget(pTHX_ SV *sv, I32 offset, I32 size)
            retnum = s[offset];
        else if (size == 16)
            retnum =
-               ((UV) s[offset] <<  8) +
+               ((UV) s[offset] <<      8) +
                      s[offset + 1];
        else if (size == 32)
            retnum =
@@ -755,8 +807,23 @@ Perl_do_vecget(pTHX_ SV *sv, I32 offset, I32 size)
                ((UV) s[offset + 1] << 16) +
                (     s[offset + 2] <<  8) +
                      s[offset + 3];
-       else
-           Perl_croak(aTHX_ "Illegal number of bits in vec");
+#ifdef UV_IS_QUAD
+       else if (size == 64) {
+           dTHR;
+           if (ckWARN(WARN_PORTABLE))
+               Perl_warner(aTHX_ WARN_PORTABLE,
+                           "Bit vector size > 32 non-portable");
+           retnum =
+               ((UV) s[offset    ] << 56) +
+               ((UV) s[offset + 1] << 48) +
+               ((UV) s[offset + 2] << 40) +
+               ((UV) s[offset + 3] << 32) +
+               ((UV) s[offset + 4] << 24) +
+               ((UV) s[offset + 5] << 16) +
+               (     s[offset + 6] <<  8) +
+                     s[offset + 7];
+       }
+#endif
     }
 
     return retnum;
@@ -780,6 +847,8 @@ Perl_do_vecset(pTHX_ SV *sv)
     lval = SvUV(sv);
     offset = LvTARGOFF(sv);
     size = LvTARGLEN(sv);
+    if (size < 1 || (size & (size-1))) /* size < 1 or not a power of two */ 
+       Perl_croak(aTHX_ "Illegal number of bits in vec");
     
     offset *= size;                    /* turn into bit offset */
     len = (offset + size + 7) / 8;     /* required number of bytes */
@@ -800,17 +869,33 @@ Perl_do_vecset(pTHX_ SV *sv)
     else {
        offset >>= 3;                   /* turn into byte offset */
        if (size == 8)
-           s[offset] = lval & 255;
+           s[offset  ] = lval         & 0xff;
        else if (size == 16) {
-           s[offset] = (lval >> 8) & 255;
-           s[offset+1] = lval & 255;
+           s[offset  ] = (lval >>  8) & 0xff;
+           s[offset+1] = lval         & 0xff;
        }
        else if (size == 32) {
-           s[offset] = (lval >> 24) & 255;
-           s[offset+1] = (lval >> 16) & 255;
-           s[offset+2] = (lval >> 8) & 255;
-           s[offset+3] = lval & 255;
+           s[offset  ] = (lval >> 24) & 0xff;
+           s[offset+1] = (lval >> 16) & 0xff;
+           s[offset+2] = (lval >>  8) & 0xff;
+           s[offset+3] =  lval        & 0xff;
        }
+#ifdef UV_IS_QUAD
+       else if (size == 64) {
+           dTHR;
+           if (ckWARN(WARN_PORTABLE))
+               Perl_warner(aTHX_ WARN_PORTABLE,
+                           "Bit vector size > 32 non-portable");
+           s[offset  ] = (lval >> 56) & 0xff;
+           s[offset+1] = (lval >> 48) & 0xff;
+           s[offset+2] = (lval >> 40) & 0xff;
+           s[offset+3] = (lval >> 32) & 0xff;
+           s[offset+4] = (lval >> 24) & 0xff;
+           s[offset+5] = (lval >> 16) & 0xff;
+           s[offset+6] = (lval >>  8) & 0xff;
+           s[offset+7] =  lval        & 0xff;
+       }
+#endif
     }
     SvSETMAGIC(targ);
 }
@@ -848,7 +933,7 @@ Perl_do_chop(pTHX_ register SV *astr, register SV *sv)
     s = SvPV(sv, len);
     if (len && !SvPOK(sv))
        s = SvPV_force(sv, len);
-    if (IN_UTF8) {
+    if (DO_UTF8(sv)) {
        if (s && len) {
            char *send = s + len;
            char *start = s;
@@ -861,22 +946,23 @@ Perl_do_chop(pTHX_ register SV *astr, register SV *sv)
            *s = '\0';
            SvCUR_set(sv, s - start);
            SvNIOK_off(sv);
+           SvUTF8_on(astr);
        }
        else
            sv_setpvn(astr, "", 0);
     }
-    else
-    if (s && len) {
+    else if (s && len) {
        s += --len;
        sv_setpvn(astr, s, 1);
        *s = '\0';
        SvCUR_set(sv, len);
+       SvUTF8_off(sv);
        SvNIOK_off(sv);
     }
     else
        sv_setpvn(astr, "", 0);
     SvSETMAGIC(sv);
-} 
+}
 
 I32
 Perl_do_chomp(pTHX_ register SV *sv)