Minor multi-threading patches for VMS.
[p5sagit/p5-mst-13.2.git] / hv.c
diff --git a/hv.c b/hv.c
index 3208b56..454ee23 100644 (file)
--- a/hv.c
+++ b/hv.c
@@ -1,6 +1,6 @@
 /*    hv.c
  *
- *    Copyright (c) 1991-1994, Larry Wall
+ *    Copyright (c) 1991-1997, 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.
@@ -100,6 +100,7 @@ I32 lval;
 
     if (SvRMAGICAL(hv)) {
        if (mg_find((SV*)hv,'P')) {
+           dTHR;
            sv = sv_newmortal();
            mg_copy((SV*)hv, sv, key, klen);
            Sv = sv;
@@ -135,9 +136,9 @@ I32 lval;
     if (HvNAME(hv) && strEQ(HvNAME(hv),ENV_HV_NAME)) {
       char *gotenv;
 
-      gotenv = my_getenv(key);
-      if (gotenv != NULL) {
+      if ((gotenv = ENV_getenv(key)) != Nullch) {
         sv = newSVpv(gotenv,strlen(gotenv));
+        SvTAINTED_on(sv);
         return hv_store(hv,key,klen,sv,hash);
       }
     }
@@ -177,7 +178,6 @@ register U32 hash;
            char *k;
            New(54, k, HEK_BASESIZE + sizeof(SV*), char);
            HeKEY_hek(&mh) = (HEK*)k;
-           HeKLEN(&mh) = HEf_SVKEY;    /* key will always hold an SV* */
        }
        HeSVKEY_set(&mh, keysv);
        HeVAL(&mh) = sv;
