applied patch, with indentation tweaks
[p5sagit/p5-mst-13.2.git] / mg.c
diff --git a/mg.c b/mg.c
index 902a853..b981c12 100644 (file)
--- a/mg.c
+++ b/mg.c
@@ -478,7 +478,8 @@ magic_get(SV *sv, MAGIC *mg)
                    }
                    sv_setpvn(sv,s,i);
                    if (tainting)
-                       tainted = was_tainted || RX_MATCH_TAINTED(rx);
+                       tainted = (was_tainted || RX_MATCH_TAINTED(rx) ||
+                                  (curpm->op_pmflags & PMf_TAINTMEM));
                    break;
                }
            }
@@ -963,11 +964,33 @@ magic_setamagic(SV *sv, MAGIC *mg)
 #endif /* OVERLOAD */
 
 int
+magic_getnkeys(SV *sv, MAGIC *mg)
+{
+    HV *hv = (HV*)LvTARG(sv);
+    HE *entry;
+    I32 i = 0;
+
+    if (hv) {
+       (void) hv_iterinit(hv);
+       if (!SvRMAGICAL(hv) || !mg_find((SV*)hv,'P'))
+           i = HvKEYS(hv);
+       else {
+           /*SUPPRESS 560*/
+           while (entry = hv_iternext(hv)) {
+               i++;
+           }
+       }
+    }
+
+    sv_setiv(sv, (IV)i);
+    return 0;
+}
+
+int
 magic_setnkeys(SV *sv, MAGIC *mg)
 {
     if (LvTARG(sv)) {
        hv_ksplit((HV*)LvTARG(sv), SvIV(sv));
-       LvTARG(sv) = Nullsv;    /* Don't allow a ref to reassign this. */
     }
     return 0;
 }          
@@ -1236,6 +1259,23 @@ magic_setglob(SV *sv, MAGIC *mg)
 }
 
 int
+magic_getsubstr(SV *sv, MAGIC *mg)
+{
+    STRLEN len;
+    SV *lsv = LvTARG(sv);
+    char *tmps = SvPV(lsv,len);
+    I32 offs = LvTARGOFF(sv);
+    I32 rem = LvTARGLEN(sv);
+
+    if (offs > len)
+       offs = len;
+    if (rem + offs > len)
+       rem = len - offs;
+    sv_setpvn(sv, tmps + offs, (STRLEN)rem);
+    return 0;
+}
+
+int
 magic_setsubstr(SV *sv, MAGIC *mg)
 {
     STRLEN len;
@@ -1271,6 +1311,72 @@ magic_settaint(SV *sv, MAGIC *mg)
 }
 
 int
+magic_getvec(SV *sv, MAGIC *mg)
+{
+    SV *lsv = LvTARG(sv);
+    unsigned char *s;
+    unsigned long retnum;
+    STRLEN lsvlen;
+    I32 len;
+    I32 offset;
+    I32 size;
+
+    if (!lsv) {
+       SvOK_off(sv);
+       return 0;
+    }
+    s = (unsigned char *) SvPV(lsv, lsvlen);
+    offset = LvTARGOFF(sv);
+    size = LvTARGLEN(sv);
+    len = (offset + size + 7) / 8;
+
+    /* Copied from pp_vec() */
+
+    if (len > lsvlen) {
+       if (size <= 8)
+           retnum = 0;
+       else {
+           offset >>= 3;
+           if (size == 16) {
+               if (offset >= lsvlen)
+                   retnum = 0;
+               else
+                   retnum = (unsigned long) s[offset] << 8;
+           }
+           else if (size == 32) {
+               if (offset >= lsvlen)
+                   retnum = 0;
+               else if (offset + 1 >= lsvlen)
+                   retnum = (unsigned long) s[offset] << 24;
+               else if (offset + 2 >= lsvlen)
+                   retnum = ((unsigned long) s[offset] << 24) +
+                       ((unsigned long) s[offset + 1] << 16);
+               else
+                   retnum = ((unsigned long) s[offset] << 24) +
+                       ((unsigned long) s[offset + 1] << 16) +
+                       (s[offset + 2] << 8);
+           }
+       }
+    }
+    else if (size < 8)
+       retnum = (s[offset >> 3] >> (offset & 7)) & ((1 << size) - 1);
+    else {
+       offset >>= 3;
+       if (size == 8)
+           retnum = s[offset];
+       else if (size == 16)
+           retnum = ((unsigned long) s[offset] << 8) + s[offset+1];
+       else if (size == 32)
+           retnum = ((unsigned long) s[offset] << 24) +
+               ((unsigned long) s[offset + 1] << 16) +
+               (s[offset + 2] << 8) + s[offset+3];
+    }
+
+    sv_setuv(sv, (UV)retnum);
+    return 0;
+}
+
+int
 magic_setvec(SV *sv, MAGIC *mg)
 {
     do_vecset(sv);     /* XXX slurp this routine */
@@ -1289,7 +1395,7 @@ magic_getdefelem(SV *sv, MAGIC *mg)
                targ = HeVAL(he);
        }
        else {
-           AV* av = (AV*)LvTARG(sv); 
+           AV* av = (AV*)LvTARG(sv);
            if ((I32)LvTARGOFF(sv) <= AvFILL(av))
                targ = AvARRAY(av)[LvTARGOFF(sv)];
        }
@@ -1405,6 +1511,13 @@ magic_freeregexp(SV *sv, MAGIC *mg)
     return 0;
 }
 
+int
+magic_unchain(SV *sv, MAGIC *mg)
+{
+    sv_unmagic(sv, mg->mg_type);
+    return 0;
+}
+
 #ifdef USE_LOCALE_COLLATE
 int
 magic_setcollxfrm(SV *sv, MAGIC *mg)