This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
suppress scalar leak messages for known leaks (from
[perl5.git] / doop.c
diff --git a/doop.c b/doop.c
index 4e5866e..1b7d02d 100644 (file)
--- a/doop.c
+++ b/doop.c
  */
 
 #include "EXTERN.h"
+#define PERL_IN_DOOP_C
 #include "perl.h"
 
 #if !defined(NSIG) || defined(M_UNIX) || defined(M_XENIX)
 #include <signal.h>
 #endif
 
-#ifndef PERL_OBJECT
-static I32 do_trans_CC_simple _((SV *sv));
-static I32 do_trans_CC_count _((SV *sv));
-static I32 do_trans_CC_complex _((SV *sv));
-static I32 do_trans_UU_simple _((SV *sv));
-static I32 do_trans_UU_count _((SV *sv));
-static I32 do_trans_UU_complex _((SV *sv));
-static I32 do_trans_UC_simple _((SV *sv));
-static I32 do_trans_CU_simple _((SV *sv));
-static I32 do_trans_UC_trivial _((SV *sv));
-static I32 do_trans_CU_trivial _((SV *sv));
-#endif
-
 STATIC I32
-do_trans_CC_simple(SV *sv)
+S_do_trans_CC_simple(pTHX_ SV *sv)
 {
     dTHR;
     U8 *s;
@@ -44,7 +32,7 @@ do_trans_CC_simple(SV *sv)
 
     tbl = (short*)cPVOP->op_pv;
     if (!tbl)
-       croak("panic: do_trans");
+       Perl_croak(aTHX_ "panic: do_trans");
 
     s = (U8*)SvPV(sv, len);
     send = s + len;
@@ -62,7 +50,7 @@ do_trans_CC_simple(SV *sv)
 }
 
 STATIC I32
-do_trans_CC_count(SV *sv)
+S_do_trans_CC_count(pTHX_ SV *sv)
 {
     dTHR;
     U8 *s;
@@ -73,7 +61,7 @@ do_trans_CC_count(SV *sv)
 
     tbl = (short*)cPVOP->op_pv;
     if (!tbl)
-       croak("panic: do_trans");
+       Perl_croak(aTHX_ "panic: do_trans");
 
     s = (U8*)SvPV(sv, len);
     send = s + len;
@@ -88,7 +76,7 @@ do_trans_CC_count(SV *sv)
 }
 
 STATIC I32
-do_trans_CC_complex(SV *sv)
+S_do_trans_CC_complex(pTHX_ SV *sv)
 {
     dTHR;
     U8 *s;
@@ -101,7 +89,7 @@ do_trans_CC_complex(SV *sv)
 
     tbl = (short*)cPVOP->op_pv;
     if (!tbl)
-       croak("panic: do_trans");
+       Perl_croak(aTHX_ "panic: do_trans");
 
     s = (U8*)SvPV(sv, len);
     send = s + len;
@@ -145,7 +133,7 @@ do_trans_CC_complex(SV *sv)
 }
 
 STATIC I32
-do_trans_UU_simple(SV *sv)
+S_do_trans_UU_simple(pTHX_ SV *sv)
 {
     dTHR;
     U8 *s;
@@ -197,7 +185,7 @@ do_trans_UU_simple(SV *sv)
 }
 
 STATIC I32
-do_trans_UU_count(SV *sv)
+S_do_trans_UU_count(pTHX_ SV *sv)
 {
     dTHR;
     U8 *s;
@@ -224,7 +212,7 @@ do_trans_UU_count(SV *sv)
 }
 
 STATIC I32
-do_trans_UC_simple(SV *sv)
+S_do_trans_UC_simple(pTHX_ SV *sv)
 {
     dTHR;
     U8 *s;
@@ -277,7 +265,7 @@ do_trans_UC_simple(SV *sv)
 }
 
 STATIC I32
-do_trans_CU_simple(SV *sv)
+S_do_trans_CU_simple(pTHX_ SV *sv)
 {
     dTHR;
     U8 *s;
@@ -340,7 +328,7 @@ do_trans_CU_simple(SV *sv)
 /* utf-8 to latin-1 */
 
 STATIC I32
-do_trans_UC_trivial(SV *sv)
+S_do_trans_UC_trivial(pTHX_ SV *sv)
 {
     dTHR;
     U8 *s;
@@ -372,7 +360,7 @@ do_trans_UC_trivial(SV *sv)
 /* latin-1 to utf-8 */
 
 STATIC I32
-do_trans_CU_trivial(SV *sv)
+S_do_trans_CU_trivial(pTHX_ SV *sv)
 {
     dTHR;
     U8 *s;
@@ -406,7 +394,7 @@ do_trans_CU_trivial(SV *sv)
 }
 
 STATIC I32
-do_trans_UU_complex(SV *sv)
+S_do_trans_UU_complex(pTHX_ SV *sv)
 {
     dTHR;
     U8 *s;
@@ -591,13 +579,13 @@ do_trans_UU_complex(SV *sv)
 }
 
 I32
-do_trans(SV *sv)
+Perl_do_trans(pTHX_ SV *sv)
 {
     dTHR;
     STRLEN len;
 
     if (SvREADONLY(sv) && !(PL_op->op_private & OPpTRANS_IDENTICAL))
-       croak(PL_no_modify);
+       Perl_croak(aTHX_ PL_no_modify);
 
     (void)SvPV(sv, len);
     if (!len)
@@ -606,7 +594,7 @@ do_trans(SV *sv)
        (void)SvPV_force(sv, len);
     (void)SvPOK_only(sv);
 
-    DEBUG_t( deb("2.TBL\n"));
+    DEBUG_t( Perl_deb(aTHX_ "2.TBL\n"));
 
     switch (PL_op->op_private & 63) {
     case 0:
@@ -642,7 +630,7 @@ do_trans(SV *sv)
 }
 
 void
-do_join(register SV *sv, SV *del, register SV **mark, register SV **sp)
+Perl_do_join(pTHX_ register SV *sv, SV *del, register SV **mark, register SV **sp)
 {
     SV **oldmark = mark;
     register I32 items = sp - mark;
@@ -665,7 +653,7 @@ do_join(register SV *sv, SV *del, register SV **mark, register SV **sp)
        SvGROW(sv, len + 1);            /* so try to pre-extend */
 
        mark = oldmark;
-       items = sp - mark;;
+       items = sp - mark;
        ++mark;
     }
 
@@ -697,7 +685,7 @@ do_join(register SV *sv, SV *del, register SV **mark, register SV **sp)
 }
 
 void
-do_sprintf(SV *sv, I32 len, SV **sarg)
+Perl_do_sprintf(pTHX_ SV *sv, I32 len, SV **sarg)
 {
     STRLEN patlen;
     char *pat = SvPV(*sarg, patlen);
@@ -709,14 +697,146 @@ do_sprintf(SV *sv, I32 len, SV **sarg)
        SvTAINTED_on(sv);
 }
 
+UV
+Perl_do_vecget(pTHX_ SV *sv, I32 offset, I32 size)
+{
+    STRLEN srclen, len;
+    unsigned char *s = (unsigned char *) SvPV(sv, srclen);
+    UV retnum = 0;
+
+    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) {
+       if (size <= 8)
+           retnum = 0;
+       else {
+           offset >>= 3;       /* turn into byte offset */
+           if (size == 16) {
+               if (offset >= srclen)
+                   retnum = 0;
+               else
+                   retnum = (UV) s[offset] << 8;
+           }
+           else if (size == 32) {
+               if (offset >= srclen)
+                   retnum = 0;
+               else if (offset + 1 >= srclen)
+                   retnum =
+                       ((UV) s[offset    ] << 24);
+               else if (offset + 2 >= srclen)
+                   retnum =
+                       ((UV) s[offset    ] << 24) +
+                       ((UV) s[offset + 1] << 16);
+               else
+                   retnum =
+                       ((UV) s[offset    ] << 24) +
+                       ((UV) s[offset + 1] << 16) +
+                       (     s[offset + 2] <<  8);
+           }
+#ifdef HAS_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)
+       retnum = (s[offset >> 3] >> (offset & 7)) & ((1 << size) - 1);
+    else {
+       offset >>= 3;   /* turn into byte offset */
+       if (size == 8)
+           retnum = s[offset];
+       else if (size == 16)
+           retnum =
+               ((UV) s[offset] <<  8) +
+                     s[offset + 1];
+       else if (size == 32)
+           retnum =
+               ((UV) s[offset    ] << 24) +
+               ((UV) s[offset + 1] << 16) +
+               (     s[offset + 2] <<  8) +
+                     s[offset + 3];
+#ifdef HAS_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;
+}
+
 void
-do_vecset(SV *sv)
+Perl_do_vecset(pTHX_ SV *sv)
 {
     SV *targ = LvTARG(sv);
     register I32 offset;
     register I32 size;
     register unsigned char *s;
-    register unsigned long lval;
+    register UV lval;
     I32 mask;
     STRLEN targlen;
     STRLEN len;
@@ -724,11 +844,14 @@ do_vecset(SV *sv)
     if (!targ)
        return;
     s = (unsigned char*)SvPV_force(targ, targlen);
-    lval = U_L(SvNV(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");
     
-    len = (offset + size + 7) / 8;
+    offset *= size;                    /* turn into bit offset */
+    len = (offset + size + 7) / 8;     /* required number of bytes */
     if (len > targlen) {
        s = (unsigned char*)SvGROW(targ, len + 1);
        (void)memzero(s + targlen, len - targlen + 1);
@@ -739,29 +862,46 @@ do_vecset(SV *sv)
        mask = (1 << size) - 1;
        size = offset & 7;
        lval &= mask;
-       offset >>= 3;
+       offset >>= 3;                   /* turn into byte offset */
        s[offset] &= ~(mask << size);
        s[offset] |= lval << size;
     }
     else {
-       offset >>= 3;
+       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 HAS_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);
 }
 
 void
-do_chop(register SV *astr, register SV *sv)
+Perl_do_chop(pTHX_ register SV *astr, register SV *sv)
 {
     STRLEN len;
     char *s;
@@ -789,7 +929,7 @@ do_chop(register SV *astr, register SV *sv)
         return;
     }
     else if (SvREADONLY(sv))
-       croak(PL_no_modify);
+       Perl_croak(aTHX_ PL_no_modify);
     s = SvPV(sv, len);
     if (len && !SvPOK(sv))
        s = SvPV_force(sv, len);
@@ -800,8 +940,8 @@ do_chop(register SV *astr, register SV *sv)
            s = send - 1;
            while ((*s & 0xc0) == 0x80)
                --s;
-           if (UTF8SKIP(s) != send - s)
-               warn("Malformed UTF-8 character");
+           if (UTF8SKIP(s) != send - s && ckWARN_d(WARN_UTF8))
+               Perl_warner(aTHX_ WARN_UTF8, "Malformed UTF-8 character");
            sv_setpvn(astr, s, send - s);
            *s = '\0';
            SvCUR_set(sv, s - start);
@@ -824,7 +964,7 @@ do_chop(register SV *astr, register SV *sv)
 } 
 
 I32
-do_chomp(register SV *sv)
+Perl_do_chomp(pTHX_ register SV *sv)
 {
     dTHR;
     register I32 count;
@@ -858,7 +998,7 @@ do_chomp(register SV *sv)
         return count;
     }
     else if (SvREADONLY(sv))
-       croak(PL_no_modify);
+       Perl_croak(aTHX_ PL_no_modify);
     s = SvPV(sv, len);
     if (len && !SvPOKp(sv))
        s = SvPV_force(sv, len);
@@ -902,7 +1042,7 @@ do_chomp(register SV *sv)
 } 
 
 void
-do_vop(I32 optype, SV *sv, SV *left, SV *right)
+Perl_do_vop(pTHX_ I32 optype, SV *sv, SV *left, SV *right)
 {
     dTHR;      /* just for taint */
 #ifdef LIBERAL
@@ -1017,7 +1157,7 @@ do_vop(I32 optype, SV *sv, SV *left, SV *right)
 }
 
 OP *
-do_kv(ARGSproto)
+Perl_do_kv(pTHX)
 {
     djSP;
     HV *hv = (HV*)POPs;
@@ -1089,7 +1229,7 @@ do_kv(ARGSproto)
            PUTBACK;
            tmpstr = realhv ?
                     hv_iterval(hv,entry) : avhv_iterval((AV*)hv,entry);
-           DEBUG_H(sv_setpvf(tmpstr, "%lu%%%d=%lu",
+           DEBUG_H(Perl_sv_setpvf(aTHX_ tmpstr, "%lu%%%d=%lu",
                            (unsigned long)HeHASH(entry),
                            HvMAX(keys)+1,
                            (unsigned long)(HeHASH(entry) & HvMAX(keys))));