@@ -215,9 +215,9 @@ register U32 hash;
     if (HvNAME(hv) && strEQ(HvNAME(hv),ENV_HV_NAME)) {
       char *gotenv;
 
-      gotenv = my_getenv(key);
-      if (gotenv != NULL) {
+      if ((gotenv = ENV_getenv(key)) != Nullch) {
         sv = newSVpv(gotenv,strlen(gotenv));
+        SvTAINTED_on(sv);
         return hv_store_ent(hv,keysv,sv,hash);
       }
     }
@@ -316,8 +316,12 @@ register U32 hash;
 
     xhv = (XPVHV*)SvANY(hv);
     if (SvMAGICAL(hv)) {
+       bool save_taint = tainted;
+       if (tainting)
+           tainted = SvTAINTED(keysv);
        keysv = sv_2mortal(newSVsv(keysv));
        mg_copy((SV*)hv, val, (char*)keysv, HEf_SVKEY);
+       TAINT_IF(save_taint);
        if (!xhv->xhv_array
            && (SvMAGIC(hv)->mg_moremagic
                || (SvMAGIC(hv)->mg_type != 'E'
@@ -423,7 +427,7 @@ I32 flags;
        if (entry == xhv->xhv_eiter)
            HvLAZYDEL_on(hv);
        else
-           he_free(entry, HvSHAREKEYS(hv));
+           hv_free_ent(hv, entry);
        --xhv->xhv_keys;
        return sv;
     }
@@ -485,7 +489,7 @@ U32 hash;
        if (entry == xhv->xhv_eiter)
            HvLAZYDEL_on(hv);
        else
-           he_free(entry, HvSHAREKEYS(hv));
+           hv_free_ent(hv, entry);
        --xhv->xhv_keys;
        return sv;
     }
@@ -508,6 +512,7 @@ U32 klen;
 
     if (SvRMAGICAL(hv)) {
        if (mg_find((SV*)hv,'P')) {
+           dTHR;
            sv = sv_newmortal();
            mg_copy((SV*)hv, sv, key, klen); 
            magic_existspack(sv, mg_find(sv, 'p'));
@@ -552,6 +557,7 @@ U32 hash;
 
     if (SvRMAGICAL(hv)) {
        if (mg_find((SV*)hv,'P')) {
+           dTHR;               /* just for SvTRUE */
            sv = sv_newmortal();
            keysv = sv_2mortal(newSVsv(keysv));
            mg_copy((SV*)hv, sv, (char*)keysv, HEf_SVKEY); 
@@ -746,41 +752,45 @@ newHV()
 }
 
 void
-he_free(hent, shared)
-register HE *hent;
-I32 shared;
+hv_free_ent(hv, entry)
+HV *hv;
+register HE *entry;
 {
-    if (!hent)
+    if (!entry)
        return;
-    if (SvTYPE(HeVAL(hent)) == SVt_PVGV && GvCV(HeVAL(hent)))
-       sub_generation++;               /* May be deletion of method? */
-    SvREFCNT_dec(HeVAL(hent));
-    if (HeKLEN(hent) == HEf_SVKEY) {
-       SvREFCNT_dec(HeKEY_sv(hent));
-        Safefree(HeKEY_hek(hent));
-    } else if (shared)
-       unshare_hek(HeKEY_hek(hent));
+    if (isGV(HeVAL(entry)) && GvCVu(HeVAL(entry)) && HvNAME(hv))
+       sub_generation++;       /* may be deletion of method from stash */
+    SvREFCNT_dec(HeVAL(entry));
+    if (HeKLEN(entry) == HEf_SVKEY) {
+       SvREFCNT_dec(HeKEY_sv(entry));
+        Safefree(HeKEY_hek(entry));
+    }
+    else if (HvSHAREKEYS(hv))
+       unshare_hek(HeKEY_hek(entry));
     else
-       Safefree(HeKEY_hek(hent));
-    del_he(hent);
+       Safefree(HeKEY_hek(entry));
+    del_he(entry);
 }
 
 void
-he_delayfree(hent, shared)
-register HE *hent;
-I32 shared;
+hv_delayfree_ent(hv, entry)
+HV *hv;
+register HE *entry;
 {
-    if (!hent)
+    if (!entry)
        return;
-    sv_2mortal(HeVAL(hent));   /* free between statements */
-    if (HeKLEN(hent) == HEf_SVKEY) {
-       sv_2mortal(HeKEY_sv(hent));
-       Safefree(HeKEY_hek(hent));
-    } else if (shared)
-       unshare_hek(HeKEY_hek(hent));
+    if (isGV(HeVAL(entry)) && GvCVu(HeVAL(entry)) && HvNAME(hv))
+       sub_generation++;       /* may be deletion of method from stash */
+    sv_2mortal(HeVAL(entry));  /* free between statements */
+    if (HeKLEN(entry) == HEf_SVKEY) {
+       sv_2mortal(HeKEY_sv(entry));
+       Safefree(HeKEY_hek(entry));
+    }
+    else if (HvSHAREKEYS(hv))
+       unshare_hek(HeKEY_hek(entry));
     else
-       Safefree(HeKEY_hek(hent));
-    del_he(hent);
+       Safefree(HeKEY_hek(entry));
+    del_he(entry);
 }
 
 void
@@ -806,11 +816,10 @@ hfreeentries(hv)
 HV *hv;
 {
     register HE **array;
-    register HE *hent;
-    register HE *ohent = Null(HE*);
+    register HE *entry;
+    register HE *oentry = Null(HE*);
     I32 riter;
     I32 max;
-    I32 shared;
 
     if (!hv)
        return;
@@ -820,18 +829,17 @@ HV *hv;
     riter = 0;
     max = HvMAX(hv);
     array = HvARRAY(hv);
-    hent = array[0];
-    shared = HvSHAREKEYS(hv);
+    entry = array[0];
     for (;;) {
-       if (hent) {
-           ohent = hent;
-           hent = HeNEXT(hent);
-           he_free(ohent, shared);
+       if (entry) {
+           oentry = entry;
+           entry = HeNEXT(entry);
+           hv_free_ent(hv, oentry);
        }
-       if (!hent) {
+       if (!entry) {
            if (++riter > max)
                break;
-           hent = array[riter];
+           entry = array[riter];
        } 
     }
     (void)hv_iterinit(hv);
@@ -852,7 +860,7 @@ HV *hv;
        HvNAME(hv) = 0;
     }
     xhv->xhv_array = 0;
-    xhv->xhv_max = 7;          /* it's a normal associative array */
+    xhv->xhv_max = 7;          /* it's a normal hash */
     xhv->xhv_fill = 0;
     xhv->xhv_keys = 0;
 
@@ -864,14 +872,20 @@ I32
 hv_iterinit(hv)
 HV *hv;
 {
-    register XPVHV* xhv = (XPVHV*)SvANY(hv);
-    HE *entry = xhv->xhv_eiter;
+    register XPVHV* xhv;
+    HE *entry;
+
+    if (!hv)
+       croak("Bad hash");
+    xhv = (XPVHV*)SvANY(hv);
+    entry = xhv->xhv_eiter;
 #ifdef DYNAMIC_ENV_FETCH  /* set up %ENV for iteration */
-    if (HvNAME(hv) && strEQ(HvNAME(hv),ENV_HV_NAME)) prime_env_iter();
+    if (HvNAME(hv) && strEQ(HvNAME(hv), ENV_HV_NAME))
+       prime_env_iter();
 #endif
     if (entry && HvLAZYDEL(hv)) {      /* was deleted earlier? */
        HvLAZYDEL_off(hv);
-       he_free(entry, HvSHAREKEYS(hv));
+       hv_free_ent(hv, entry);
     }
     xhv->xhv_riter = -1;
     xhv->xhv_eiter = Null(HE*);
@@ -888,7 +902,7 @@ HV *hv;
     MAGIC* mg;
 
     if (!hv)
-       croak("Bad associative array");
+       croak("Bad hash");
     xhv = (XPVHV*)SvANY(hv);
     oldentry = entry = xhv->xhv_eiter;
 
@@ -911,6 +925,7 @@ HV *hv;
        }
        magic_nextpack((SV*) hv,mg,key);
         if (SvOK(key)) {
+           dTHR;               /* just for SvREFCNT_inc */
            /* force key to stay around until next time */
            HeSVKEY_set(entry, SvREFCNT_inc(key));
            return entry;               /* beware, hent_val is not set */
@@ -938,7 +953,7 @@ HV *hv;
 
     if (oldentry && HvLAZYDEL(hv)) {           /* was deleted earlier? */
        HvLAZYDEL_off(hv);
-       he_free(oldentry, HvSHAREKEYS(hv));
+       hv_free_ent(hv, oldentry);
     }
 
     xhv->xhv_eiter = entry;