X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=hv.c;h=50ff060e366ec382634b96669c4f168695859c30;hb=db173bac9b6de7d701a38c2f8b62f2fce229ec77;hp=3208b56651074536c8f368aaaca7f3530c5f2825;hpb=7a4c00b4303a05a04564a03a88f4fa5c7a06a6e9;p=p5sagit%2Fp5-mst-13.2.git diff --git a/hv.c b/hv.c index 3208b56..50ff060 100644 --- 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); @@ -612,9 +618,9 @@ HV *hv; assert(tmp >= newsize); New(2,a, tmp, HE*); Copy(xhv->xhv_array, a, oldsize, HE*); - if (oldsize >= 64 && !nice_chunk) { - nice_chunk = (char*)xhv->xhv_array; - nice_chunk_size = oldsize * sizeof(HE*) * 2 - MALLOC_OVERHEAD; + if (oldsize >= 64) { + offer_nice_chunk(xhv->xhv_array, + oldsize * sizeof(HE*) * 2 - MALLOC_OVERHEAD); } else Safefree(xhv->xhv_array); @@ -686,9 +692,9 @@ IV newmax; assert(j >= newsize); New(2, a, j, HE*); Copy(xhv->xhv_array, a, oldsize, HE*); - if (oldsize >= 64 && !nice_chunk) { - nice_chunk = (char*)xhv->xhv_array; - nice_chunk_size = oldsize * sizeof(HE*) * 2 - MALLOC_OVERHEAD; + if (oldsize >= 64) { + offer_nice_chunk(xhv->xhv_array, + oldsize * sizeof(HE*) * 2 - MALLOC_OVERHEAD); } else Safefree(xhv->xhv_array); @@ -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,18 +872,24 @@ 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*); - return xhv->xhv_fill; + return xhv->xhv_fill; /* should be xhv->xhv_keys? May change later */ } 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; @@ -951,7 +966,10 @@ register HE *entry; I32 *retlen; { if (HeKLEN(entry) == HEf_SVKEY) { - return SvPV(HeKEY_sv(entry), *(STRLEN*)retlen); + STRLEN len; + char *p = SvPV(HeKEY_sv(entry), len); + *retlen = len; + return p; } else { *retlen = HeKLEN(entry);