diff options
Diffstat (limited to 'contrib/perl5/sv.c')
-rw-r--r-- | contrib/perl5/sv.c | 8413 |
1 files changed, 0 insertions, 8413 deletions
diff --git a/contrib/perl5/sv.c b/contrib/perl5/sv.c deleted file mode 100644 index 7b8263b..0000000 --- a/contrib/perl5/sv.c +++ /dev/null @@ -1,8413 +0,0 @@ -/* sv.c - * - * Copyright (c) 1991-2001, 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. - * - */ - -/* - * "I wonder what the Entish is for 'yes' and 'no'," he thought. - */ - -#include "EXTERN.h" -#define PERL_IN_SV_C -#include "perl.h" - -#define FCALL *f -#define SV_CHECK_THINKFIRST(sv) if (SvTHINKFIRST(sv)) sv_force_normal(sv) - -static void do_report_used(pTHXo_ SV *sv); -static void do_clean_objs(pTHXo_ SV *sv); -#ifndef DISABLE_DESTRUCTOR_KLUDGE -static void do_clean_named_objs(pTHXo_ SV *sv); -#endif -static void do_clean_all(pTHXo_ SV *sv); - -/* - * "A time to plant, and a time to uproot what was planted..." - */ - -#define plant_SV(p) \ - STMT_START { \ - SvANY(p) = (void *)PL_sv_root; \ - SvFLAGS(p) = SVTYPEMASK; \ - PL_sv_root = (p); \ - --PL_sv_count; \ - } STMT_END - -/* sv_mutex must be held while calling uproot_SV() */ -#define uproot_SV(p) \ - STMT_START { \ - (p) = PL_sv_root; \ - PL_sv_root = (SV*)SvANY(p); \ - ++PL_sv_count; \ - } STMT_END - -#define new_SV(p) \ - STMT_START { \ - LOCK_SV_MUTEX; \ - if (PL_sv_root) \ - uproot_SV(p); \ - else \ - (p) = more_sv(); \ - UNLOCK_SV_MUTEX; \ - SvANY(p) = 0; \ - SvREFCNT(p) = 1; \ - SvFLAGS(p) = 0; \ - } STMT_END - -#ifdef DEBUGGING - -#define del_SV(p) \ - STMT_START { \ - LOCK_SV_MUTEX; \ - if (PL_debug & 32768) \ - del_sv(p); \ - else \ - plant_SV(p); \ - UNLOCK_SV_MUTEX; \ - } STMT_END - -STATIC void -S_del_sv(pTHX_ SV *p) -{ - if (PL_debug & 32768) { - SV* sva; - SV* sv; - SV* svend; - int ok = 0; - for (sva = PL_sv_arenaroot; sva; sva = (SV *) SvANY(sva)) { - sv = sva + 1; - svend = &sva[SvREFCNT(sva)]; - if (p >= sv && p < svend) - ok = 1; - } - if (!ok) { - if (ckWARN_d(WARN_INTERNAL)) - Perl_warner(aTHX_ WARN_INTERNAL, - "Attempt to free non-arena SV: 0x%"UVxf, - PTR2UV(p)); - return; - } - } - plant_SV(p); -} - -#else /* ! DEBUGGING */ - -#define del_SV(p) plant_SV(p) - -#endif /* DEBUGGING */ - -void -Perl_sv_add_arena(pTHX_ char *ptr, U32 size, U32 flags) -{ - SV* sva = (SV*)ptr; - register SV* sv; - register SV* svend; - Zero(ptr, size, char); - - /* The first SV in an arena isn't an SV. */ - SvANY(sva) = (void *) PL_sv_arenaroot; /* ptr to next arena */ - SvREFCNT(sva) = size / sizeof(SV); /* number of SV slots */ - SvFLAGS(sva) = flags; /* FAKE if not to be freed */ - - PL_sv_arenaroot = sva; - PL_sv_root = sva + 1; - - svend = &sva[SvREFCNT(sva) - 1]; - sv = sva + 1; - while (sv < svend) { - SvANY(sv) = (void *)(SV*)(sv + 1); - SvFLAGS(sv) = SVTYPEMASK; - sv++; - } - SvANY(sv) = 0; - SvFLAGS(sv) = SVTYPEMASK; -} - -/* sv_mutex must be held while calling more_sv() */ -STATIC SV* -S_more_sv(pTHX) -{ - register SV* sv; - - if (PL_nice_chunk) { - sv_add_arena(PL_nice_chunk, PL_nice_chunk_size, 0); - PL_nice_chunk = Nullch; - } - else { - char *chunk; /* must use New here to match call to */ - New(704,chunk,1008,char); /* Safefree() in sv_free_arenas() */ - sv_add_arena(chunk, 1008, 0); - } - uproot_SV(sv); - return sv; -} - -STATIC I32 -S_visit(pTHX_ SVFUNC_t f) -{ - SV* sva; - SV* sv; - register SV* svend; - I32 visited = 0; - - for (sva = PL_sv_arenaroot; sva; sva = (SV*)SvANY(sva)) { - svend = &sva[SvREFCNT(sva)]; - for (sv = sva + 1; sv < svend; ++sv) { - if (SvTYPE(sv) != SVTYPEMASK && SvREFCNT(sv)) { - (FCALL)(aTHXo_ sv); - ++visited; - } - } - } - return visited; -} - -void -Perl_sv_report_used(pTHX) -{ - visit(do_report_used); -} - -void -Perl_sv_clean_objs(pTHX) -{ - PL_in_clean_objs = TRUE; - visit(do_clean_objs); -#ifndef DISABLE_DESTRUCTOR_KLUDGE - /* some barnacles may yet remain, clinging to typeglobs */ - visit(do_clean_named_objs); -#endif - PL_in_clean_objs = FALSE; -} - -I32 -Perl_sv_clean_all(pTHX) -{ - I32 cleaned; - PL_in_clean_all = TRUE; - cleaned = visit(do_clean_all); - PL_in_clean_all = FALSE; - return cleaned; -} - -void -Perl_sv_free_arenas(pTHX) -{ - SV* sva; - SV* svanext; - XPV *arena, *arenanext; - - /* Free arenas here, but be careful about fake ones. (We assume - contiguity of the fake ones with the corresponding real ones.) */ - - for (sva = PL_sv_arenaroot; sva; sva = svanext) { - svanext = (SV*) SvANY(sva); - while (svanext && SvFAKE(svanext)) - svanext = (SV*) SvANY(svanext); - - if (!SvFAKE(sva)) - Safefree((void *)sva); - } - - for (arena = PL_xiv_arenaroot; arena; arena = arenanext) { - arenanext = (XPV*)arena->xpv_pv; - Safefree(arena); - } - PL_xiv_arenaroot = 0; - - for (arena = PL_xnv_arenaroot; arena; arena = arenanext) { - arenanext = (XPV*)arena->xpv_pv; - Safefree(arena); - } - PL_xnv_arenaroot = 0; - - for (arena = PL_xrv_arenaroot; arena; arena = arenanext) { - arenanext = (XPV*)arena->xpv_pv; - Safefree(arena); - } - PL_xrv_arenaroot = 0; - - for (arena = PL_xpv_arenaroot; arena; arena = arenanext) { - arenanext = (XPV*)arena->xpv_pv; - Safefree(arena); - } - PL_xpv_arenaroot = 0; - - for (arena = (XPV*)PL_xpviv_arenaroot; arena; arena = arenanext) { - arenanext = (XPV*)arena->xpv_pv; - Safefree(arena); - } - PL_xpviv_arenaroot = 0; - - for (arena = (XPV*)PL_xpvnv_arenaroot; arena; arena = arenanext) { - arenanext = (XPV*)arena->xpv_pv; - Safefree(arena); - } - PL_xpvnv_arenaroot = 0; - - for (arena = (XPV*)PL_xpvcv_arenaroot; arena; arena = arenanext) { - arenanext = (XPV*)arena->xpv_pv; - Safefree(arena); - } - PL_xpvcv_arenaroot = 0; - - for (arena = (XPV*)PL_xpvav_arenaroot; arena; arena = arenanext) { - arenanext = (XPV*)arena->xpv_pv; - Safefree(arena); - } - PL_xpvav_arenaroot = 0; - - for (arena = (XPV*)PL_xpvhv_arenaroot; arena; arena = arenanext) { - arenanext = (XPV*)arena->xpv_pv; - Safefree(arena); - } - PL_xpvhv_arenaroot = 0; - - for (arena = (XPV*)PL_xpvmg_arenaroot; arena; arena = arenanext) { - arenanext = (XPV*)arena->xpv_pv; - Safefree(arena); - } - PL_xpvmg_arenaroot = 0; - - for (arena = (XPV*)PL_xpvlv_arenaroot; arena; arena = arenanext) { - arenanext = (XPV*)arena->xpv_pv; - Safefree(arena); - } - PL_xpvlv_arenaroot = 0; - - for (arena = (XPV*)PL_xpvbm_arenaroot; arena; arena = arenanext) { - arenanext = (XPV*)arena->xpv_pv; - Safefree(arena); - } - PL_xpvbm_arenaroot = 0; - - for (arena = (XPV*)PL_he_arenaroot; arena; arena = arenanext) { - arenanext = (XPV*)arena->xpv_pv; - Safefree(arena); - } - PL_he_arenaroot = 0; - - if (PL_nice_chunk) - Safefree(PL_nice_chunk); - PL_nice_chunk = Nullch; - PL_nice_chunk_size = 0; - PL_sv_arenaroot = 0; - PL_sv_root = 0; -} - -void -Perl_report_uninit(pTHX) -{ - if (PL_op) - Perl_warner(aTHX_ WARN_UNINITIALIZED, PL_warn_uninit, - " in ", PL_op_desc[PL_op->op_type]); - else - Perl_warner(aTHX_ WARN_UNINITIALIZED, PL_warn_uninit, "", ""); -} - -STATIC XPVIV* -S_new_xiv(pTHX) -{ - IV* xiv; - LOCK_SV_MUTEX; - if (!PL_xiv_root) - more_xiv(); - xiv = PL_xiv_root; - /* - * See comment in more_xiv() -- RAM. - */ - PL_xiv_root = *(IV**)xiv; - UNLOCK_SV_MUTEX; - return (XPVIV*)((char*)xiv - STRUCT_OFFSET(XPVIV, xiv_iv)); -} - -STATIC void -S_del_xiv(pTHX_ XPVIV *p) -{ - IV* xiv = (IV*)((char*)(p) + STRUCT_OFFSET(XPVIV, xiv_iv)); - LOCK_SV_MUTEX; - *(IV**)xiv = PL_xiv_root; - PL_xiv_root = xiv; - UNLOCK_SV_MUTEX; -} - -STATIC void -S_more_xiv(pTHX) -{ - register IV* xiv; - register IV* xivend; - XPV* ptr; - New(705, ptr, 1008/sizeof(XPV), XPV); - ptr->xpv_pv = (char*)PL_xiv_arenaroot; /* linked list of xiv arenas */ - PL_xiv_arenaroot = ptr; /* to keep Purify happy */ - - xiv = (IV*) ptr; - xivend = &xiv[1008 / sizeof(IV) - 1]; - xiv += (sizeof(XPV) - 1) / sizeof(IV) + 1; /* fudge by size of XPV */ - PL_xiv_root = xiv; - while (xiv < xivend) { - *(IV**)xiv = (IV *)(xiv + 1); - xiv++; - } - *(IV**)xiv = 0; -} - -STATIC XPVNV* -S_new_xnv(pTHX) -{ - NV* xnv; - LOCK_SV_MUTEX; - if (!PL_xnv_root) - more_xnv(); - xnv = PL_xnv_root; - PL_xnv_root = *(NV**)xnv; - UNLOCK_SV_MUTEX; - return (XPVNV*)((char*)xnv - STRUCT_OFFSET(XPVNV, xnv_nv)); -} - -STATIC void -S_del_xnv(pTHX_ XPVNV *p) -{ - NV* xnv = (NV*)((char*)(p) + STRUCT_OFFSET(XPVNV, xnv_nv)); - LOCK_SV_MUTEX; - *(NV**)xnv = PL_xnv_root; - PL_xnv_root = xnv; - UNLOCK_SV_MUTEX; -} - -STATIC void -S_more_xnv(pTHX) -{ - register NV* xnv; - register NV* xnvend; - XPV *ptr; - New(711, ptr, 1008/sizeof(XPV), XPV); - ptr->xpv_pv = (char*)PL_xnv_arenaroot; - PL_xnv_arenaroot = ptr; - - xnv = (NV*) ptr; - xnvend = &xnv[1008 / sizeof(NV) - 1]; - xnv += (sizeof(XPVIV) - 1) / sizeof(NV) + 1; /* fudge by sizeof XPVIV */ - PL_xnv_root = xnv; - while (xnv < xnvend) { - *(NV**)xnv = (NV*)(xnv + 1); - xnv++; - } - *(NV**)xnv = 0; -} - -STATIC XRV* -S_new_xrv(pTHX) -{ - XRV* xrv; - LOCK_SV_MUTEX; - if (!PL_xrv_root) - more_xrv(); - xrv = PL_xrv_root; - PL_xrv_root = (XRV*)xrv->xrv_rv; - UNLOCK_SV_MUTEX; - return xrv; -} - -STATIC void -S_del_xrv(pTHX_ XRV *p) -{ - LOCK_SV_MUTEX; - p->xrv_rv = (SV*)PL_xrv_root; - PL_xrv_root = p; - UNLOCK_SV_MUTEX; -} - -STATIC void -S_more_xrv(pTHX) -{ - register XRV* xrv; - register XRV* xrvend; - XPV *ptr; - New(712, ptr, 1008/sizeof(XPV), XPV); - ptr->xpv_pv = (char*)PL_xrv_arenaroot; - PL_xrv_arenaroot = ptr; - - xrv = (XRV*) ptr; - xrvend = &xrv[1008 / sizeof(XRV) - 1]; - xrv += (sizeof(XPV) - 1) / sizeof(XRV) + 1; - PL_xrv_root = xrv; - while (xrv < xrvend) { - xrv->xrv_rv = (SV*)(xrv + 1); - xrv++; - } - xrv->xrv_rv = 0; -} - -STATIC XPV* -S_new_xpv(pTHX) -{ - XPV* xpv; - LOCK_SV_MUTEX; - if (!PL_xpv_root) - more_xpv(); - xpv = PL_xpv_root; - PL_xpv_root = (XPV*)xpv->xpv_pv; - UNLOCK_SV_MUTEX; - return xpv; -} - -STATIC void -S_del_xpv(pTHX_ XPV *p) -{ - LOCK_SV_MUTEX; - p->xpv_pv = (char*)PL_xpv_root; - PL_xpv_root = p; - UNLOCK_SV_MUTEX; -} - -STATIC void -S_more_xpv(pTHX) -{ - register XPV* xpv; - register XPV* xpvend; - New(713, xpv, 1008/sizeof(XPV), XPV); - xpv->xpv_pv = (char*)PL_xpv_arenaroot; - PL_xpv_arenaroot = xpv; - - xpvend = &xpv[1008 / sizeof(XPV) - 1]; - PL_xpv_root = ++xpv; - while (xpv < xpvend) { - xpv->xpv_pv = (char*)(xpv + 1); - xpv++; - } - xpv->xpv_pv = 0; -} - -STATIC XPVIV* -S_new_xpviv(pTHX) -{ - XPVIV* xpviv; - LOCK_SV_MUTEX; - if (!PL_xpviv_root) - more_xpviv(); - xpviv = PL_xpviv_root; - PL_xpviv_root = (XPVIV*)xpviv->xpv_pv; - UNLOCK_SV_MUTEX; - return xpviv; -} - -STATIC void -S_del_xpviv(pTHX_ XPVIV *p) -{ - LOCK_SV_MUTEX; - p->xpv_pv = (char*)PL_xpviv_root; - PL_xpviv_root = p; - UNLOCK_SV_MUTEX; -} - -STATIC void -S_more_xpviv(pTHX) -{ - register XPVIV* xpviv; - register XPVIV* xpvivend; - New(714, xpviv, 1008/sizeof(XPVIV), XPVIV); - xpviv->xpv_pv = (char*)PL_xpviv_arenaroot; - PL_xpviv_arenaroot = xpviv; - - xpvivend = &xpviv[1008 / sizeof(XPVIV) - 1]; - PL_xpviv_root = ++xpviv; - while (xpviv < xpvivend) { - xpviv->xpv_pv = (char*)(xpviv + 1); - xpviv++; - } - xpviv->xpv_pv = 0; -} - -STATIC XPVNV* -S_new_xpvnv(pTHX) -{ - XPVNV* xpvnv; - LOCK_SV_MUTEX; - if (!PL_xpvnv_root) - more_xpvnv(); - xpvnv = PL_xpvnv_root; - PL_xpvnv_root = (XPVNV*)xpvnv->xpv_pv; - UNLOCK_SV_MUTEX; - return xpvnv; -} - -STATIC void -S_del_xpvnv(pTHX_ XPVNV *p) -{ - LOCK_SV_MUTEX; - p->xpv_pv = (char*)PL_xpvnv_root; - PL_xpvnv_root = p; - UNLOCK_SV_MUTEX; -} - -STATIC void -S_more_xpvnv(pTHX) -{ - register XPVNV* xpvnv; - register XPVNV* xpvnvend; - New(715, xpvnv, 1008/sizeof(XPVNV), XPVNV); - xpvnv->xpv_pv = (char*)PL_xpvnv_arenaroot; - PL_xpvnv_arenaroot = xpvnv; - - xpvnvend = &xpvnv[1008 / sizeof(XPVNV) - 1]; - PL_xpvnv_root = ++xpvnv; - while (xpvnv < xpvnvend) { - xpvnv->xpv_pv = (char*)(xpvnv + 1); - xpvnv++; - } - xpvnv->xpv_pv = 0; -} - -STATIC XPVCV* -S_new_xpvcv(pTHX) -{ - XPVCV* xpvcv; - LOCK_SV_MUTEX; - if (!PL_xpvcv_root) - more_xpvcv(); - xpvcv = PL_xpvcv_root; - PL_xpvcv_root = (XPVCV*)xpvcv->xpv_pv; - UNLOCK_SV_MUTEX; - return xpvcv; -} - -STATIC void -S_del_xpvcv(pTHX_ XPVCV *p) -{ - LOCK_SV_MUTEX; - p->xpv_pv = (char*)PL_xpvcv_root; - PL_xpvcv_root = p; - UNLOCK_SV_MUTEX; -} - -STATIC void -S_more_xpvcv(pTHX) -{ - register XPVCV* xpvcv; - register XPVCV* xpvcvend; - New(716, xpvcv, 1008/sizeof(XPVCV), XPVCV); - xpvcv->xpv_pv = (char*)PL_xpvcv_arenaroot; - PL_xpvcv_arenaroot = xpvcv; - - xpvcvend = &xpvcv[1008 / sizeof(XPVCV) - 1]; - PL_xpvcv_root = ++xpvcv; - while (xpvcv < xpvcvend) { - xpvcv->xpv_pv = (char*)(xpvcv + 1); - xpvcv++; - } - xpvcv->xpv_pv = 0; -} - -STATIC XPVAV* -S_new_xpvav(pTHX) -{ - XPVAV* xpvav; - LOCK_SV_MUTEX; - if (!PL_xpvav_root) - more_xpvav(); - xpvav = PL_xpvav_root; - PL_xpvav_root = (XPVAV*)xpvav->xav_array; - UNLOCK_SV_MUTEX; - return xpvav; -} - -STATIC void -S_del_xpvav(pTHX_ XPVAV *p) -{ - LOCK_SV_MUTEX; - p->xav_array = (char*)PL_xpvav_root; - PL_xpvav_root = p; - UNLOCK_SV_MUTEX; -} - -STATIC void -S_more_xpvav(pTHX) -{ - register XPVAV* xpvav; - register XPVAV* xpvavend; - New(717, xpvav, 1008/sizeof(XPVAV), XPVAV); - xpvav->xav_array = (char*)PL_xpvav_arenaroot; - PL_xpvav_arenaroot = xpvav; - - xpvavend = &xpvav[1008 / sizeof(XPVAV) - 1]; - PL_xpvav_root = ++xpvav; - while (xpvav < xpvavend) { - xpvav->xav_array = (char*)(xpvav + 1); - xpvav++; - } - xpvav->xav_array = 0; -} - -STATIC XPVHV* -S_new_xpvhv(pTHX) -{ - XPVHV* xpvhv; - LOCK_SV_MUTEX; - if (!PL_xpvhv_root) - more_xpvhv(); - xpvhv = PL_xpvhv_root; - PL_xpvhv_root = (XPVHV*)xpvhv->xhv_array; - UNLOCK_SV_MUTEX; - return xpvhv; -} - -STATIC void -S_del_xpvhv(pTHX_ XPVHV *p) -{ - LOCK_SV_MUTEX; - p->xhv_array = (char*)PL_xpvhv_root; - PL_xpvhv_root = p; - UNLOCK_SV_MUTEX; -} - -STATIC void -S_more_xpvhv(pTHX) -{ - register XPVHV* xpvhv; - register XPVHV* xpvhvend; - New(718, xpvhv, 1008/sizeof(XPVHV), XPVHV); - xpvhv->xhv_array = (char*)PL_xpvhv_arenaroot; - PL_xpvhv_arenaroot = xpvhv; - - xpvhvend = &xpvhv[1008 / sizeof(XPVHV) - 1]; - PL_xpvhv_root = ++xpvhv; - while (xpvhv < xpvhvend) { - xpvhv->xhv_array = (char*)(xpvhv + 1); - xpvhv++; - } - xpvhv->xhv_array = 0; -} - -STATIC XPVMG* -S_new_xpvmg(pTHX) -{ - XPVMG* xpvmg; - LOCK_SV_MUTEX; - if (!PL_xpvmg_root) - more_xpvmg(); - xpvmg = PL_xpvmg_root; - PL_xpvmg_root = (XPVMG*)xpvmg->xpv_pv; - UNLOCK_SV_MUTEX; - return xpvmg; -} - -STATIC void -S_del_xpvmg(pTHX_ XPVMG *p) -{ - LOCK_SV_MUTEX; - p->xpv_pv = (char*)PL_xpvmg_root; - PL_xpvmg_root = p; - UNLOCK_SV_MUTEX; -} - -STATIC void -S_more_xpvmg(pTHX) -{ - register XPVMG* xpvmg; - register XPVMG* xpvmgend; - New(719, xpvmg, 1008/sizeof(XPVMG), XPVMG); - xpvmg->xpv_pv = (char*)PL_xpvmg_arenaroot; - PL_xpvmg_arenaroot = xpvmg; - - xpvmgend = &xpvmg[1008 / sizeof(XPVMG) - 1]; - PL_xpvmg_root = ++xpvmg; - while (xpvmg < xpvmgend) { - xpvmg->xpv_pv = (char*)(xpvmg + 1); - xpvmg++; - } - xpvmg->xpv_pv = 0; -} - -STATIC XPVLV* -S_new_xpvlv(pTHX) -{ - XPVLV* xpvlv; - LOCK_SV_MUTEX; - if (!PL_xpvlv_root) - more_xpvlv(); - xpvlv = PL_xpvlv_root; - PL_xpvlv_root = (XPVLV*)xpvlv->xpv_pv; - UNLOCK_SV_MUTEX; - return xpvlv; -} - -STATIC void -S_del_xpvlv(pTHX_ XPVLV *p) -{ - LOCK_SV_MUTEX; - p->xpv_pv = (char*)PL_xpvlv_root; - PL_xpvlv_root = p; - UNLOCK_SV_MUTEX; -} - -STATIC void -S_more_xpvlv(pTHX) -{ - register XPVLV* xpvlv; - register XPVLV* xpvlvend; - New(720, xpvlv, 1008/sizeof(XPVLV), XPVLV); - xpvlv->xpv_pv = (char*)PL_xpvlv_arenaroot; - PL_xpvlv_arenaroot = xpvlv; - - xpvlvend = &xpvlv[1008 / sizeof(XPVLV) - 1]; - PL_xpvlv_root = ++xpvlv; - while (xpvlv < xpvlvend) { - xpvlv->xpv_pv = (char*)(xpvlv + 1); - xpvlv++; - } - xpvlv->xpv_pv = 0; -} - -STATIC XPVBM* -S_new_xpvbm(pTHX) -{ - XPVBM* xpvbm; - LOCK_SV_MUTEX; - if (!PL_xpvbm_root) - more_xpvbm(); - xpvbm = PL_xpvbm_root; - PL_xpvbm_root = (XPVBM*)xpvbm->xpv_pv; - UNLOCK_SV_MUTEX; - return xpvbm; -} - -STATIC void -S_del_xpvbm(pTHX_ XPVBM *p) -{ - LOCK_SV_MUTEX; - p->xpv_pv = (char*)PL_xpvbm_root; - PL_xpvbm_root = p; - UNLOCK_SV_MUTEX; -} - -STATIC void -S_more_xpvbm(pTHX) -{ - register XPVBM* xpvbm; - register XPVBM* xpvbmend; - New(721, xpvbm, 1008/sizeof(XPVBM), XPVBM); - xpvbm->xpv_pv = (char*)PL_xpvbm_arenaroot; - PL_xpvbm_arenaroot = xpvbm; - - xpvbmend = &xpvbm[1008 / sizeof(XPVBM) - 1]; - PL_xpvbm_root = ++xpvbm; - while (xpvbm < xpvbmend) { - xpvbm->xpv_pv = (char*)(xpvbm + 1); - xpvbm++; - } - xpvbm->xpv_pv = 0; -} - -#ifdef LEAKTEST -# define my_safemalloc(s) (void*)safexmalloc(717,s) -# define my_safefree(p) safexfree((char*)p) -#else -# define my_safemalloc(s) (void*)safemalloc(s) -# define my_safefree(p) safefree((char*)p) -#endif - -#ifdef PURIFY - -#define new_XIV() my_safemalloc(sizeof(XPVIV)) -#define del_XIV(p) my_safefree(p) - -#define new_XNV() my_safemalloc(sizeof(XPVNV)) -#define del_XNV(p) my_safefree(p) - -#define new_XRV() my_safemalloc(sizeof(XRV)) -#define del_XRV(p) my_safefree(p) - -#define new_XPV() my_safemalloc(sizeof(XPV)) -#define del_XPV(p) my_safefree(p) - -#define new_XPVIV() my_safemalloc(sizeof(XPVIV)) -#define del_XPVIV(p) my_safefree(p) - -#define new_XPVNV() my_safemalloc(sizeof(XPVNV)) -#define del_XPVNV(p) my_safefree(p) - -#define new_XPVCV() my_safemalloc(sizeof(XPVCV)) -#define del_XPVCV(p) my_safefree(p) - -#define new_XPVAV() my_safemalloc(sizeof(XPVAV)) -#define del_XPVAV(p) my_safefree(p) - -#define new_XPVHV() my_safemalloc(sizeof(XPVHV)) -#define del_XPVHV(p) my_safefree(p) - -#define new_XPVMG() my_safemalloc(sizeof(XPVMG)) -#define del_XPVMG(p) my_safefree(p) - -#define new_XPVLV() my_safemalloc(sizeof(XPVLV)) -#define del_XPVLV(p) my_safefree(p) - -#define new_XPVBM() my_safemalloc(sizeof(XPVBM)) -#define del_XPVBM(p) my_safefree(p) - -#else /* !PURIFY */ - -#define new_XIV() (void*)new_xiv() -#define del_XIV(p) del_xiv((XPVIV*) p) - -#define new_XNV() (void*)new_xnv() -#define del_XNV(p) del_xnv((XPVNV*) p) - -#define new_XRV() (void*)new_xrv() -#define del_XRV(p) del_xrv((XRV*) p) - -#define new_XPV() (void*)new_xpv() -#define del_XPV(p) del_xpv((XPV *)p) - -#define new_XPVIV() (void*)new_xpviv() -#define del_XPVIV(p) del_xpviv((XPVIV *)p) - -#define new_XPVNV() (void*)new_xpvnv() -#define del_XPVNV(p) del_xpvnv((XPVNV *)p) - -#define new_XPVCV() (void*)new_xpvcv() -#define del_XPVCV(p) del_xpvcv((XPVCV *)p) - -#define new_XPVAV() (void*)new_xpvav() -#define del_XPVAV(p) del_xpvav((XPVAV *)p) - -#define new_XPVHV() (void*)new_xpvhv() -#define del_XPVHV(p) del_xpvhv((XPVHV *)p) - -#define new_XPVMG() (void*)new_xpvmg() -#define del_XPVMG(p) del_xpvmg((XPVMG *)p) - -#define new_XPVLV() (void*)new_xpvlv() -#define del_XPVLV(p) del_xpvlv((XPVLV *)p) - -#define new_XPVBM() (void*)new_xpvbm() -#define del_XPVBM(p) del_xpvbm((XPVBM *)p) - -#endif /* PURIFY */ - -#define new_XPVGV() my_safemalloc(sizeof(XPVGV)) -#define del_XPVGV(p) my_safefree(p) - -#define new_XPVFM() my_safemalloc(sizeof(XPVFM)) -#define del_XPVFM(p) my_safefree(p) - -#define new_XPVIO() my_safemalloc(sizeof(XPVIO)) -#define del_XPVIO(p) my_safefree(p) - -/* -=for apidoc sv_upgrade - -Upgrade an SV to a more complex form. Use C<SvUPGRADE>. See -C<svtype>. - -=cut -*/ - -bool -Perl_sv_upgrade(pTHX_ register SV *sv, U32 mt) -{ - char* pv; - U32 cur; - U32 len; - IV iv; - NV nv; - MAGIC* magic; - HV* stash; - - if (SvTYPE(sv) == mt) - return TRUE; - - if (mt < SVt_PVIV) - (void)SvOOK_off(sv); - - switch (SvTYPE(sv)) { - case SVt_NULL: - pv = 0; - cur = 0; - len = 0; - iv = 0; - nv = 0.0; - magic = 0; - stash = 0; - break; - case SVt_IV: - pv = 0; - cur = 0; - len = 0; - iv = SvIVX(sv); - nv = (NV)SvIVX(sv); - del_XIV(SvANY(sv)); - magic = 0; - stash = 0; - if (mt == SVt_NV) - mt = SVt_PVNV; - else if (mt < SVt_PVIV) - mt = SVt_PVIV; - break; - case SVt_NV: - pv = 0; - cur = 0; - len = 0; - nv = SvNVX(sv); - iv = I_V(nv); - magic = 0; - stash = 0; - del_XNV(SvANY(sv)); - SvANY(sv) = 0; - if (mt < SVt_PVNV) - mt = SVt_PVNV; - break; - case SVt_RV: - pv = (char*)SvRV(sv); - cur = 0; - len = 0; - iv = PTR2IV(pv); - nv = PTR2NV(pv); - del_XRV(SvANY(sv)); - magic = 0; - stash = 0; - break; - case SVt_PV: - pv = SvPVX(sv); - cur = SvCUR(sv); - len = SvLEN(sv); - iv = 0; - nv = 0.0; - magic = 0; - stash = 0; - del_XPV(SvANY(sv)); - if (mt <= SVt_IV) - mt = SVt_PVIV; - else if (mt == SVt_NV) - mt = SVt_PVNV; - break; - case SVt_PVIV: - pv = SvPVX(sv); - cur = SvCUR(sv); - len = SvLEN(sv); - iv = SvIVX(sv); - nv = 0.0; - magic = 0; - stash = 0; - del_XPVIV(SvANY(sv)); - break; - case SVt_PVNV: - pv = SvPVX(sv); - cur = SvCUR(sv); - len = SvLEN(sv); - iv = SvIVX(sv); - nv = SvNVX(sv); - magic = 0; - stash = 0; - del_XPVNV(SvANY(sv)); - break; - case SVt_PVMG: - pv = SvPVX(sv); - cur = SvCUR(sv); - len = SvLEN(sv); - iv = SvIVX(sv); - nv = SvNVX(sv); - magic = SvMAGIC(sv); - stash = SvSTASH(sv); - del_XPVMG(SvANY(sv)); - break; - default: - Perl_croak(aTHX_ "Can't upgrade that kind of scalar"); - } - - switch (mt) { - case SVt_NULL: - Perl_croak(aTHX_ "Can't upgrade to undef"); - case SVt_IV: - SvANY(sv) = new_XIV(); - SvIVX(sv) = iv; - break; - case SVt_NV: - SvANY(sv) = new_XNV(); - SvNVX(sv) = nv; - break; - case SVt_RV: - SvANY(sv) = new_XRV(); - SvRV(sv) = (SV*)pv; - break; - case SVt_PV: - SvANY(sv) = new_XPV(); - SvPVX(sv) = pv; - SvCUR(sv) = cur; - SvLEN(sv) = len; - break; - case SVt_PVIV: - SvANY(sv) = new_XPVIV(); - SvPVX(sv) = pv; - SvCUR(sv) = cur; - SvLEN(sv) = len; - SvIVX(sv) = iv; - if (SvNIOK(sv)) - (void)SvIOK_on(sv); - SvNOK_off(sv); - break; - case SVt_PVNV: - SvANY(sv) = new_XPVNV(); - SvPVX(sv) = pv; - SvCUR(sv) = cur; - SvLEN(sv) = len; - SvIVX(sv) = iv; - SvNVX(sv) = nv; - break; - case SVt_PVMG: - SvANY(sv) = new_XPVMG(); - SvPVX(sv) = pv; - SvCUR(sv) = cur; - SvLEN(sv) = len; - SvIVX(sv) = iv; - SvNVX(sv) = nv; - SvMAGIC(sv) = magic; - SvSTASH(sv) = stash; - break; - case SVt_PVLV: - SvANY(sv) = new_XPVLV(); - SvPVX(sv) = pv; - SvCUR(sv) = cur; - SvLEN(sv) = len; - SvIVX(sv) = iv; - SvNVX(sv) = nv; - SvMAGIC(sv) = magic; - SvSTASH(sv) = stash; - LvTARGOFF(sv) = 0; - LvTARGLEN(sv) = 0; - LvTARG(sv) = 0; - LvTYPE(sv) = 0; - break; - case SVt_PVAV: - SvANY(sv) = new_XPVAV(); - if (pv) - Safefree(pv); - SvPVX(sv) = 0; - AvMAX(sv) = -1; - AvFILLp(sv) = -1; - SvIVX(sv) = 0; - SvNVX(sv) = 0.0; - SvMAGIC(sv) = magic; - SvSTASH(sv) = stash; - AvALLOC(sv) = 0; - AvARYLEN(sv) = 0; - AvFLAGS(sv) = 0; - break; - case SVt_PVHV: - SvANY(sv) = new_XPVHV(); - if (pv) - Safefree(pv); - SvPVX(sv) = 0; - HvFILL(sv) = 0; - HvMAX(sv) = 0; - HvKEYS(sv) = 0; - SvNVX(sv) = 0.0; - SvMAGIC(sv) = magic; - SvSTASH(sv) = stash; - HvRITER(sv) = 0; - HvEITER(sv) = 0; - HvPMROOT(sv) = 0; - HvNAME(sv) = 0; - break; - case SVt_PVCV: - SvANY(sv) = new_XPVCV(); - Zero(SvANY(sv), 1, XPVCV); - SvPVX(sv) = pv; - SvCUR(sv) = cur; - SvLEN(sv) = len; - SvIVX(sv) = iv; - SvNVX(sv) = nv; - SvMAGIC(sv) = magic; - SvSTASH(sv) = stash; - break; - case SVt_PVGV: - SvANY(sv) = new_XPVGV(); - SvPVX(sv) = pv; - SvCUR(sv) = cur; - SvLEN(sv) = len; - SvIVX(sv) = iv; - SvNVX(sv) = nv; - SvMAGIC(sv) = magic; - SvSTASH(sv) = stash; - GvGP(sv) = 0; - GvNAME(sv) = 0; - GvNAMELEN(sv) = 0; - GvSTASH(sv) = 0; - GvFLAGS(sv) = 0; - break; - case SVt_PVBM: - SvANY(sv) = new_XPVBM(); - SvPVX(sv) = pv; - SvCUR(sv) = cur; - SvLEN(sv) = len; - SvIVX(sv) = iv; - SvNVX(sv) = nv; - SvMAGIC(sv) = magic; - SvSTASH(sv) = stash; - BmRARE(sv) = 0; - BmUSEFUL(sv) = 0; - BmPREVIOUS(sv) = 0; - break; - case SVt_PVFM: - SvANY(sv) = new_XPVFM(); - Zero(SvANY(sv), 1, XPVFM); - SvPVX(sv) = pv; - SvCUR(sv) = cur; - SvLEN(sv) = len; - SvIVX(sv) = iv; - SvNVX(sv) = nv; - SvMAGIC(sv) = magic; - SvSTASH(sv) = stash; - break; - case SVt_PVIO: - SvANY(sv) = new_XPVIO(); - Zero(SvANY(sv), 1, XPVIO); - SvPVX(sv) = pv; - SvCUR(sv) = cur; - SvLEN(sv) = len; - SvIVX(sv) = iv; - SvNVX(sv) = nv; - SvMAGIC(sv) = magic; - SvSTASH(sv) = stash; - IoPAGE_LEN(sv) = 60; - break; - } - SvFLAGS(sv) &= ~SVTYPEMASK; - SvFLAGS(sv) |= mt; - return TRUE; -} - -int -Perl_sv_backoff(pTHX_ register SV *sv) -{ - assert(SvOOK(sv)); - if (SvIVX(sv)) { - char *s = SvPVX(sv); - SvLEN(sv) += SvIVX(sv); - SvPVX(sv) -= SvIVX(sv); - SvIV_set(sv, 0); - Move(s, SvPVX(sv), SvCUR(sv)+1, char); - } - SvFLAGS(sv) &= ~SVf_OOK; - return 0; -} - -/* -=for apidoc sv_grow - -Expands the character buffer in the SV. This will use C<sv_unref> and will -upgrade the SV to C<SVt_PV>. Returns a pointer to the character buffer. -Use C<SvGROW>. - -=cut -*/ - -char * -Perl_sv_grow(pTHX_ register SV *sv, register STRLEN newlen) -{ - register char *s; - -#ifdef HAS_64K_LIMIT - if (newlen >= 0x10000) { - PerlIO_printf(Perl_debug_log, - "Allocation too large: %"UVxf"\n", (UV)newlen); - my_exit(1); - } -#endif /* HAS_64K_LIMIT */ - if (SvROK(sv)) - sv_unref(sv); - if (SvTYPE(sv) < SVt_PV) { - sv_upgrade(sv, SVt_PV); - s = SvPVX(sv); - } - else if (SvOOK(sv)) { /* pv is offset? */ - sv_backoff(sv); - s = SvPVX(sv); - if (newlen > SvLEN(sv)) - newlen += 10 * (newlen - SvCUR(sv)); /* avoid copy each time */ -#ifdef HAS_64K_LIMIT - if (newlen >= 0x10000) - newlen = 0xFFFF; -#endif - } - else - s = SvPVX(sv); - if (newlen > SvLEN(sv)) { /* need more room? */ - if (SvLEN(sv) && s) { -#if defined(MYMALLOC) && !defined(LEAKTEST) - STRLEN l = malloced_size((void*)SvPVX(sv)); - if (newlen <= l) { - SvLEN_set(sv, l); - return s; - } else -#endif - Renew(s,newlen,char); - } - else - New(703,s,newlen,char); - SvPV_set(sv, s); - SvLEN_set(sv, newlen); - } - return s; -} - -/* -=for apidoc sv_setiv - -Copies an integer into the given SV. Does not handle 'set' magic. See -C<sv_setiv_mg>. - -=cut -*/ - -void -Perl_sv_setiv(pTHX_ register SV *sv, IV i) -{ - SV_CHECK_THINKFIRST(sv); - switch (SvTYPE(sv)) { - case SVt_NULL: - sv_upgrade(sv, SVt_IV); - break; - case SVt_NV: - sv_upgrade(sv, SVt_PVNV); - break; - case SVt_RV: - case SVt_PV: - sv_upgrade(sv, SVt_PVIV); - break; - - case SVt_PVGV: - case SVt_PVAV: - case SVt_PVHV: - case SVt_PVCV: - case SVt_PVFM: - case SVt_PVIO: - Perl_croak(aTHX_ "Can't coerce %s to integer in %s", sv_reftype(sv,0), - PL_op_desc[PL_op->op_type]); - } - (void)SvIOK_only(sv); /* validate number */ - SvIVX(sv) = i; - SvTAINT(sv); -} - -/* -=for apidoc sv_setiv_mg - -Like C<sv_setiv>, but also handles 'set' magic. - -=cut -*/ - -void -Perl_sv_setiv_mg(pTHX_ register SV *sv, IV i) -{ - sv_setiv(sv,i); - SvSETMAGIC(sv); -} - -/* -=for apidoc sv_setuv - -Copies an unsigned integer into the given SV. Does not handle 'set' magic. -See C<sv_setuv_mg>. - -=cut -*/ - -void -Perl_sv_setuv(pTHX_ register SV *sv, UV u) -{ - sv_setiv(sv, 0); - SvIsUV_on(sv); - SvUVX(sv) = u; -} - -/* -=for apidoc sv_setuv_mg - -Like C<sv_setuv>, but also handles 'set' magic. - -=cut -*/ - -void -Perl_sv_setuv_mg(pTHX_ register SV *sv, UV u) -{ - sv_setuv(sv,u); - SvSETMAGIC(sv); -} - -/* -=for apidoc sv_setnv - -Copies a double into the given SV. Does not handle 'set' magic. See -C<sv_setnv_mg>. - -=cut -*/ - -void -Perl_sv_setnv(pTHX_ register SV *sv, NV num) -{ - SV_CHECK_THINKFIRST(sv); - switch (SvTYPE(sv)) { - case SVt_NULL: - case SVt_IV: - sv_upgrade(sv, SVt_NV); - break; - case SVt_RV: - case SVt_PV: - case SVt_PVIV: - sv_upgrade(sv, SVt_PVNV); - break; - - case SVt_PVGV: - case SVt_PVAV: - case SVt_PVHV: - case SVt_PVCV: - case SVt_PVFM: - case SVt_PVIO: - Perl_croak(aTHX_ "Can't coerce %s to number in %s", sv_reftype(sv,0), - PL_op_name[PL_op->op_type]); - } - SvNVX(sv) = num; - (void)SvNOK_only(sv); /* validate number */ - SvTAINT(sv); -} - -/* -=for apidoc sv_setnv_mg - -Like C<sv_setnv>, but also handles 'set' magic. - -=cut -*/ - -void -Perl_sv_setnv_mg(pTHX_ register SV *sv, NV num) -{ - sv_setnv(sv,num); - SvSETMAGIC(sv); -} - -STATIC void -S_not_a_number(pTHX_ SV *sv) -{ - char tmpbuf[64]; - char *d = tmpbuf; - char *s; - char *limit = tmpbuf + sizeof(tmpbuf) - 8; - /* each *s can expand to 4 chars + "...\0", - i.e. need room for 8 chars */ - - for (s = SvPVX(sv); *s && d < limit; s++) { - int ch = *s & 0xFF; - if (ch & 128 && !isPRINT_LC(ch)) { - *d++ = 'M'; - *d++ = '-'; - ch &= 127; - } - if (ch == '\n') { - *d++ = '\\'; - *d++ = 'n'; - } - else if (ch == '\r') { - *d++ = '\\'; - *d++ = 'r'; - } - else if (ch == '\f') { - *d++ = '\\'; - *d++ = 'f'; - } - else if (ch == '\\') { - *d++ = '\\'; - *d++ = '\\'; - } - else if (isPRINT_LC(ch)) - *d++ = ch; - else { - *d++ = '^'; - *d++ = toCTRL(ch); - } - } - if (*s) { - *d++ = '.'; - *d++ = '.'; - *d++ = '.'; - } - *d = '\0'; - - if (PL_op) - Perl_warner(aTHX_ WARN_NUMERIC, - "Argument \"%s\" isn't numeric in %s", tmpbuf, - PL_op_desc[PL_op->op_type]); - else - Perl_warner(aTHX_ WARN_NUMERIC, - "Argument \"%s\" isn't numeric", tmpbuf); -} - -/* the number can be converted to integer with atol() or atoll() */ -#define IS_NUMBER_TO_INT_BY_ATOL 0x01 -#define IS_NUMBER_TO_INT_BY_ATOF 0x02 /* atol() may be != atof() */ -#define IS_NUMBER_NOT_IV 0x04 /* (IV)atof() may be != atof() */ -#define IS_NUMBER_NEG 0x08 /* not good to cache UV */ -#define IS_NUMBER_INFINITY 0x10 /* this is big */ - -/* Actually, ISO C leaves conversion of UV to IV undefined, but - until proven guilty, assume that things are not that bad... */ - -IV -Perl_sv_2iv(pTHX_ register SV *sv) -{ - if (!sv) - return 0; - if (SvGMAGICAL(sv)) { - mg_get(sv); - if (SvIOKp(sv)) - return SvIVX(sv); - if (SvNOKp(sv)) { - return I_V(SvNVX(sv)); - } - if (SvPOKp(sv) && SvLEN(sv)) - return asIV(sv); - if (!SvROK(sv)) { - if (!(SvFLAGS(sv) & SVs_PADTMP)) { - if (ckWARN(WARN_UNINITIALIZED) && !PL_localizing) - report_uninit(); - } - return 0; - } - } - if (SvTHINKFIRST(sv)) { - if (SvROK(sv)) { - SV* tmpstr; - if (SvAMAGIC(sv) && (tmpstr=AMG_CALLun(sv,numer)) && - (SvRV(tmpstr) != SvRV(sv))) - return SvIV(tmpstr); - return PTR2IV(SvRV(sv)); - } - if (SvREADONLY(sv) && !SvOK(sv)) { - if (ckWARN(WARN_UNINITIALIZED)) - report_uninit(); - return 0; - } - } - if (SvIOKp(sv)) { - if (SvIsUV(sv)) { - return (IV)(SvUVX(sv)); - } - else { - return SvIVX(sv); - } - } - if (SvNOKp(sv)) { - /* We can cache the IV/UV value even if it not good enough - * to reconstruct NV, since the conversion to PV will prefer - * NV over IV/UV. - */ - - if (SvTYPE(sv) == SVt_NV) - sv_upgrade(sv, SVt_PVNV); - - (void)SvIOK_on(sv); - if (SvNVX(sv) < (NV)IV_MAX + 0.5) - SvIVX(sv) = I_V(SvNVX(sv)); - else { - SvUVX(sv) = U_V(SvNVX(sv)); - SvIsUV_on(sv); - ret_iv_max: - DEBUG_c(PerlIO_printf(Perl_debug_log, - "0x%"UVxf" 2iv(%"UVuf" => %"IVdf") (as unsigned)\n", - PTR2UV(sv), - SvUVX(sv), - SvUVX(sv))); - return (IV)SvUVX(sv); - } - } - else if (SvPOKp(sv) && SvLEN(sv)) { - I32 numtype = looks_like_number(sv); - - /* We want to avoid a possible problem when we cache an IV which - may be later translated to an NV, and the resulting NV is not - the translation of the initial data. - - This means that if we cache such an IV, we need to cache the - NV as well. Moreover, we trade speed for space, and do not - cache the NV if not needed. - */ - if (numtype & IS_NUMBER_NOT_IV) { - /* May be not an integer. Need to cache NV if we cache IV - * - otherwise future conversion to NV will be wrong. */ - NV d; - - d = Atof(SvPVX(sv)); - - if (SvTYPE(sv) < SVt_PVNV) - sv_upgrade(sv, SVt_PVNV); - SvNVX(sv) = d; - (void)SvNOK_on(sv); - (void)SvIOK_on(sv); -#if defined(USE_LONG_DOUBLE) - DEBUG_c(PerlIO_printf(Perl_debug_log, "0x%"UVxf" 2nv(%" PERL_PRIgldbl ")\n", - PTR2UV(sv), SvNVX(sv))); -#else - DEBUG_c(PerlIO_printf(Perl_debug_log, "0x%"UVxf" 2nv(%g)\n", - PTR2UV(sv), SvNVX(sv))); -#endif - if (SvNVX(sv) < (NV)IV_MAX + 0.5) - SvIVX(sv) = I_V(SvNVX(sv)); - else { - SvUVX(sv) = U_V(SvNVX(sv)); - SvIsUV_on(sv); - goto ret_iv_max; - } - } - else { /* The NV may be reconstructed from IV - safe to cache IV, - which may be calculated by atol(). */ - if (SvTYPE(sv) < SVt_PVIV) - sv_upgrade(sv, SVt_PVIV); - (void)SvIOK_on(sv); - SvIVX(sv) = Atol(SvPVX(sv)); - if (! numtype && ckWARN(WARN_NUMERIC)) - not_a_number(sv); - } - } - else { - if (ckWARN(WARN_UNINITIALIZED) && !PL_localizing && !(SvFLAGS(sv) & SVs_PADTMP)) - report_uninit(); - if (SvTYPE(sv) < SVt_IV) - /* Typically the caller expects that sv_any is not NULL now. */ - sv_upgrade(sv, SVt_IV); - return 0; - } - DEBUG_c(PerlIO_printf(Perl_debug_log, "0x%"UVxf" 2iv(%"IVdf")\n", - PTR2UV(sv),SvIVX(sv))); - return SvIsUV(sv) ? (IV)SvUVX(sv) : SvIVX(sv); -} - -UV -Perl_sv_2uv(pTHX_ register SV *sv) -{ - if (!sv) - return 0; - if (SvGMAGICAL(sv)) { - mg_get(sv); - if (SvIOKp(sv)) - return SvUVX(sv); - if (SvNOKp(sv)) - return U_V(SvNVX(sv)); - if (SvPOKp(sv) && SvLEN(sv)) - return asUV(sv); - if (!SvROK(sv)) { - if (!(SvFLAGS(sv) & SVs_PADTMP)) { - if (ckWARN(WARN_UNINITIALIZED) && !PL_localizing) - report_uninit(); - } - return 0; - } - } - if (SvTHINKFIRST(sv)) { - if (SvROK(sv)) { - SV* tmpstr; - if (SvAMAGIC(sv) && (tmpstr=AMG_CALLun(sv,numer)) && - (SvRV(tmpstr) != SvRV(sv))) - return SvUV(tmpstr); - return PTR2UV(SvRV(sv)); - } - if (SvREADONLY(sv) && !SvOK(sv)) { - if (ckWARN(WARN_UNINITIALIZED)) - report_uninit(); - return 0; - } - } - if (SvIOKp(sv)) { - if (SvIsUV(sv)) { - return SvUVX(sv); - } - else { - return (UV)SvIVX(sv); - } - } - if (SvNOKp(sv)) { - /* We can cache the IV/UV value even if it not good enough - * to reconstruct NV, since the conversion to PV will prefer - * NV over IV/UV. - */ - if (SvTYPE(sv) == SVt_NV) - sv_upgrade(sv, SVt_PVNV); - (void)SvIOK_on(sv); - if (SvNVX(sv) >= -0.5) { - SvIsUV_on(sv); - SvUVX(sv) = U_V(SvNVX(sv)); - } - else { - SvIVX(sv) = I_V(SvNVX(sv)); - ret_zero: - DEBUG_c(PerlIO_printf(Perl_debug_log, - "0x%"UVxf" 2uv(%"IVdf" => %"IVdf") (as signed)\n", - PTR2UV(sv), - SvIVX(sv), - (IV)(UV)SvIVX(sv))); - return (UV)SvIVX(sv); - } - } - else if (SvPOKp(sv) && SvLEN(sv)) { - I32 numtype = looks_like_number(sv); - - /* We want to avoid a possible problem when we cache a UV which - may be later translated to an NV, and the resulting NV is not - the translation of the initial data. - - This means that if we cache such a UV, we need to cache the - NV as well. Moreover, we trade speed for space, and do not - cache the NV if not needed. - */ - if (numtype & IS_NUMBER_NOT_IV) { - /* May be not an integer. Need to cache NV if we cache IV - * - otherwise future conversion to NV will be wrong. */ - NV d; - - d = Atof(SvPVX(sv)); - - if (SvTYPE(sv) < SVt_PVNV) - sv_upgrade(sv, SVt_PVNV); - SvNVX(sv) = d; - (void)SvNOK_on(sv); - (void)SvIOK_on(sv); -#if defined(USE_LONG_DOUBLE) - DEBUG_c(PerlIO_printf(Perl_debug_log, - "0x%"UVxf" 2nv(%" PERL_PRIgldbl ")\n", - PTR2UV(sv), SvNVX(sv))); -#else - DEBUG_c(PerlIO_printf(Perl_debug_log, - "0x%"UVxf" 2nv(%g)\n", - PTR2UV(sv), SvNVX(sv))); -#endif - if (SvNVX(sv) < -0.5) { - SvIVX(sv) = I_V(SvNVX(sv)); - goto ret_zero; - } else { - SvUVX(sv) = U_V(SvNVX(sv)); - SvIsUV_on(sv); - } - } - else if (numtype & IS_NUMBER_NEG) { - /* The NV may be reconstructed from IV - safe to cache IV, - which may be calculated by atol(). */ - if (SvTYPE(sv) == SVt_PV) - sv_upgrade(sv, SVt_PVIV); - (void)SvIOK_on(sv); - SvIVX(sv) = (IV)Atol(SvPVX(sv)); - } - else if (numtype) { /* Non-negative */ - /* The NV may be reconstructed from UV - safe to cache UV, - which may be calculated by strtoul()/atol. */ - if (SvTYPE(sv) == SVt_PV) - sv_upgrade(sv, SVt_PVIV); - (void)SvIOK_on(sv); - (void)SvIsUV_on(sv); -#ifdef HAS_STRTOUL - SvUVX(sv) = Strtoul(SvPVX(sv), Null(char**), 10); -#else /* no atou(), but we know the number fits into IV... */ - /* The only problem may be if it is negative... */ - SvUVX(sv) = (UV)Atol(SvPVX(sv)); -#endif - } - else { /* Not a number. Cache 0. */ - if (SvTYPE(sv) < SVt_PVIV) - sv_upgrade(sv, SVt_PVIV); - (void)SvIOK_on(sv); - (void)SvIsUV_on(sv); - SvUVX(sv) = 0; /* We assume that 0s have the - same bitmap in IV and UV. */ - if (ckWARN(WARN_NUMERIC)) - not_a_number(sv); - } - } - else { - if (!(SvFLAGS(sv) & SVs_PADTMP)) { - if (ckWARN(WARN_UNINITIALIZED) && !PL_localizing) - report_uninit(); - } - if (SvTYPE(sv) < SVt_IV) - /* Typically the caller expects that sv_any is not NULL now. */ - sv_upgrade(sv, SVt_IV); - return 0; - } - - DEBUG_c(PerlIO_printf(Perl_debug_log, "0x%"UVxf" 2uv(%"UVuf")\n", - PTR2UV(sv),SvUVX(sv))); - return SvIsUV(sv) ? SvUVX(sv) : (UV)SvIVX(sv); -} - -NV -Perl_sv_2nv(pTHX_ register SV *sv) -{ - if (!sv) - return 0.0; - if (SvGMAGICAL(sv)) { - mg_get(sv); - if (SvNOKp(sv)) - return SvNVX(sv); - if (SvPOKp(sv) && SvLEN(sv)) { - if (ckWARN(WARN_NUMERIC) && !SvIOKp(sv) && !looks_like_number(sv)) - not_a_number(sv); - return Atof(SvPVX(sv)); - } - if (SvIOKp(sv)) { - if (SvIsUV(sv)) - return (NV)SvUVX(sv); - else - return (NV)SvIVX(sv); - } - if (!SvROK(sv)) { - if (!(SvFLAGS(sv) & SVs_PADTMP)) { - if (ckWARN(WARN_UNINITIALIZED) && !PL_localizing) - report_uninit(); - } - return 0; - } - } - if (SvTHINKFIRST(sv)) { - if (SvROK(sv)) { - SV* tmpstr; - if (SvAMAGIC(sv) && (tmpstr=AMG_CALLun(sv,numer)) && - (SvRV(tmpstr) != SvRV(sv))) - return SvNV(tmpstr); - return PTR2NV(SvRV(sv)); - } - if (SvREADONLY(sv) && !SvOK(sv)) { - if (ckWARN(WARN_UNINITIALIZED)) - report_uninit(); - return 0.0; - } - } - if (SvTYPE(sv) < SVt_NV) { - if (SvTYPE(sv) == SVt_IV) - sv_upgrade(sv, SVt_PVNV); - else - sv_upgrade(sv, SVt_NV); -#if defined(USE_LONG_DOUBLE) - DEBUG_c({ - STORE_NUMERIC_LOCAL_SET_STANDARD(); - PerlIO_printf(Perl_debug_log, - "0x%"UVxf" num(%" PERL_PRIgldbl ")\n", - PTR2UV(sv), SvNVX(sv)); - RESTORE_NUMERIC_LOCAL(); - }); -#else - DEBUG_c({ - STORE_NUMERIC_LOCAL_SET_STANDARD(); - PerlIO_printf(Perl_debug_log, "0x%"UVxf" num(%g)\n", - PTR2UV(sv), SvNVX(sv)); - RESTORE_NUMERIC_LOCAL(); - }); -#endif - } - else if (SvTYPE(sv) < SVt_PVNV) - sv_upgrade(sv, SVt_PVNV); - if (SvIOKp(sv) && - (!SvPOKp(sv) || !strchr(SvPVX(sv),'.') || !looks_like_number(sv))) - { - SvNVX(sv) = SvIsUV(sv) ? (NV)SvUVX(sv) : (NV)SvIVX(sv); - } - else if (SvPOKp(sv) && SvLEN(sv)) { - if (ckWARN(WARN_NUMERIC) && !SvIOKp(sv) && !looks_like_number(sv)) - not_a_number(sv); - SvNVX(sv) = Atof(SvPVX(sv)); - } - else { - if (ckWARN(WARN_UNINITIALIZED) && !PL_localizing && !(SvFLAGS(sv) & SVs_PADTMP)) - report_uninit(); - if (SvTYPE(sv) < SVt_NV) - /* Typically the caller expects that sv_any is not NULL now. */ - sv_upgrade(sv, SVt_NV); - return 0.0; - } - SvNOK_on(sv); -#if defined(USE_LONG_DOUBLE) - DEBUG_c({ - STORE_NUMERIC_LOCAL_SET_STANDARD(); - PerlIO_printf(Perl_debug_log, "0x%"UVxf" 2nv(%" PERL_PRIgldbl ")\n", - PTR2UV(sv), SvNVX(sv)); - RESTORE_NUMERIC_LOCAL(); - }); -#else - DEBUG_c({ - STORE_NUMERIC_LOCAL_SET_STANDARD(); - PerlIO_printf(Perl_debug_log, "0x%"UVxf" 1nv(%g)\n", - PTR2UV(sv), SvNVX(sv)); - RESTORE_NUMERIC_LOCAL(); - }); -#endif - return SvNVX(sv); -} - -STATIC IV -S_asIV(pTHX_ SV *sv) -{ - I32 numtype = looks_like_number(sv); - NV d; - - if (numtype & IS_NUMBER_TO_INT_BY_ATOL) - return Atol(SvPVX(sv)); - if (!numtype) { - if (ckWARN(WARN_NUMERIC)) - not_a_number(sv); - } - d = Atof(SvPVX(sv)); - return I_V(d); -} - -STATIC UV -S_asUV(pTHX_ SV *sv) -{ - I32 numtype = looks_like_number(sv); - -#ifdef HAS_STRTOUL - if (numtype & IS_NUMBER_TO_INT_BY_ATOL) - return Strtoul(SvPVX(sv), Null(char**), 10); -#endif - if (!numtype) { - if (ckWARN(WARN_NUMERIC)) - not_a_number(sv); - } - return U_V(Atof(SvPVX(sv))); -} - -/* - * Returns a combination of (advisory only - can get false negatives) - * IS_NUMBER_TO_INT_BY_ATOL, IS_NUMBER_TO_INT_BY_ATOF, IS_NUMBER_NOT_IV, - * IS_NUMBER_NEG - * 0 if does not look like number. - * - * In fact possible values are 0 and - * IS_NUMBER_TO_INT_BY_ATOL 123 - * IS_NUMBER_TO_INT_BY_ATOL | IS_NUMBER_NOT_IV 123.1 - * IS_NUMBER_TO_INT_BY_ATOF | IS_NUMBER_NOT_IV 123e0 - * IS_NUMBER_INFINITY - * with a possible addition of IS_NUMBER_NEG. - */ - -/* -=for apidoc looks_like_number - -Test if an the content of an SV looks like a number (or is a -number). - -=cut -*/ - -I32 -Perl_looks_like_number(pTHX_ SV *sv) -{ - register char *s; - register char *send; - register char *sbegin; - register char *nbegin; - I32 numtype = 0; - I32 sawinf = 0; - STRLEN len; -#ifdef USE_LOCALE_NUMERIC - bool specialradix = FALSE; -#endif - - if (SvPOK(sv)) { - sbegin = SvPVX(sv); - len = SvCUR(sv); - } - else if (SvPOKp(sv)) - sbegin = SvPV(sv, len); - else - return 1; - send = sbegin + len; - - s = sbegin; - while (isSPACE(*s)) - s++; - if (*s == '-') { - s++; - numtype = IS_NUMBER_NEG; - } - else if (*s == '+') - s++; - - nbegin = s; - /* - * we return IS_NUMBER_TO_INT_BY_ATOL if the number can be converted - * to _integer_ with atol() and IS_NUMBER_TO_INT_BY_ATOF if you need - * (int)atof(). - */ - - /* next must be digit or the radix separator or beginning of infinity */ - if (isDIGIT(*s)) { - do { - s++; - } while (isDIGIT(*s)); - - if (s - nbegin >= TYPE_DIGITS(IV)) /* Cannot cache ato[ul]() */ - numtype |= IS_NUMBER_TO_INT_BY_ATOF | IS_NUMBER_NOT_IV; - else - numtype |= IS_NUMBER_TO_INT_BY_ATOL; - - if (*s == '.' -#ifdef USE_LOCALE_NUMERIC - || (specialradix = IS_NUMERIC_RADIX(s)) -#endif - ) { -#ifdef USE_LOCALE_NUMERIC - if (specialradix) - s += SvCUR(PL_numeric_radix_sv); - else -#endif - s++; - numtype |= IS_NUMBER_NOT_IV; - while (isDIGIT(*s)) /* optional digits after the radix */ - s++; - } - } - else if (*s == '.' -#ifdef USE_LOCALE_NUMERIC - || (specialradix = IS_NUMERIC_RADIX(s)) -#endif - ) { -#ifdef USE_LOCALE_NUMERIC - if (specialradix) - s += SvCUR(PL_numeric_radix_sv); - else -#endif - s++; - numtype |= IS_NUMBER_TO_INT_BY_ATOL | IS_NUMBER_NOT_IV; - /* no digits before the radix means we need digits after it */ - if (isDIGIT(*s)) { - do { - s++; - } while (isDIGIT(*s)); - } - else - return 0; - } - else if (*s == 'I' || *s == 'i') { - s++; if (*s != 'N' && *s != 'n') return 0; - s++; if (*s != 'F' && *s != 'f') return 0; - s++; if (*s == 'I' || *s == 'i') { - s++; if (*s != 'N' && *s != 'n') return 0; - s++; if (*s != 'I' && *s != 'i') return 0; - s++; if (*s != 'T' && *s != 't') return 0; - s++; if (*s != 'Y' && *s != 'y') return 0; - } - sawinf = 1; - } - else - return 0; - - if (sawinf) - numtype = IS_NUMBER_INFINITY; - else { - /* we can have an optional exponent part */ - if (*s == 'e' || *s == 'E') { - numtype &= ~IS_NUMBER_NEG; - numtype |= IS_NUMBER_TO_INT_BY_ATOF | IS_NUMBER_NOT_IV; - s++; - if (*s == '+' || *s == '-') - s++; - if (isDIGIT(*s)) { - do { - s++; - } while (isDIGIT(*s)); - } - else - return 0; - } - } - while (isSPACE(*s)) - s++; - if (s >= send) - return numtype; - if (len == 10 && memEQ(sbegin, "0 but true", 10)) - return IS_NUMBER_TO_INT_BY_ATOL; - return 0; -} - -char * -Perl_sv_2pv_nolen(pTHX_ register SV *sv) -{ - STRLEN n_a; - return sv_2pv(sv, &n_a); -} - -/* We assume that buf is at least TYPE_CHARS(UV) long. */ -static char * -uiv_2buf(char *buf, IV iv, UV uv, int is_uv, char **peob) -{ - char *ptr = buf + TYPE_CHARS(UV); - char *ebuf = ptr; - int sign; - - if (is_uv) - sign = 0; - else if (iv >= 0) { - uv = iv; - sign = 0; - } else { - uv = -iv; - sign = 1; - } - do { - *--ptr = '0' + (uv % 10); - } while (uv /= 10); - if (sign) - *--ptr = '-'; - *peob = ebuf; - return ptr; -} - -char * -Perl_sv_2pv(pTHX_ register SV *sv, STRLEN *lp) -{ - register char *s; - int olderrno; - SV *tsv; - char tbuf[64]; /* Must fit sprintf/Gconvert of longest IV/NV */ - char *tmpbuf = tbuf; - - if (!sv) { - *lp = 0; - return ""; - } - if (SvGMAGICAL(sv)) { - mg_get(sv); - if (SvPOKp(sv)) { - *lp = SvCUR(sv); - return SvPVX(sv); - } - if (SvIOKp(sv)) { - if (SvIsUV(sv)) - (void)sprintf(tmpbuf,"%"UVuf, (UV)SvUVX(sv)); - else - (void)sprintf(tmpbuf,"%"IVdf, (IV)SvIVX(sv)); - tsv = Nullsv; - goto tokensave; - } - if (SvNOKp(sv)) { - Gconvert(SvNVX(sv), NV_DIG, 0, tmpbuf); - tsv = Nullsv; - goto tokensave; - } - if (!SvROK(sv)) { - if (!(SvFLAGS(sv) & SVs_PADTMP)) { - if (ckWARN(WARN_UNINITIALIZED) && !PL_localizing) - report_uninit(); - } - *lp = 0; - return ""; - } - } - if (SvTHINKFIRST(sv)) { - if (SvROK(sv)) { - SV* tmpstr; - if (SvAMAGIC(sv) && (tmpstr=AMG_CALLun(sv,string)) && - (SvRV(tmpstr) != SvRV(sv))) - return SvPV(tmpstr,*lp); - sv = (SV*)SvRV(sv); - if (!sv) - s = "NULLREF"; - else { - MAGIC *mg; - - switch (SvTYPE(sv)) { - case SVt_PVMG: - if ( ((SvFLAGS(sv) & - (SVs_OBJECT|SVf_OK|SVs_GMG|SVs_SMG|SVs_RMG)) - == (SVs_OBJECT|SVs_RMG)) - && strEQ(s=HvNAME(SvSTASH(sv)), "Regexp") - && (mg = mg_find(sv, 'r'))) { - regexp *re = (regexp *)mg->mg_obj; - - if (!mg->mg_ptr) { - char *fptr = "msix"; - char reflags[6]; - char ch; - int left = 0; - int right = 4; - U16 reganch = (re->reganch & PMf_COMPILETIME) >> 12; - - while((ch = *fptr++)) { - if(reganch & 1) { - reflags[left++] = ch; - } - else { - reflags[right--] = ch; - } - reganch >>= 1; - } - if(left != 4) { - reflags[left] = '-'; - left = 5; - } - - mg->mg_len = re->prelen + 4 + left; - New(616, mg->mg_ptr, mg->mg_len + 1 + left, char); - Copy("(?", mg->mg_ptr, 2, char); - Copy(reflags, mg->mg_ptr+2, left, char); - Copy(":", mg->mg_ptr+left+2, 1, char); - Copy(re->precomp, mg->mg_ptr+3+left, re->prelen, char); - mg->mg_ptr[mg->mg_len - 1] = ')'; - mg->mg_ptr[mg->mg_len] = 0; - } - PL_reginterp_cnt += re->program[0].next_off; - *lp = mg->mg_len; - return mg->mg_ptr; - } - /* Fall through */ - case SVt_NULL: - case SVt_IV: - case SVt_NV: - case SVt_RV: - case SVt_PV: - case SVt_PVIV: - case SVt_PVNV: - case SVt_PVBM: s = "SCALAR"; break; - case SVt_PVLV: s = "LVALUE"; break; - case SVt_PVAV: s = "ARRAY"; break; - case SVt_PVHV: s = "HASH"; break; - case SVt_PVCV: s = "CODE"; break; - case SVt_PVGV: s = "GLOB"; break; - case SVt_PVFM: s = "FORMAT"; break; - case SVt_PVIO: s = "IO"; break; - default: s = "UNKNOWN"; break; - } - tsv = NEWSV(0,0); - if (SvOBJECT(sv)) - Perl_sv_setpvf(aTHX_ tsv, "%s=%s", HvNAME(SvSTASH(sv)), s); - else - sv_setpv(tsv, s); - Perl_sv_catpvf(aTHX_ tsv, "(0x%"UVxf")", PTR2UV(sv)); - goto tokensaveref; - } - *lp = strlen(s); - return s; - } - if (SvREADONLY(sv) && !SvOK(sv)) { - if (ckWARN(WARN_UNINITIALIZED)) - report_uninit(); - *lp = 0; - return ""; - } - } - if (SvNOKp(sv)) { /* See note in sv_2uv() */ - /* XXXX 64-bit? IV may have better precision... */ - /* I tried changing this to be 64-bit-aware and - * the t/op/numconvert.t became very, very, angry. - * --jhi Sep 1999 */ - if (SvTYPE(sv) < SVt_PVNV) - sv_upgrade(sv, SVt_PVNV); - /* The +20 is pure guesswork. Configure test needed. --jhi */ - SvGROW(sv, NV_DIG + 20); - s = SvPVX(sv); - olderrno = errno; /* some Xenix systems wipe out errno here */ -#ifdef apollo - if (SvNVX(sv) == 0.0) - (void)strcpy(s,"0"); - else -#endif /*apollo*/ - { - Gconvert(SvNVX(sv), NV_DIG, 0, s); - } - errno = olderrno; -#ifdef FIXNEGATIVEZERO - if (*s == '-' && s[1] == '0' && !s[2]) - strcpy(s,"0"); -#endif - while (*s) s++; -#ifdef hcx - if (s[-1] == '.') - *--s = '\0'; -#endif - } - else if (SvIOKp(sv)) { - U32 isIOK = SvIOK(sv); - U32 isUIOK = SvIsUV(sv); - char buf[TYPE_CHARS(UV)]; - char *ebuf, *ptr; - - if (SvTYPE(sv) < SVt_PVIV) - sv_upgrade(sv, SVt_PVIV); - if (isUIOK) - ptr = uiv_2buf(buf, 0, SvUVX(sv), 1, &ebuf); - else - ptr = uiv_2buf(buf, SvIVX(sv), 0, 0, &ebuf); - SvGROW(sv, ebuf - ptr + 1); /* inlined from sv_setpvn */ - Move(ptr,SvPVX(sv),ebuf - ptr,char); - SvCUR_set(sv, ebuf - ptr); - s = SvEND(sv); - *s = '\0'; - if (isIOK) - SvIOK_on(sv); - else - SvIOKp_on(sv); - if (isUIOK) - SvIsUV_on(sv); - SvPOK_on(sv); - } - else { - if (ckWARN(WARN_UNINITIALIZED) - && !PL_localizing && !(SvFLAGS(sv) & SVs_PADTMP)) - report_uninit(); - *lp = 0; - if (SvTYPE(sv) < SVt_PV) - /* Typically the caller expects that sv_any is not NULL now. */ - sv_upgrade(sv, SVt_PV); - return ""; - } - *lp = s - SvPVX(sv); - SvCUR_set(sv, *lp); - SvPOK_on(sv); - DEBUG_c(PerlIO_printf(Perl_debug_log, "0x%"UVxf" 2pv(%s)\n", - PTR2UV(sv),SvPVX(sv))); - return SvPVX(sv); - - tokensave: - if (SvROK(sv)) { /* XXX Skip this when sv_pvn_force calls */ - /* Sneaky stuff here */ - - tokensaveref: - if (!tsv) - tsv = newSVpv(tmpbuf, 0); - sv_2mortal(tsv); - *lp = SvCUR(tsv); - return SvPVX(tsv); - } - else { - STRLEN len; - char *t; - - if (tsv) { - sv_2mortal(tsv); - t = SvPVX(tsv); - len = SvCUR(tsv); - } - else { - t = tmpbuf; - len = strlen(tmpbuf); - } -#ifdef FIXNEGATIVEZERO - if (len == 2 && t[0] == '-' && t[1] == '0') { - t = "0"; - len = 1; - } -#endif - (void)SvUPGRADE(sv, SVt_PV); - *lp = len; - s = SvGROW(sv, len + 1); - SvCUR_set(sv, len); - (void)strcpy(s, t); - SvPOKp_on(sv); - return s; - } -} - -char * -Perl_sv_2pvbyte_nolen(pTHX_ register SV *sv) -{ - STRLEN n_a; - return sv_2pvbyte(sv, &n_a); -} - -char * -Perl_sv_2pvbyte(pTHX_ register SV *sv, STRLEN *lp) -{ - return sv_2pv(sv,lp); -} - -char * -Perl_sv_2pvutf8_nolen(pTHX_ register SV *sv) -{ - STRLEN n_a; - return sv_2pvutf8(sv, &n_a); -} - -char * -Perl_sv_2pvutf8(pTHX_ register SV *sv, STRLEN *lp) -{ - sv_utf8_upgrade(sv); - return SvPV(sv,*lp); -} - -/* This function is only called on magical items */ -bool -Perl_sv_2bool(pTHX_ register SV *sv) -{ - if (SvGMAGICAL(sv)) - mg_get(sv); - - if (!SvOK(sv)) - return 0; - if (SvROK(sv)) { - SV* tmpsv; - if (SvAMAGIC(sv) && (tmpsv=AMG_CALLun(sv,bool_)) && - (SvRV(tmpsv) != SvRV(sv))) - return SvTRUE(tmpsv); - return SvRV(sv) != 0; - } - if (SvPOKp(sv)) { - register XPV* Xpvtmp; - if ((Xpvtmp = (XPV*)SvANY(sv)) && - (*Xpvtmp->xpv_pv > '0' || - Xpvtmp->xpv_cur > 1 || - (Xpvtmp->xpv_cur && *Xpvtmp->xpv_pv != '0'))) - return 1; - else - return 0; - } - else { - if (SvIOKp(sv)) - return SvIVX(sv) != 0; - else { - if (SvNOKp(sv)) - return SvNVX(sv) != 0.0; - else - return FALSE; - } - } -} - -/* -=for apidoc sv_utf8_upgrade - -Convert the PV of an SV to its UTF8-encoded form. - -=cut -*/ - -void -Perl_sv_utf8_upgrade(pTHX_ register SV *sv) -{ - char *s, *t, *e; - int hibit = 0; - - if (!sv || !SvPOK(sv) || SvUTF8(sv)) - return; - - /* This function could be much more efficient if we had a FLAG in SVs - * to signal if there are any hibit chars in the PV. - * Given that there isn't make loop fast as possible - */ - s = SvPVX(sv); - e = SvEND(sv); - t = s; - while (t < e) { - if ((hibit = UTF8_IS_CONTINUED(*t++))) - break; - } - - if (hibit) { - STRLEN len; - - if (SvREADONLY(sv) && SvFAKE(sv)) { - sv_force_normal(sv); - s = SvPVX(sv); - } - len = SvCUR(sv) + 1; /* Plus the \0 */ - SvPVX(sv) = (char*)bytes_to_utf8((U8*)s, &len); - SvCUR(sv) = len - 1; - if (SvLEN(sv) != 0) - Safefree(s); /* No longer using what was there before. */ - SvLEN(sv) = len; /* No longer know the real size. */ - SvUTF8_on(sv); - } -} - -/* -=for apidoc sv_utf8_downgrade - -Attempt to convert the PV of an SV from UTF8-encoded to byte encoding. -This may not be possible if the PV contains non-byte encoding characters; -if this is the case, either returns false or, if C<fail_ok> is not -true, croaks. - -=cut -*/ - -bool -Perl_sv_utf8_downgrade(pTHX_ register SV* sv, bool fail_ok) -{ - if (SvPOK(sv) && SvUTF8(sv)) { - if (SvCUR(sv)) { - char *s; - STRLEN len; - - if (SvREADONLY(sv) && SvFAKE(sv)) - sv_force_normal(sv); - s = SvPV(sv, len); - if (!utf8_to_bytes((U8*)s, &len)) { - if (fail_ok) - return FALSE; - else { - if (PL_op) - Perl_croak(aTHX_ "Wide character in %s", - PL_op_desc[PL_op->op_type]); - else - Perl_croak(aTHX_ "Wide character"); - } - } - SvCUR(sv) = len; - } - SvUTF8_off(sv); - } - - return TRUE; -} - -/* -=for apidoc sv_utf8_encode - -Convert the PV of an SV to UTF8-encoded, but then turn off the C<SvUTF8> -flag so that it looks like bytes again. Nothing calls this. - -=cut -*/ - -void -Perl_sv_utf8_encode(pTHX_ register SV *sv) -{ - sv_utf8_upgrade(sv); - SvUTF8_off(sv); -} - -bool -Perl_sv_utf8_decode(pTHX_ register SV *sv) -{ - if (SvPOK(sv)) { - char *c; - char *e; - bool has_utf = FALSE; - if (!sv_utf8_downgrade(sv, TRUE)) - return FALSE; - - /* it is actually just a matter of turning the utf8 flag on, but - * we want to make sure everything inside is valid utf8 first. - */ - c = SvPVX(sv); - if (!is_utf8_string((U8*)c, SvCUR(sv)+1)) - return FALSE; - e = SvEND(sv); - while (c < e) { - if (UTF8_IS_CONTINUED(*c++)) { - SvUTF8_on(sv); - break; - } - } - } - return TRUE; -} - - -/* Note: sv_setsv() should not be called with a source string that needs - * to be reused, since it may destroy the source string if it is marked - * as temporary. - */ - -/* -=for apidoc sv_setsv - -Copies the contents of the source SV C<ssv> into the destination SV C<dsv>. -The source SV may be destroyed if it is mortal. Does not handle 'set' -magic. See the macro forms C<SvSetSV>, C<SvSetSV_nosteal> and -C<sv_setsv_mg>. - -=cut -*/ - -void -Perl_sv_setsv(pTHX_ SV *dstr, register SV *sstr) -{ - register U32 sflags; - register int dtype; - register int stype; - - if (sstr == dstr) - return; - SV_CHECK_THINKFIRST(dstr); - if (!sstr) - sstr = &PL_sv_undef; - stype = SvTYPE(sstr); - dtype = SvTYPE(dstr); - - SvAMAGIC_off(dstr); - - /* There's a lot of redundancy below but we're going for speed here */ - - switch (stype) { - case SVt_NULL: - undef_sstr: - if (dtype != SVt_PVGV) { - (void)SvOK_off(dstr); - return; - } - break; - case SVt_IV: - if (SvIOK(sstr)) { - switch (dtype) { - case SVt_NULL: - sv_upgrade(dstr, SVt_IV); - break; - case SVt_NV: - sv_upgrade(dstr, SVt_PVNV); - break; - case SVt_RV: - case SVt_PV: - sv_upgrade(dstr, SVt_PVIV); - break; - } - (void)SvIOK_only(dstr); - SvIVX(dstr) = SvIVX(sstr); - if (SvIsUV(sstr)) - SvIsUV_on(dstr); - if (SvTAINTED(sstr)) - SvTAINT(dstr); - return; - } - goto undef_sstr; - - case SVt_NV: - if (SvNOK(sstr)) { - switch (dtype) { - case SVt_NULL: - case SVt_IV: - sv_upgrade(dstr, SVt_NV); - break; - case SVt_RV: - case SVt_PV: - case SVt_PVIV: - sv_upgrade(dstr, SVt_PVNV); - break; - } - SvNVX(dstr) = SvNVX(sstr); - (void)SvNOK_only(dstr); - if (SvTAINTED(sstr)) - SvTAINT(dstr); - return; - } - goto undef_sstr; - - case SVt_RV: - if (dtype < SVt_RV) - sv_upgrade(dstr, SVt_RV); - else if (dtype == SVt_PVGV && - SvTYPE(SvRV(sstr)) == SVt_PVGV) { - sstr = SvRV(sstr); - if (sstr == dstr) { - if (GvIMPORTED(dstr) != GVf_IMPORTED - && CopSTASH_ne(PL_curcop, GvSTASH(dstr))) - { - GvIMPORTED_on(dstr); - } - GvMULTI_on(dstr); - return; - } - goto glob_assign; - } - break; - case SVt_PV: - case SVt_PVFM: - if (dtype < SVt_PV) - sv_upgrade(dstr, SVt_PV); - break; - case SVt_PVIV: - if (dtype < SVt_PVIV) - sv_upgrade(dstr, SVt_PVIV); - break; - case SVt_PVNV: - if (dtype < SVt_PVNV) - sv_upgrade(dstr, SVt_PVNV); - break; - case SVt_PVAV: - case SVt_PVHV: - case SVt_PVCV: - case SVt_PVIO: - if (PL_op) - Perl_croak(aTHX_ "Bizarre copy of %s in %s", sv_reftype(sstr, 0), - PL_op_name[PL_op->op_type]); - else - Perl_croak(aTHX_ "Bizarre copy of %s", sv_reftype(sstr, 0)); - break; - - case SVt_PVGV: - if (dtype <= SVt_PVGV) { - glob_assign: - if (dtype != SVt_PVGV) { - char *name = GvNAME(sstr); - STRLEN len = GvNAMELEN(sstr); - sv_upgrade(dstr, SVt_PVGV); - sv_magic(dstr, dstr, '*', Nullch, 0); - GvSTASH(dstr) = (HV*)SvREFCNT_inc(GvSTASH(sstr)); - GvNAME(dstr) = savepvn(name, len); - GvNAMELEN(dstr) = len; - SvFAKE_on(dstr); /* can coerce to non-glob */ - } - /* ahem, death to those who redefine active sort subs */ - else if (PL_curstackinfo->si_type == PERLSI_SORT - && GvCV(dstr) && PL_sortcop == CvSTART(GvCV(dstr))) - Perl_croak(aTHX_ "Can't redefine active sort subroutine %s", - GvNAME(dstr)); - (void)SvOK_off(dstr); - GvINTRO_off(dstr); /* one-shot flag */ - gp_free((GV*)dstr); - GvGP(dstr) = gp_ref(GvGP(sstr)); - if (SvTAINTED(sstr)) - SvTAINT(dstr); - if (GvIMPORTED(dstr) != GVf_IMPORTED - && CopSTASH_ne(PL_curcop, GvSTASH(dstr))) - { - GvIMPORTED_on(dstr); - } - GvMULTI_on(dstr); - return; - } - /* FALL THROUGH */ - - default: - if (SvGMAGICAL(sstr)) { - mg_get(sstr); - if (SvTYPE(sstr) != stype) { - stype = SvTYPE(sstr); - if (stype == SVt_PVGV && dtype <= SVt_PVGV) - goto glob_assign; - } - } - if (stype == SVt_PVLV) - (void)SvUPGRADE(dstr, SVt_PVNV); - else - (void)SvUPGRADE(dstr, stype); - } - - sflags = SvFLAGS(sstr); - - if (sflags & SVf_ROK) { - if (dtype >= SVt_PV) { - if (dtype == SVt_PVGV) { - SV *sref = SvREFCNT_inc(SvRV(sstr)); - SV *dref = 0; - int intro = GvINTRO(dstr); - - if (intro) { - GP *gp; - gp_free((GV*)dstr); - GvINTRO_off(dstr); /* one-shot flag */ - Newz(602,gp, 1, GP); - GvGP(dstr) = gp_ref(gp); - GvSV(dstr) = NEWSV(72,0); - GvLINE(dstr) = CopLINE(PL_curcop); - GvEGV(dstr) = (GV*)dstr; - } - GvMULTI_on(dstr); - switch (SvTYPE(sref)) { - case SVt_PVAV: - if (intro) - SAVESPTR(GvAV(dstr)); - else - dref = (SV*)GvAV(dstr); - GvAV(dstr) = (AV*)sref; - if (!GvIMPORTED_AV(dstr) - && CopSTASH_ne(PL_curcop, GvSTASH(dstr))) - { - GvIMPORTED_AV_on(dstr); - } - break; - case SVt_PVHV: - if (intro) - SAVESPTR(GvHV(dstr)); - else - dref = (SV*)GvHV(dstr); - GvHV(dstr) = (HV*)sref; - if (!GvIMPORTED_HV(dstr) - && CopSTASH_ne(PL_curcop, GvSTASH(dstr))) - { - GvIMPORTED_HV_on(dstr); - } - break; - case SVt_PVCV: - if (intro) { - if (GvCVGEN(dstr) && GvCV(dstr) != (CV*)sref) { - SvREFCNT_dec(GvCV(dstr)); - GvCV(dstr) = Nullcv; - GvCVGEN(dstr) = 0; /* Switch off cacheness. */ - PL_sub_generation++; - } - SAVESPTR(GvCV(dstr)); - } - else - dref = (SV*)GvCV(dstr); - if (GvCV(dstr) != (CV*)sref) { - CV* cv = GvCV(dstr); - if (cv) { - if (!GvCVGEN((GV*)dstr) && - (CvROOT(cv) || CvXSUB(cv))) - { - SV *const_sv = cv_const_sv(cv); - bool const_changed = TRUE; - if(const_sv) - const_changed = sv_cmp(const_sv, - op_const_sv(CvSTART((CV*)sref), - Nullcv)); - /* ahem, death to those who redefine - * active sort subs */ - if (PL_curstackinfo->si_type == PERLSI_SORT && - PL_sortcop == CvSTART(cv)) - Perl_croak(aTHX_ - "Can't redefine active sort subroutine %s", - GvENAME((GV*)dstr)); - if ((const_changed || const_sv) && ckWARN(WARN_REDEFINE)) - Perl_warner(aTHX_ WARN_REDEFINE, const_sv ? - "Constant subroutine %s redefined" - : "Subroutine %s redefined", - GvENAME((GV*)dstr)); - } - cv_ckproto(cv, (GV*)dstr, - SvPOK(sref) ? SvPVX(sref) : Nullch); - } - GvCV(dstr) = (CV*)sref; - GvCVGEN(dstr) = 0; /* Switch off cacheness. */ - GvASSUMECV_on(dstr); - PL_sub_generation++; - } - if (!GvIMPORTED_CV(dstr) - && CopSTASH_ne(PL_curcop, GvSTASH(dstr))) - { - GvIMPORTED_CV_on(dstr); - } - break; - case SVt_PVIO: - if (intro) - SAVESPTR(GvIOp(dstr)); - else - dref = (SV*)GvIOp(dstr); - GvIOp(dstr) = (IO*)sref; - break; - default: - if (intro) - SAVESPTR(GvSV(dstr)); - else - dref = (SV*)GvSV(dstr); - GvSV(dstr) = sref; - if (!GvIMPORTED_SV(dstr) - && CopSTASH_ne(PL_curcop, GvSTASH(dstr))) - { - GvIMPORTED_SV_on(dstr); - } - break; - } - if (dref) - SvREFCNT_dec(dref); - if (intro) - SAVEFREESV(sref); - if (SvTAINTED(sstr)) - SvTAINT(dstr); - return; - } - if (SvPVX(dstr)) { - (void)SvOOK_off(dstr); /* backoff */ - if (SvLEN(dstr)) - Safefree(SvPVX(dstr)); - SvLEN(dstr)=SvCUR(dstr)=0; - } - } - (void)SvOK_off(dstr); - SvRV(dstr) = SvREFCNT_inc(SvRV(sstr)); - SvROK_on(dstr); - if (sflags & SVp_NOK) { - SvNOK_on(dstr); - SvNVX(dstr) = SvNVX(sstr); - } - if (sflags & SVp_IOK) { - (void)SvIOK_on(dstr); - SvIVX(dstr) = SvIVX(sstr); - if (sflags & SVf_IVisUV) - SvIsUV_on(dstr); - } - if (SvAMAGIC(sstr)) { - SvAMAGIC_on(dstr); - } - } - else if (sflags & SVp_POK) { - - /* - * Check to see if we can just swipe the string. If so, it's a - * possible small lose on short strings, but a big win on long ones. - * It might even be a win on short strings if SvPVX(dstr) - * has to be allocated and SvPVX(sstr) has to be freed. - */ - - if (SvTEMP(sstr) && /* slated for free anyway? */ - SvREFCNT(sstr) == 1 && /* and no other references to it? */ - !(sflags & SVf_OOK)) /* and not involved in OOK hack? */ - { - if (SvPVX(dstr)) { /* we know that dtype >= SVt_PV */ - if (SvOOK(dstr)) { - SvFLAGS(dstr) &= ~SVf_OOK; - Safefree(SvPVX(dstr) - SvIVX(dstr)); - } - else if (SvLEN(dstr)) - Safefree(SvPVX(dstr)); - } - (void)SvPOK_only(dstr); - SvPV_set(dstr, SvPVX(sstr)); - SvLEN_set(dstr, SvLEN(sstr)); - SvCUR_set(dstr, SvCUR(sstr)); - - SvTEMP_off(dstr); - (void)SvOK_off(sstr); /* NOTE: nukes most SvFLAGS on sstr */ - SvPV_set(sstr, Nullch); - SvLEN_set(sstr, 0); - SvCUR_set(sstr, 0); - SvTEMP_off(sstr); - } - else { /* have to copy actual string */ - STRLEN len = SvCUR(sstr); - - SvGROW(dstr, len + 1); /* inlined from sv_setpvn */ - Move(SvPVX(sstr),SvPVX(dstr),len,char); - SvCUR_set(dstr, len); - *SvEND(dstr) = '\0'; - (void)SvPOK_only(dstr); - } - if (sflags & SVf_UTF8) - SvUTF8_on(dstr); - /*SUPPRESS 560*/ - if (sflags & SVp_NOK) { - SvNOK_on(dstr); - SvNVX(dstr) = SvNVX(sstr); - } - if (sflags & SVp_IOK) { - (void)SvIOK_on(dstr); - SvIVX(dstr) = SvIVX(sstr); - if (sflags & SVf_IVisUV) - SvIsUV_on(dstr); - } - } - else if (sflags & SVp_NOK) { - SvNVX(dstr) = SvNVX(sstr); - (void)SvNOK_only(dstr); - if (sflags & SVf_IOK) { - (void)SvIOK_on(dstr); - SvIVX(dstr) = SvIVX(sstr); - /* XXXX Do we want to set IsUV for IV(ROK)? Be extra safe... */ - if (sflags & SVf_IVisUV) - SvIsUV_on(dstr); - } - } - else if (sflags & SVp_IOK) { - (void)SvIOK_only(dstr); - SvIVX(dstr) = SvIVX(sstr); - if (sflags & SVf_IVisUV) - SvIsUV_on(dstr); - } - else { - if (dtype == SVt_PVGV) { - if (ckWARN(WARN_MISC)) - Perl_warner(aTHX_ WARN_MISC, "Undefined value assigned to typeglob"); - } - else - (void)SvOK_off(dstr); - } - if (SvTAINTED(sstr)) - SvTAINT(dstr); -} - -/* -=for apidoc sv_setsv_mg - -Like C<sv_setsv>, but also handles 'set' magic. - -=cut -*/ - -void -Perl_sv_setsv_mg(pTHX_ SV *dstr, register SV *sstr) -{ - sv_setsv(dstr,sstr); - SvSETMAGIC(dstr); -} - -/* -=for apidoc sv_setpvn - -Copies a string into an SV. The C<len> parameter indicates the number of -bytes to be copied. Does not handle 'set' magic. See C<sv_setpvn_mg>. - -=cut -*/ - -void -Perl_sv_setpvn(pTHX_ register SV *sv, register const char *ptr, register STRLEN len) -{ - register char *dptr; - - SV_CHECK_THINKFIRST(sv); - if (!ptr) { - (void)SvOK_off(sv); - return; - } - else { - /* len is STRLEN which is unsigned, need to copy to signed */ - IV iv = len; - assert(iv >= 0); - } - (void)SvUPGRADE(sv, SVt_PV); - - SvGROW(sv, len + 1); - dptr = SvPVX(sv); - Move(ptr,dptr,len,char); - dptr[len] = '\0'; - SvCUR_set(sv, len); - (void)SvPOK_only(sv); /* validate pointer */ - SvTAINT(sv); -} - -/* -=for apidoc sv_setpvn_mg - -Like C<sv_setpvn>, but also handles 'set' magic. - -=cut -*/ - -void -Perl_sv_setpvn_mg(pTHX_ register SV *sv, register const char *ptr, register STRLEN len) -{ - sv_setpvn(sv,ptr,len); - SvSETMAGIC(sv); -} - -/* -=for apidoc sv_setpv - -Copies a string into an SV. The string must be null-terminated. Does not -handle 'set' magic. See C<sv_setpv_mg>. - -=cut -*/ - -void -Perl_sv_setpv(pTHX_ register SV *sv, register const char *ptr) -{ - register STRLEN len; - - SV_CHECK_THINKFIRST(sv); - if (!ptr) { - (void)SvOK_off(sv); - return; - } - len = strlen(ptr); - (void)SvUPGRADE(sv, SVt_PV); - - SvGROW(sv, len + 1); - Move(ptr,SvPVX(sv),len+1,char); - SvCUR_set(sv, len); - (void)SvPOK_only(sv); /* validate pointer */ - SvTAINT(sv); -} - -/* -=for apidoc sv_setpv_mg - -Like C<sv_setpv>, but also handles 'set' magic. - -=cut -*/ - -void -Perl_sv_setpv_mg(pTHX_ register SV *sv, register const char *ptr) -{ - sv_setpv(sv,ptr); - SvSETMAGIC(sv); -} - -/* -=for apidoc sv_usepvn - -Tells an SV to use C<ptr> to find its string value. Normally the string is -stored inside the SV but sv_usepvn allows the SV to use an outside string. -The C<ptr> should point to memory that was allocated by C<malloc>. The -string length, C<len>, must be supplied. This function will realloc the -memory pointed to by C<ptr>, so that pointer should not be freed or used by -the programmer after giving it to sv_usepvn. Does not handle 'set' magic. -See C<sv_usepvn_mg>. - -=cut -*/ - -void -Perl_sv_usepvn(pTHX_ register SV *sv, register char *ptr, register STRLEN len) -{ - SV_CHECK_THINKFIRST(sv); - (void)SvUPGRADE(sv, SVt_PV); - if (!ptr) { - (void)SvOK_off(sv); - return; - } - (void)SvOOK_off(sv); - if (SvPVX(sv) && SvLEN(sv)) - Safefree(SvPVX(sv)); - Renew(ptr, len+1, char); - SvPVX(sv) = ptr; - SvCUR_set(sv, len); - SvLEN_set(sv, len+1); - *SvEND(sv) = '\0'; - (void)SvPOK_only(sv); /* validate pointer */ - SvTAINT(sv); -} - -/* -=for apidoc sv_usepvn_mg - -Like C<sv_usepvn>, but also handles 'set' magic. - -=cut -*/ - -void -Perl_sv_usepvn_mg(pTHX_ register SV *sv, register char *ptr, register STRLEN len) -{ - sv_usepvn(sv,ptr,len); - SvSETMAGIC(sv); -} - -void -Perl_sv_force_normal(pTHX_ register SV *sv) -{ - if (SvREADONLY(sv)) { - if (PL_curcop != &PL_compiling) - Perl_croak(aTHX_ PL_no_modify); - } - if (SvROK(sv)) - sv_unref(sv); - else if (SvFAKE(sv) && SvTYPE(sv) == SVt_PVGV) - sv_unglob(sv); -} - -/* -=for apidoc sv_chop - -Efficient removal of characters from the beginning of the string buffer. -SvPOK(sv) must be true and the C<ptr> must be a pointer to somewhere inside -the string buffer. The C<ptr> becomes the first character of the adjusted -string. - -=cut -*/ - -void -Perl_sv_chop(pTHX_ register SV *sv, register char *ptr) /* like set but assuming ptr is in sv */ - - -{ - register STRLEN delta; - - if (!ptr || !SvPOKp(sv)) - return; - SV_CHECK_THINKFIRST(sv); - if (SvTYPE(sv) < SVt_PVIV) - sv_upgrade(sv,SVt_PVIV); - - if (!SvOOK(sv)) { - if (!SvLEN(sv)) { /* make copy of shared string */ - char *pvx = SvPVX(sv); - STRLEN len = SvCUR(sv); - SvGROW(sv, len + 1); - Move(pvx,SvPVX(sv),len,char); - *SvEND(sv) = '\0'; - } - SvIVX(sv) = 0; - SvFLAGS(sv) |= SVf_OOK; - } - SvFLAGS(sv) &= ~(SVf_IOK|SVf_NOK|SVp_IOK|SVp_NOK|SVf_IVisUV); - delta = ptr - SvPVX(sv); - SvLEN(sv) -= delta; - SvCUR(sv) -= delta; - SvPVX(sv) += delta; - SvIVX(sv) += delta; -} - -/* -=for apidoc sv_catpvn - -Concatenates the string onto the end of the string which is in the SV. The -C<len> indicates number of bytes to copy. Handles 'get' magic, but not -'set' magic. See C<sv_catpvn_mg>. - -=cut -*/ - -void -Perl_sv_catpvn(pTHX_ register SV *sv, register const char *ptr, register STRLEN len) -{ - STRLEN tlen; - char *junk; - - junk = SvPV_force(sv, tlen); - SvGROW(sv, tlen + len + 1); - if (ptr == junk) - ptr = SvPVX(sv); - Move(ptr,SvPVX(sv)+tlen,len,char); - SvCUR(sv) += len; - *SvEND(sv) = '\0'; - (void)SvPOK_only_UTF8(sv); /* validate pointer */ - SvTAINT(sv); -} - -/* -=for apidoc sv_catpvn_mg - -Like C<sv_catpvn>, but also handles 'set' magic. - -=cut -*/ - -void -Perl_sv_catpvn_mg(pTHX_ register SV *sv, register const char *ptr, register STRLEN len) -{ - sv_catpvn(sv,ptr,len); - SvSETMAGIC(sv); -} - -/* -=for apidoc sv_catsv - -Concatenates the string from SV C<ssv> onto the end of the string in -SV C<dsv>. Modifies C<dsv> but not C<ssv>. Handles 'get' magic, but -not 'set' magic. See C<sv_catsv_mg>. - -=cut */ - -void -Perl_sv_catsv(pTHX_ SV *dstr, register SV *sstr) -{ - char *spv; - STRLEN slen; - if (!sstr) - return; - if ((spv = SvPV(sstr, slen))) { - bool dutf8 = DO_UTF8(dstr); - bool sutf8 = DO_UTF8(sstr); - - if (dutf8 == sutf8) - sv_catpvn(dstr,spv,slen); - else { - if (dutf8) { - SV* cstr = newSVsv(sstr); - char *cpv; - STRLEN clen; - - sv_utf8_upgrade(cstr); - cpv = SvPV(cstr,clen); - sv_catpvn(dstr,cpv,clen); - sv_2mortal(cstr); - } - else { - sv_utf8_upgrade(dstr); - sv_catpvn(dstr,spv,slen); - SvUTF8_on(dstr); - } - } - } -} - -/* -=for apidoc sv_catsv_mg - -Like C<sv_catsv>, but also handles 'set' magic. - -=cut -*/ - -void -Perl_sv_catsv_mg(pTHX_ SV *dstr, register SV *sstr) -{ - sv_catsv(dstr,sstr); - SvSETMAGIC(dstr); -} - -/* -=for apidoc sv_catpv - -Concatenates the string onto the end of the string which is in the SV. -Handles 'get' magic, but not 'set' magic. See C<sv_catpv_mg>. - -=cut -*/ - -void -Perl_sv_catpv(pTHX_ register SV *sv, register const char *ptr) -{ - register STRLEN len; - STRLEN tlen; - char *junk; - - if (!ptr) - return; - junk = SvPV_force(sv, tlen); - len = strlen(ptr); - SvGROW(sv, tlen + len + 1); - if (ptr == junk) - ptr = SvPVX(sv); - Move(ptr,SvPVX(sv)+tlen,len+1,char); - SvCUR(sv) += len; - (void)SvPOK_only_UTF8(sv); /* validate pointer */ - SvTAINT(sv); -} - -/* -=for apidoc sv_catpv_mg - -Like C<sv_catpv>, but also handles 'set' magic. - -=cut -*/ - -void -Perl_sv_catpv_mg(pTHX_ register SV *sv, register const char *ptr) -{ - sv_catpv(sv,ptr); - SvSETMAGIC(sv); -} - -SV * -Perl_newSV(pTHX_ STRLEN len) -{ - register SV *sv; - - new_SV(sv); - if (len) { - sv_upgrade(sv, SVt_PV); - SvGROW(sv, len + 1); - } - return sv; -} - -/* name is assumed to contain an SV* if (name && namelen == HEf_SVKEY) */ - -/* -=for apidoc sv_magic - -Adds magic to an SV. - -=cut -*/ - -void -Perl_sv_magic(pTHX_ register SV *sv, SV *obj, int how, const char *name, I32 namlen) -{ - MAGIC* mg; - - if (SvREADONLY(sv)) { - if (PL_curcop != &PL_compiling && !strchr("gBf", how)) - Perl_croak(aTHX_ PL_no_modify); - } - if (SvMAGICAL(sv) || (how == 't' && SvTYPE(sv) >= SVt_PVMG)) { - if (SvMAGIC(sv) && (mg = mg_find(sv, how))) { - if (how == 't') - mg->mg_len |= 1; - return; - } - } - else { - (void)SvUPGRADE(sv, SVt_PVMG); - } - Newz(702,mg, 1, MAGIC); - mg->mg_moremagic = SvMAGIC(sv); - SvMAGIC(sv) = mg; - - /* Some magic sontains a reference loop, where the sv and object refer to - each other. To prevent a avoid a reference loop that would prevent such - objects being freed, we look for such loops and if we find one we avoid - incrementing the object refcount. */ - if (!obj || obj == sv || how == '#' || how == 'r' || - (SvTYPE(obj) == SVt_PVGV && - (GvSV(obj) == sv || GvHV(obj) == (HV*)sv || GvAV(obj) == (AV*)sv || - GvCV(obj) == (CV*)sv || GvIOp(obj) == (IO*)sv || - GvFORM(obj) == (CV*)sv))) - { - mg->mg_obj = obj; - } - else { - mg->mg_obj = SvREFCNT_inc(obj); - mg->mg_flags |= MGf_REFCOUNTED; - } - mg->mg_type = how; - mg->mg_len = namlen; - if (name) - if (namlen >= 0) - mg->mg_ptr = savepvn(name, namlen); - else if (namlen == HEf_SVKEY) - mg->mg_ptr = (char*)SvREFCNT_inc((SV*)name); - - switch (how) { - case 0: - mg->mg_virtual = &PL_vtbl_sv; - break; - case 'A': - mg->mg_virtual = &PL_vtbl_amagic; - break; - case 'a': - mg->mg_virtual = &PL_vtbl_amagicelem; - break; - case 'c': - mg->mg_virtual = 0; - break; - case 'B': - mg->mg_virtual = &PL_vtbl_bm; - break; - case 'D': - mg->mg_virtual = &PL_vtbl_regdata; - break; - case 'd': - mg->mg_virtual = &PL_vtbl_regdatum; - break; - case 'E': - mg->mg_virtual = &PL_vtbl_env; - break; - case 'f': - mg->mg_virtual = &PL_vtbl_fm; - break; - case 'e': - mg->mg_virtual = &PL_vtbl_envelem; - break; - case 'g': - mg->mg_virtual = &PL_vtbl_mglob; - break; - case 'I': - mg->mg_virtual = &PL_vtbl_isa; - break; - case 'i': - mg->mg_virtual = &PL_vtbl_isaelem; - break; - case 'k': - mg->mg_virtual = &PL_vtbl_nkeys; - break; - case 'L': - SvRMAGICAL_on(sv); - mg->mg_virtual = 0; - break; - case 'l': - mg->mg_virtual = &PL_vtbl_dbline; - break; -#ifdef USE_THREADS - case 'm': - mg->mg_virtual = &PL_vtbl_mutex; - break; -#endif /* USE_THREADS */ -#ifdef USE_LOCALE_COLLATE - case 'o': - mg->mg_virtual = &PL_vtbl_collxfrm; - break; -#endif /* USE_LOCALE_COLLATE */ - case 'P': - mg->mg_virtual = &PL_vtbl_pack; - break; - case 'p': - case 'q': - mg->mg_virtual = &PL_vtbl_packelem; - break; - case 'r': - mg->mg_virtual = &PL_vtbl_regexp; - break; - case 'S': - mg->mg_virtual = &PL_vtbl_sig; - break; - case 's': - mg->mg_virtual = &PL_vtbl_sigelem; - break; - case 't': - mg->mg_virtual = &PL_vtbl_taint; - mg->mg_len = 1; - break; - case 'U': - mg->mg_virtual = &PL_vtbl_uvar; - break; - case 'v': - mg->mg_virtual = &PL_vtbl_vec; - break; - case 'x': - mg->mg_virtual = &PL_vtbl_substr; - break; - case 'y': - mg->mg_virtual = &PL_vtbl_defelem; - break; - case '*': - mg->mg_virtual = &PL_vtbl_glob; - break; - case '#': - mg->mg_virtual = &PL_vtbl_arylen; - break; - case '.': - mg->mg_virtual = &PL_vtbl_pos; - break; - case '<': - mg->mg_virtual = &PL_vtbl_backref; - break; - case '~': /* Reserved for use by extensions not perl internals. */ - /* Useful for attaching extension internal data to perl vars. */ - /* Note that multiple extensions may clash if magical scalars */ - /* etc holding private data from one are passed to another. */ - SvRMAGICAL_on(sv); - break; - default: - Perl_croak(aTHX_ "Don't know how to handle magic of type '%c'", how); - } - mg_magical(sv); - if (SvGMAGICAL(sv)) - SvFLAGS(sv) &= ~(SVf_IOK|SVf_NOK|SVf_POK); -} - -/* -=for apidoc sv_unmagic - -Removes magic from an SV. - -=cut -*/ - -int -Perl_sv_unmagic(pTHX_ SV *sv, int type) -{ - MAGIC* mg; - MAGIC** mgp; - if (SvTYPE(sv) < SVt_PVMG || !SvMAGIC(sv)) - return 0; - mgp = &SvMAGIC(sv); - for (mg = *mgp; mg; mg = *mgp) { - if (mg->mg_type == type) { - MGVTBL* vtbl = mg->mg_virtual; - *mgp = mg->mg_moremagic; - if (vtbl && vtbl->svt_free) - CALL_FPTR(vtbl->svt_free)(aTHX_ sv, mg); - if (mg->mg_ptr && mg->mg_type != 'g') - if (mg->mg_len >= 0) - Safefree(mg->mg_ptr); - else if (mg->mg_len == HEf_SVKEY) - SvREFCNT_dec((SV*)mg->mg_ptr); - if (mg->mg_flags & MGf_REFCOUNTED) - SvREFCNT_dec(mg->mg_obj); - Safefree(mg); - } - else - mgp = &mg->mg_moremagic; - } - if (!SvMAGIC(sv)) { - SvMAGICAL_off(sv); - SvFLAGS(sv) |= (SvFLAGS(sv) & (SVp_IOK|SVp_NOK|SVp_POK)) >> PRIVSHIFT; - } - - return 0; -} - -/* -=for apidoc sv_rvweaken - -Weaken a reference. - -=cut -*/ - -SV * -Perl_sv_rvweaken(pTHX_ SV *sv) -{ - SV *tsv; - if (!SvOK(sv)) /* let undefs pass */ - return sv; - if (!SvROK(sv)) - Perl_croak(aTHX_ "Can't weaken a nonreference"); - else if (SvWEAKREF(sv)) { - if (ckWARN(WARN_MISC)) - Perl_warner(aTHX_ WARN_MISC, "Reference is already weak"); - return sv; - } - tsv = SvRV(sv); - sv_add_backref(tsv, sv); - SvWEAKREF_on(sv); - SvREFCNT_dec(tsv); - return sv; -} - -void -Perl_sv_add_backref(pTHX_ SV *tsv, SV *sv) -{ - AV *av; - MAGIC *mg; - if (SvMAGICAL(tsv) && (mg = mg_find(tsv, '<'))) - av = (AV*)mg->mg_obj; - else { - av = newAV(); - sv_magic(tsv, (SV*)av, '<', NULL, 0); - SvREFCNT_dec(av); /* for sv_magic */ - } - av_push(av,sv); -} - -void -Perl_sv_del_backref(pTHX_ SV *sv) -{ - AV *av; - SV **svp; - I32 i; - SV *tsv = SvRV(sv); - MAGIC *mg; - if (!SvMAGICAL(tsv) || !(mg = mg_find(tsv, '<'))) - Perl_croak(aTHX_ "panic: del_backref"); - av = (AV *)mg->mg_obj; - svp = AvARRAY(av); - i = AvFILLp(av); - while (i >= 0) { - if (svp[i] == sv) { - svp[i] = &PL_sv_undef; /* XXX */ - } - i--; - } -} - -/* -=for apidoc sv_insert - -Inserts a string at the specified offset/length within the SV. Similar to -the Perl substr() function. - -=cut -*/ - -void -Perl_sv_insert(pTHX_ SV *bigstr, STRLEN offset, STRLEN len, char *little, STRLEN littlelen) -{ - register char *big; - register char *mid; - register char *midend; - register char *bigend; - register I32 i; - STRLEN curlen; - - - if (!bigstr) - Perl_croak(aTHX_ "Can't modify non-existent substring"); - SvPV_force(bigstr, curlen); - (void)SvPOK_only_UTF8(bigstr); - if (offset + len > curlen) { - SvGROW(bigstr, offset+len+1); - Zero(SvPVX(bigstr)+curlen, offset+len-curlen, char); - SvCUR_set(bigstr, offset+len); - } - - SvTAINT(bigstr); - i = littlelen - len; - if (i > 0) { /* string might grow */ - big = SvGROW(bigstr, SvCUR(bigstr) + i + 1); - mid = big + offset + len; - midend = bigend = big + SvCUR(bigstr); - bigend += i; - *bigend = '\0'; - while (midend > mid) /* shove everything down */ - *--bigend = *--midend; - Move(little,big+offset,littlelen,char); - SvCUR(bigstr) += i; - SvSETMAGIC(bigstr); - return; - } - else if (i == 0) { - Move(little,SvPVX(bigstr)+offset,len,char); - SvSETMAGIC(bigstr); - return; - } - - big = SvPVX(bigstr); - mid = big + offset; - midend = mid + len; - bigend = big + SvCUR(bigstr); - - if (midend > bigend) - Perl_croak(aTHX_ "panic: sv_insert"); - - if (mid - big > bigend - midend) { /* faster to shorten from end */ - if (littlelen) { - Move(little, mid, littlelen,char); - mid += littlelen; - } - i = bigend - midend; - if (i > 0) { - Move(midend, mid, i,char); - mid += i; - } - *mid = '\0'; - SvCUR_set(bigstr, mid - big); - } - /*SUPPRESS 560*/ - else if ((i = mid - big)) { /* faster from front */ - midend -= littlelen; - mid = midend; - sv_chop(bigstr,midend-i); - big += i; - while (i--) - *--midend = *--big; - if (littlelen) - Move(little, mid, littlelen,char); - } - else if (littlelen) { - midend -= littlelen; - sv_chop(bigstr,midend); - Move(little,midend,littlelen,char); - } - else { - sv_chop(bigstr,midend); - } - SvSETMAGIC(bigstr); -} - -/* -=for apidoc sv_replace - -Make the first argument a copy of the second, then delete the original. - -=cut -*/ - -void -Perl_sv_replace(pTHX_ register SV *sv, register SV *nsv) -{ - U32 refcnt = SvREFCNT(sv); - SV_CHECK_THINKFIRST(sv); - if (SvREFCNT(nsv) != 1 && ckWARN_d(WARN_INTERNAL)) - Perl_warner(aTHX_ WARN_INTERNAL, "Reference miscount in sv_replace()"); - if (SvMAGICAL(sv)) { - if (SvMAGICAL(nsv)) - mg_free(nsv); - else - sv_upgrade(nsv, SVt_PVMG); - SvMAGIC(nsv) = SvMAGIC(sv); - SvFLAGS(nsv) |= SvMAGICAL(sv); - SvMAGICAL_off(sv); - SvMAGIC(sv) = 0; - } - SvREFCNT(sv) = 0; - sv_clear(sv); - assert(!SvREFCNT(sv)); - StructCopy(nsv,sv,SV); - SvREFCNT(sv) = refcnt; - SvFLAGS(nsv) |= SVTYPEMASK; /* Mark as freed */ - del_SV(nsv); -} - -/* -=for apidoc sv_clear - -Clear an SV, making it empty. Does not free the memory used by the SV -itself. - -=cut -*/ - -void -Perl_sv_clear(pTHX_ register SV *sv) -{ - HV* stash; - assert(sv); - assert(SvREFCNT(sv) == 0); - - if (SvOBJECT(sv)) { - if (PL_defstash) { /* Still have a symbol table? */ - dSP; - GV* destructor; - SV tmpref; - - Zero(&tmpref, 1, SV); - sv_upgrade(&tmpref, SVt_RV); - SvROK_on(&tmpref); - SvREADONLY_on(&tmpref); /* DESTROY() could be naughty */ - SvREFCNT(&tmpref) = 1; - - do { - stash = SvSTASH(sv); - destructor = gv_fetchmethod(SvSTASH(sv), "DESTROY"); - if (destructor) { - ENTER; - PUSHSTACKi(PERLSI_DESTROY); - SvRV(&tmpref) = SvREFCNT_inc(sv); - EXTEND(SP, 2); - PUSHMARK(SP); - PUSHs(&tmpref); - PUTBACK; - call_sv((SV*)GvCV(destructor), - G_DISCARD|G_EVAL|G_KEEPERR); - SvREFCNT(sv)--; - POPSTACK; - SPAGAIN; - LEAVE; - } - } while (SvOBJECT(sv) && SvSTASH(sv) != stash); - - del_XRV(SvANY(&tmpref)); - - if (SvREFCNT(sv)) { - if (PL_in_clean_objs) - Perl_croak(aTHX_ "DESTROY created new reference to dead object '%s'", - HvNAME(stash)); - /* DESTROY gave object new lease on life */ - return; - } - } - - if (SvOBJECT(sv)) { - SvREFCNT_dec(SvSTASH(sv)); /* possibly of changed persuasion */ - SvOBJECT_off(sv); /* Curse the object. */ - if (SvTYPE(sv) != SVt_PVIO) - --PL_sv_objcount; /* XXX Might want something more general */ - } - } - if (SvTYPE(sv) >= SVt_PVMG && SvMAGIC(sv)) - mg_free(sv); - stash = NULL; - switch (SvTYPE(sv)) { - case SVt_PVIO: - if (IoIFP(sv) && - IoIFP(sv) != PerlIO_stdin() && - IoIFP(sv) != PerlIO_stdout() && - IoIFP(sv) != PerlIO_stderr()) - { - io_close((IO*)sv, FALSE); - } - if (IoDIRP(sv) && !(IoFLAGS(sv) & IOf_FAKE_DIRP)) - PerlDir_close(IoDIRP(sv)); - IoDIRP(sv) = (DIR*)NULL; - Safefree(IoTOP_NAME(sv)); - Safefree(IoFMT_NAME(sv)); - Safefree(IoBOTTOM_NAME(sv)); - /* FALL THROUGH */ - case SVt_PVBM: - goto freescalar; - case SVt_PVCV: - case SVt_PVFM: - cv_undef((CV*)sv); - goto freescalar; - case SVt_PVHV: - hv_undef((HV*)sv); - break; - case SVt_PVAV: - av_undef((AV*)sv); - break; - case SVt_PVLV: - SvREFCNT_dec(LvTARG(sv)); - goto freescalar; - case SVt_PVGV: - gp_free((GV*)sv); - Safefree(GvNAME(sv)); - /* cannot decrease stash refcount yet, as we might recursively delete - ourselves when the refcnt drops to zero. Delay SvREFCNT_dec - of stash until current sv is completely gone. - -- JohnPC, 27 Mar 1998 */ - stash = GvSTASH(sv); - /* FALL THROUGH */ - case SVt_PVMG: - case SVt_PVNV: - case SVt_PVIV: - freescalar: - (void)SvOOK_off(sv); - /* FALL THROUGH */ - case SVt_PV: - case SVt_RV: - if (SvROK(sv)) { - if (SvWEAKREF(sv)) - sv_del_backref(sv); - else - SvREFCNT_dec(SvRV(sv)); - } - else if (SvPVX(sv) && SvLEN(sv)) - Safefree(SvPVX(sv)); - break; -/* - case SVt_NV: - case SVt_IV: - case SVt_NULL: - break; -*/ - } - - switch (SvTYPE(sv)) { - case SVt_NULL: - break; - case SVt_IV: - del_XIV(SvANY(sv)); - break; - case SVt_NV: - del_XNV(SvANY(sv)); - break; - case SVt_RV: - del_XRV(SvANY(sv)); - break; - case SVt_PV: - del_XPV(SvANY(sv)); - break; - case SVt_PVIV: - del_XPVIV(SvANY(sv)); - break; - case SVt_PVNV: - del_XPVNV(SvANY(sv)); - break; - case SVt_PVMG: - del_XPVMG(SvANY(sv)); - break; - case SVt_PVLV: - del_XPVLV(SvANY(sv)); - break; - case SVt_PVAV: - del_XPVAV(SvANY(sv)); - break; - case SVt_PVHV: - del_XPVHV(SvANY(sv)); - break; - case SVt_PVCV: - del_XPVCV(SvANY(sv)); - break; - case SVt_PVGV: - del_XPVGV(SvANY(sv)); - /* code duplication for increased performance. */ - SvFLAGS(sv) &= SVf_BREAK; - SvFLAGS(sv) |= SVTYPEMASK; - /* decrease refcount of the stash that owns this GV, if any */ - if (stash) - SvREFCNT_dec(stash); - return; /* not break, SvFLAGS reset already happened */ - case SVt_PVBM: - del_XPVBM(SvANY(sv)); - break; - case SVt_PVFM: - del_XPVFM(SvANY(sv)); - break; - case SVt_PVIO: - del_XPVIO(SvANY(sv)); - break; - } - SvFLAGS(sv) &= SVf_BREAK; - SvFLAGS(sv) |= SVTYPEMASK; -} - -SV * -Perl_sv_newref(pTHX_ SV *sv) -{ - if (sv) - ATOMIC_INC(SvREFCNT(sv)); - return sv; -} - -/* -=for apidoc sv_free - -Free the memory used by an SV. - -=cut -*/ - -void -Perl_sv_free(pTHX_ SV *sv) -{ - int refcount_is_zero; - - if (!sv) - return; - if (SvREFCNT(sv) == 0) { - if (SvFLAGS(sv) & SVf_BREAK) - return; - if (PL_in_clean_all) /* All is fair */ - return; - if (SvREADONLY(sv) && SvIMMORTAL(sv)) { - /* make sure SvREFCNT(sv)==0 happens very seldom */ - SvREFCNT(sv) = (~(U32)0)/2; - return; - } - if (ckWARN_d(WARN_INTERNAL)) - Perl_warner(aTHX_ WARN_INTERNAL, "Attempt to free unreferenced scalar"); - return; - } - ATOMIC_DEC_AND_TEST(refcount_is_zero, SvREFCNT(sv)); - if (!refcount_is_zero) - return; -#ifdef DEBUGGING - if (SvTEMP(sv)) { - if (ckWARN_d(WARN_DEBUGGING)) - Perl_warner(aTHX_ WARN_DEBUGGING, - "Attempt to free temp prematurely: SV 0x%"UVxf, - PTR2UV(sv)); - return; - } -#endif - if (SvREADONLY(sv) && SvIMMORTAL(sv)) { - /* make sure SvREFCNT(sv)==0 happens very seldom */ - SvREFCNT(sv) = (~(U32)0)/2; - return; - } - sv_clear(sv); - if (! SvREFCNT(sv)) - del_SV(sv); -} - -/* -=for apidoc sv_len - -Returns the length of the string in the SV. See also C<SvCUR>. - -=cut -*/ - -STRLEN -Perl_sv_len(pTHX_ register SV *sv) -{ - char *junk; - STRLEN len; - - if (!sv) - return 0; - - if (SvGMAGICAL(sv)) - len = mg_length(sv); - else - junk = SvPV(sv, len); - return len; -} - -/* -=for apidoc sv_len_utf8 - -Returns the number of characters in the string in an SV, counting wide -UTF8 bytes as a single character. - -=cut -*/ - -STRLEN -Perl_sv_len_utf8(pTHX_ register SV *sv) -{ - if (!sv) - return 0; - -#ifdef NOTYET - if (SvGMAGICAL(sv)) - return mg_length(sv); - else -#endif - { - STRLEN len; - U8 *s = (U8*)SvPV(sv, len); - - return Perl_utf8_length(aTHX_ s, s + len); - } -} - -void -Perl_sv_pos_u2b(pTHX_ register SV *sv, I32* offsetp, I32* lenp) -{ - U8 *start; - U8 *s; - U8 *send; - I32 uoffset = *offsetp; - STRLEN len; - - if (!sv) - return; - - start = s = (U8*)SvPV(sv, len); - send = s + len; - while (s < send && uoffset--) - s += UTF8SKIP(s); - if (s >= send) - s = send; - *offsetp = s - start; - if (lenp) { - I32 ulen = *lenp; - start = s; - while (s < send && ulen--) - s += UTF8SKIP(s); - if (s >= send) - s = send; - *lenp = s - start; - } - return; -} - -void -Perl_sv_pos_b2u(pTHX_ register SV *sv, I32* offsetp) -{ - U8 *s; - U8 *send; - STRLEN len; - - if (!sv) - return; - - s = (U8*)SvPV(sv, len); - if (len < *offsetp) - Perl_croak(aTHX_ "panic: sv_pos_b2u: bad byte offset"); - send = s + *offsetp; - len = 0; - while (s < send) { - STRLEN n; - - if (utf8_to_uv(s, UTF8SKIP(s), &n, 0)) { - s += n; - len++; - } - else - break; - } - *offsetp = len; - return; -} - -/* -=for apidoc sv_eq - -Returns a boolean indicating whether the strings in the two SVs are -identical. - -=cut -*/ - -I32 -Perl_sv_eq(pTHX_ register SV *sv1, register SV *sv2) -{ - char *pv1; - STRLEN cur1; - char *pv2; - STRLEN cur2; - I32 eq = 0; - bool pv1tmp = FALSE; - bool pv2tmp = FALSE; - - if (!sv1) { - pv1 = ""; - cur1 = 0; - } - else - pv1 = SvPV(sv1, cur1); - - if (!sv2){ - pv2 = ""; - cur2 = 0; - } - else - pv2 = SvPV(sv2, cur2); - - /* do not utf8ize the comparands as a side-effect */ - if (cur1 && cur2 && SvUTF8(sv1) != SvUTF8(sv2) && !IN_BYTE) { - bool is_utf8 = TRUE; - - if (SvUTF8(sv1)) { - char *pv = (char*)bytes_from_utf8((U8*)pv1, &cur1, &is_utf8); - - if ((pv1tmp = (pv != pv1))) - pv1 = pv; - } - else { - char *pv = (char *)bytes_from_utf8((U8*)pv2, &cur2, &is_utf8); - - if ((pv2tmp = (pv != pv2))) - pv2 = pv; - } - } - - if (cur1 == cur2) - eq = memEQ(pv1, pv2, cur1); - - if (pv1tmp) - Safefree(pv1); - if (pv2tmp) - Safefree(pv2); - - return eq; -} - -/* -=for apidoc sv_cmp - -Compares the strings in two SVs. Returns -1, 0, or 1 indicating whether the -string in C<sv1> is less than, equal to, or greater than the string in -C<sv2>. - -=cut -*/ - -I32 -Perl_sv_cmp(pTHX_ register SV *sv1, register SV *sv2) -{ - STRLEN cur1, cur2; - char *pv1, *pv2; - I32 cmp; - bool pv1tmp = FALSE; - bool pv2tmp = FALSE; - - if (!sv1) { - pv1 = ""; - cur1 = 0; - } - else - pv1 = SvPV(sv1, cur1); - - if (!sv2){ - pv2 = ""; - cur2 = 0; - } - else - pv2 = SvPV(sv2, cur2); - - /* do not utf8ize the comparands as a side-effect */ - if (cur1 && cur2 && SvUTF8(sv1) != SvUTF8(sv2) && !IN_BYTE) { - if (SvUTF8(sv1)) { - pv2 = (char*)bytes_to_utf8((U8*)pv2, &cur2); - pv2tmp = TRUE; - } - else { - pv1 = (char*)bytes_to_utf8((U8*)pv1, &cur1); - pv1tmp = TRUE; - } - } - - if (!cur1) { - cmp = cur2 ? -1 : 0; - } else if (!cur2) { - cmp = 1; - } else { - I32 retval = memcmp((void*)pv1, (void*)pv2, cur1 < cur2 ? cur1 : cur2); - - if (retval) { - cmp = retval < 0 ? -1 : 1; - } else if (cur1 == cur2) { - cmp = 0; - } else { - cmp = cur1 < cur2 ? -1 : 1; - } - } - - if (pv1tmp) - Safefree(pv1); - if (pv2tmp) - Safefree(pv2); - - return cmp; -} - -/* -=for apidoc sv_cmp_locale - -Compares the strings in two SVs in a locale-aware manner. See -L</sv_cmp_locale> - -=cut -*/ - -I32 -Perl_sv_cmp_locale(pTHX_ register SV *sv1, register SV *sv2) -{ -#ifdef USE_LOCALE_COLLATE - - char *pv1, *pv2; - STRLEN len1, len2; - I32 retval; - - if (PL_collation_standard) - goto raw_compare; - - len1 = 0; - pv1 = sv1 ? sv_collxfrm(sv1, &len1) : (char *) NULL; - len2 = 0; - pv2 = sv2 ? sv_collxfrm(sv2, &len2) : (char *) NULL; - - if (!pv1 || !len1) { - if (pv2 && len2) - return -1; - else - goto raw_compare; - } - else { - if (!pv2 || !len2) - return 1; - } - - retval = memcmp((void*)pv1, (void*)pv2, len1 < len2 ? len1 : len2); - - if (retval) - return retval < 0 ? -1 : 1; - - /* - * When the result of collation is equality, that doesn't mean - * that there are no differences -- some locales exclude some - * characters from consideration. So to avoid false equalities, - * we use the raw string as a tiebreaker. - */ - - raw_compare: - /* FALL THROUGH */ - -#endif /* USE_LOCALE_COLLATE */ - - return sv_cmp(sv1, sv2); -} - -#ifdef USE_LOCALE_COLLATE -/* - * Any scalar variable may carry an 'o' magic that contains the - * scalar data of the variable transformed to such a format that - * a normal memory comparison can be used to compare the data - * according to the locale settings. - */ -char * -Perl_sv_collxfrm(pTHX_ SV *sv, STRLEN *nxp) -{ - MAGIC *mg; - - mg = SvMAGICAL(sv) ? mg_find(sv, 'o') : (MAGIC *) NULL; - if (!mg || !mg->mg_ptr || *(U32*)mg->mg_ptr != PL_collation_ix) { - char *s, *xf; - STRLEN len, xlen; - - if (mg) - Safefree(mg->mg_ptr); - s = SvPV(sv, len); - if ((xf = mem_collxfrm(s, len, &xlen))) { - if (SvREADONLY(sv)) { - SAVEFREEPV(xf); - *nxp = xlen; - return xf + sizeof(PL_collation_ix); - } - if (! mg) { - sv_magic(sv, 0, 'o', 0, 0); - mg = mg_find(sv, 'o'); - assert(mg); - } - mg->mg_ptr = xf; - mg->mg_len = xlen; - } - else { - if (mg) { - mg->mg_ptr = NULL; - mg->mg_len = -1; - } - } - } - if (mg && mg->mg_ptr) { - *nxp = mg->mg_len; - return mg->mg_ptr + sizeof(PL_collation_ix); - } - else { - *nxp = 0; - return NULL; - } -} - -#endif /* USE_LOCALE_COLLATE */ - -/* -=for apidoc sv_gets - -Get a line from the filehandle and store it into the SV, optionally -appending to the currently-stored string. - -=cut -*/ - -char * -Perl_sv_gets(pTHX_ register SV *sv, register PerlIO *fp, I32 append) -{ - char *rsptr; - STRLEN rslen; - register STDCHAR rslast; - register STDCHAR *bp; - register I32 cnt; - I32 i; - - SV_CHECK_THINKFIRST(sv); - (void)SvUPGRADE(sv, SVt_PV); - - SvSCREAM_off(sv); - - if (RsSNARF(PL_rs)) { - rsptr = NULL; - rslen = 0; - } - else if (RsRECORD(PL_rs)) { - I32 recsize, bytesread; - char *buffer; - - /* Grab the size of the record we're getting */ - recsize = SvIV(SvRV(PL_rs)); - (void)SvPOK_only(sv); /* Validate pointer */ - buffer = SvGROW(sv, recsize + 1); - /* Go yank in */ -#ifdef VMS - /* VMS wants read instead of fread, because fread doesn't respect */ - /* RMS record boundaries. This is not necessarily a good thing to be */ - /* doing, but we've got no other real choice */ - bytesread = PerlLIO_read(PerlIO_fileno(fp), buffer, recsize); -#else - bytesread = PerlIO_read(fp, buffer, recsize); -#endif - SvCUR_set(sv, bytesread); - buffer[bytesread] = '\0'; - SvUTF8_off(sv); - return(SvCUR(sv) ? SvPVX(sv) : Nullch); - } - else if (RsPARA(PL_rs)) { - rsptr = "\n\n"; - rslen = 2; - } - else { - /* Get $/ i.e. PL_rs into same encoding as stream wants */ - if (SvUTF8(PL_rs)) { - if (!sv_utf8_downgrade(PL_rs, TRUE)) { - Perl_croak(aTHX_ "Wide character in $/"); - } - } - rsptr = SvPV(PL_rs, rslen); - } - - rslast = rslen ? rsptr[rslen - 1] : '\0'; - - if (RsPARA(PL_rs)) { /* have to do this both before and after */ - do { /* to make sure file boundaries work right */ - if (PerlIO_eof(fp)) - return 0; - i = PerlIO_getc(fp); - if (i != '\n') { - if (i == -1) - return 0; - PerlIO_ungetc(fp,i); - break; - } - } while (i != EOF); - } - - /* See if we know enough about I/O mechanism to cheat it ! */ - - /* This used to be #ifdef test - it is made run-time test for ease - of abstracting out stdio interface. One call should be cheap - enough here - and may even be a macro allowing compile - time optimization. - */ - - if (PerlIO_fast_gets(fp)) { - - /* - * We're going to steal some values from the stdio struct - * and put EVERYTHING in the innermost loop into registers. - */ - register STDCHAR *ptr; - STRLEN bpx; - I32 shortbuffered; - -#if defined(VMS) && defined(PERLIO_IS_STDIO) - /* An ungetc()d char is handled separately from the regular - * buffer, so we getc() it back out and stuff it in the buffer. - */ - i = PerlIO_getc(fp); - if (i == EOF) return 0; - *(--((*fp)->_ptr)) = (unsigned char) i; - (*fp)->_cnt++; -#endif - - /* Here is some breathtakingly efficient cheating */ - - cnt = PerlIO_get_cnt(fp); /* get count into register */ - (void)SvPOK_only(sv); /* validate pointer */ - if (SvLEN(sv) - append <= cnt + 1) { /* make sure we have the room */ - if (cnt > 80 && SvLEN(sv) > append) { - shortbuffered = cnt - SvLEN(sv) + append + 1; - cnt -= shortbuffered; - } - else { - shortbuffered = 0; - /* remember that cnt can be negative */ - SvGROW(sv, append + (cnt <= 0 ? 2 : (cnt + 1))); - } - } - else - shortbuffered = 0; - bp = (STDCHAR*)SvPVX(sv) + append; /* move these two too to registers */ - ptr = (STDCHAR*)PerlIO_get_ptr(fp); - DEBUG_P(PerlIO_printf(Perl_debug_log, - "Screamer: entering, ptr=%"UVuf", cnt=%ld\n",PTR2UV(ptr),(long)cnt)); - DEBUG_P(PerlIO_printf(Perl_debug_log, - "Screamer: entering: FILE * thinks ptr=%"UVuf", cnt=%ld, base=%"UVuf"\n", - PTR2UV(PerlIO_get_ptr(fp)), (long)PerlIO_get_cnt(fp), - PTR2UV(PerlIO_has_base(fp) ? PerlIO_get_base(fp) : 0))); - for (;;) { - screamer: - if (cnt > 0) { - if (rslen) { - while (cnt > 0) { /* this | eat */ - cnt--; - if ((*bp++ = *ptr++) == rslast) /* really | dust */ - goto thats_all_folks; /* screams | sed :-) */ - } - } - else { - Copy(ptr, bp, cnt, char); /* this | eat */ - bp += cnt; /* screams | dust */ - ptr += cnt; /* louder | sed :-) */ - cnt = 0; - } - } - - if (shortbuffered) { /* oh well, must extend */ - cnt = shortbuffered; - shortbuffered = 0; - bpx = bp - (STDCHAR*)SvPVX(sv); /* box up before relocation */ - SvCUR_set(sv, bpx); - SvGROW(sv, SvLEN(sv) + append + cnt + 2); - bp = (STDCHAR*)SvPVX(sv) + bpx; /* unbox after relocation */ - continue; - } - - DEBUG_P(PerlIO_printf(Perl_debug_log, - "Screamer: going to getc, ptr=%"UVuf", cnt=%ld\n", - PTR2UV(ptr),(long)cnt)); - PerlIO_set_ptrcnt(fp, ptr, cnt); /* deregisterize cnt and ptr */ - DEBUG_P(PerlIO_printf(Perl_debug_log, - "Screamer: pre: FILE * thinks ptr=%"UVuf", cnt=%ld, base=%"UVuf"\n", - PTR2UV(PerlIO_get_ptr(fp)), (long)PerlIO_get_cnt(fp), - PTR2UV(PerlIO_has_base (fp) ? PerlIO_get_base(fp) : 0))); - /* This used to call 'filbuf' in stdio form, but as that behaves like - getc when cnt <= 0 we use PerlIO_getc here to avoid introducing - another abstraction. */ - i = PerlIO_getc(fp); /* get more characters */ - DEBUG_P(PerlIO_printf(Perl_debug_log, - "Screamer: post: FILE * thinks ptr=%"UVuf", cnt=%ld, base=%"UVuf"\n", - PTR2UV(PerlIO_get_ptr(fp)), (long)PerlIO_get_cnt(fp), - PTR2UV(PerlIO_has_base (fp) ? PerlIO_get_base(fp) : 0))); - cnt = PerlIO_get_cnt(fp); - ptr = (STDCHAR*)PerlIO_get_ptr(fp); /* reregisterize cnt and ptr */ - DEBUG_P(PerlIO_printf(Perl_debug_log, - "Screamer: after getc, ptr=%"UVuf", cnt=%ld\n",PTR2UV(ptr),(long)cnt)); - - if (i == EOF) /* all done for ever? */ - goto thats_really_all_folks; - - bpx = bp - (STDCHAR*)SvPVX(sv); /* box up before relocation */ - SvCUR_set(sv, bpx); - SvGROW(sv, bpx + cnt + 2); - bp = (STDCHAR*)SvPVX(sv) + bpx; /* unbox after relocation */ - - *bp++ = i; /* store character from PerlIO_getc */ - - if (rslen && (STDCHAR)i == rslast) /* all done for now? */ - goto thats_all_folks; - } - -thats_all_folks: - if ((rslen > 1 && (bp - (STDCHAR*)SvPVX(sv) < rslen)) || - memNE((char*)bp - rslen, rsptr, rslen)) - goto screamer; /* go back to the fray */ -thats_really_all_folks: - if (shortbuffered) - cnt += shortbuffered; - DEBUG_P(PerlIO_printf(Perl_debug_log, - "Screamer: quitting, ptr=%"UVuf", cnt=%ld\n",PTR2UV(ptr),(long)cnt)); - PerlIO_set_ptrcnt(fp, ptr, cnt); /* put these back or we're in trouble */ - DEBUG_P(PerlIO_printf(Perl_debug_log, - "Screamer: end: FILE * thinks ptr=%"UVuf", cnt=%ld, base=%"UVuf"\n", - PTR2UV(PerlIO_get_ptr(fp)), (long)PerlIO_get_cnt(fp), - PTR2UV(PerlIO_has_base (fp) ? PerlIO_get_base(fp) : 0))); - *bp = '\0'; - SvCUR_set(sv, bp - (STDCHAR*)SvPVX(sv)); /* set length */ - DEBUG_P(PerlIO_printf(Perl_debug_log, - "Screamer: done, len=%ld, string=|%.*s|\n", - (long)SvCUR(sv),(int)SvCUR(sv),SvPVX(sv))); - } - else - { -#ifndef EPOC - /*The big, slow, and stupid way */ - STDCHAR buf[8192]; -#else - /* Need to work around EPOC SDK features */ - /* On WINS: MS VC5 generates calls to _chkstk, */ - /* if a `large' stack frame is allocated */ - /* gcc on MARM does not generate calls like these */ - STDCHAR buf[1024]; -#endif - -screamer2: - if (rslen) { - register STDCHAR *bpe = buf + sizeof(buf); - bp = buf; - while ((i = PerlIO_getc(fp)) != EOF && (*bp++ = i) != rslast && bp < bpe) - ; /* keep reading */ - cnt = bp - buf; - } - else { - cnt = PerlIO_read(fp,(char*)buf, sizeof(buf)); - /* Accomodate broken VAXC compiler, which applies U8 cast to - * both args of ?: operator, causing EOF to change into 255 - */ - if (cnt) { i = (U8)buf[cnt - 1]; } else { i = EOF; } - } - - if (append) - sv_catpvn(sv, (char *) buf, cnt); - else - sv_setpvn(sv, (char *) buf, cnt); - - if (i != EOF && /* joy */ - (!rslen || - SvCUR(sv) < rslen || - memNE(SvPVX(sv) + SvCUR(sv) - rslen, rsptr, rslen))) - { - append = -1; - /* - * If we're reading from a TTY and we get a short read, - * indicating that the user hit his EOF character, we need - * to notice it now, because if we try to read from the TTY - * again, the EOF condition will disappear. - * - * The comparison of cnt to sizeof(buf) is an optimization - * that prevents unnecessary calls to feof(). - * - * - jik 9/25/96 - */ - if (!(cnt < sizeof(buf) && PerlIO_eof(fp))) - goto screamer2; - } - } - - if (RsPARA(PL_rs)) { /* have to do this both before and after */ - while (i != EOF) { /* to make sure file boundaries work right */ - i = PerlIO_getc(fp); - if (i != '\n') { - PerlIO_ungetc(fp,i); - break; - } - } - } - - SvUTF8_off(sv); - - return (SvCUR(sv) - append) ? SvPVX(sv) : Nullch; -} - - -/* -=for apidoc sv_inc - -Auto-increment of the value in the SV. - -=cut -*/ - -void -Perl_sv_inc(pTHX_ register SV *sv) -{ - register char *d; - int flags; - - if (!sv) - return; - if (SvGMAGICAL(sv)) - mg_get(sv); - if (SvTHINKFIRST(sv)) { - if (SvREADONLY(sv)) { - if (PL_curcop != &PL_compiling) - Perl_croak(aTHX_ PL_no_modify); - } - if (SvROK(sv)) { - IV i; - if (SvAMAGIC(sv) && AMG_CALLun(sv,inc)) - return; - i = PTR2IV(SvRV(sv)); - sv_unref(sv); - sv_setiv(sv, i); - } - } - flags = SvFLAGS(sv); - if (flags & SVp_NOK) { - (void)SvNOK_only(sv); - SvNVX(sv) += 1.0; - return; - } - if (flags & SVp_IOK) { - if (SvIsUV(sv)) { - if (SvUVX(sv) == UV_MAX) - sv_setnv(sv, (NV)UV_MAX + 1.0); - else - (void)SvIOK_only_UV(sv); - ++SvUVX(sv); - } else { - if (SvIVX(sv) == IV_MAX) - sv_setnv(sv, (NV)IV_MAX + 1.0); - else { - (void)SvIOK_only(sv); - ++SvIVX(sv); - } - } - return; - } - if (!(flags & SVp_POK) || !*SvPVX(sv)) { - if ((flags & SVTYPEMASK) < SVt_PVNV) - sv_upgrade(sv, SVt_NV); - SvNVX(sv) = 1.0; - (void)SvNOK_only(sv); - return; - } - d = SvPVX(sv); - while (isALPHA(*d)) d++; - while (isDIGIT(*d)) d++; - if (*d) { - sv_setnv(sv,Atof(SvPVX(sv)) + 1.0); /* punt */ - return; - } - d--; - while (d >= SvPVX(sv)) { - if (isDIGIT(*d)) { - if (++*d <= '9') - return; - *(d--) = '0'; - } - else { -#ifdef EBCDIC - /* MKS: The original code here died if letters weren't consecutive. - * at least it didn't have to worry about non-C locales. The - * new code assumes that ('z'-'a')==('Z'-'A'), letters are - * arranged in order (although not consecutively) and that only - * [A-Za-z] are accepted by isALPHA in the C locale. - */ - if (*d != 'z' && *d != 'Z') { - do { ++*d; } while (!isALPHA(*d)); - return; - } - *(d--) -= 'z' - 'a'; -#else - ++*d; - if (isALPHA(*d)) - return; - *(d--) -= 'z' - 'a' + 1; -#endif - } - } - /* oh,oh, the number grew */ - SvGROW(sv, SvCUR(sv) + 2); - SvCUR(sv)++; - for (d = SvPVX(sv) + SvCUR(sv); d > SvPVX(sv); d--) - *d = d[-1]; - if (isDIGIT(d[1])) - *d = '1'; - else - *d = d[1]; -} - -/* -=for apidoc sv_dec - -Auto-decrement of the value in the SV. - -=cut -*/ - -void -Perl_sv_dec(pTHX_ register SV *sv) -{ - int flags; - - if (!sv) - return; - if (SvGMAGICAL(sv)) - mg_get(sv); - if (SvTHINKFIRST(sv)) { - if (SvREADONLY(sv)) { - if (PL_curcop != &PL_compiling) - Perl_croak(aTHX_ PL_no_modify); - } - if (SvROK(sv)) { - IV i; - if (SvAMAGIC(sv) && AMG_CALLun(sv,dec)) - return; - i = PTR2IV(SvRV(sv)); - sv_unref(sv); - sv_setiv(sv, i); - } - } - flags = SvFLAGS(sv); - if (flags & SVp_NOK) { - SvNVX(sv) -= 1.0; - (void)SvNOK_only(sv); - return; - } - if (flags & SVp_IOK) { - if (SvIsUV(sv)) { - if (SvUVX(sv) == 0) { - (void)SvIOK_only(sv); - SvIVX(sv) = -1; - } - else { - (void)SvIOK_only_UV(sv); - --SvUVX(sv); - } - } else { - if (SvIVX(sv) == IV_MIN) - sv_setnv(sv, (NV)IV_MIN - 1.0); - else { - (void)SvIOK_only(sv); - --SvIVX(sv); - } - } - return; - } - if (!(flags & SVp_POK)) { - if ((flags & SVTYPEMASK) < SVt_PVNV) - sv_upgrade(sv, SVt_NV); - SvNVX(sv) = -1.0; - (void)SvNOK_only(sv); - return; - } - sv_setnv(sv,Atof(SvPVX(sv)) - 1.0); /* punt */ -} - -/* -=for apidoc sv_mortalcopy - -Creates a new SV which is a copy of the original SV. The new SV is marked -as mortal. - -=cut -*/ - -/* Make a string that will exist for the duration of the expression - * evaluation. Actually, it may have to last longer than that, but - * hopefully we won't free it until it has been assigned to a - * permanent location. */ - -SV * -Perl_sv_mortalcopy(pTHX_ SV *oldstr) -{ - register SV *sv; - - new_SV(sv); - sv_setsv(sv,oldstr); - EXTEND_MORTAL(1); - PL_tmps_stack[++PL_tmps_ix] = sv; - SvTEMP_on(sv); - return sv; -} - -/* -=for apidoc sv_newmortal - -Creates a new SV which is mortal. The reference count of the SV is set to 1. - -=cut -*/ - -SV * -Perl_sv_newmortal(pTHX) -{ - register SV *sv; - - new_SV(sv); - SvFLAGS(sv) = SVs_TEMP; - EXTEND_MORTAL(1); - PL_tmps_stack[++PL_tmps_ix] = sv; - return sv; -} - -/* -=for apidoc sv_2mortal - -Marks an SV as mortal. The SV will be destroyed when the current context -ends. - -=cut -*/ - -/* same thing without the copying */ - -SV * -Perl_sv_2mortal(pTHX_ register SV *sv) -{ - if (!sv) - return sv; - if (SvREADONLY(sv) && SvIMMORTAL(sv)) - return sv; - EXTEND_MORTAL(1); - PL_tmps_stack[++PL_tmps_ix] = sv; - SvTEMP_on(sv); - return sv; -} - -/* -=for apidoc newSVpv - -Creates a new SV and copies a string into it. The reference count for the -SV is set to 1. If C<len> is zero, Perl will compute the length using -strlen(). For efficiency, consider using C<newSVpvn> instead. - -=cut -*/ - -SV * -Perl_newSVpv(pTHX_ const char *s, STRLEN len) -{ - register SV *sv; - - new_SV(sv); - if (!len) - len = strlen(s); - sv_setpvn(sv,s,len); - return sv; -} - -/* -=for apidoc newSVpvn - -Creates a new SV and copies a string into it. The reference count for the -SV is set to 1. Note that if C<len> is zero, Perl will create a zero length -string. You are responsible for ensuring that the source string is at least -C<len> bytes long. - -=cut -*/ - -SV * -Perl_newSVpvn(pTHX_ const char *s, STRLEN len) -{ - register SV *sv; - - new_SV(sv); - sv_setpvn(sv,s,len); - return sv; -} - -#if defined(PERL_IMPLICIT_CONTEXT) -SV * -Perl_newSVpvf_nocontext(const char* pat, ...) -{ - dTHX; - register SV *sv; - va_list args; - va_start(args, pat); - sv = vnewSVpvf(pat, &args); - va_end(args); - return sv; -} -#endif - -/* -=for apidoc newSVpvf - -Creates a new SV an initialize it with the string formatted like -C<sprintf>. - -=cut -*/ - -SV * -Perl_newSVpvf(pTHX_ const char* pat, ...) -{ - register SV *sv; - va_list args; - va_start(args, pat); - sv = vnewSVpvf(pat, &args); - va_end(args); - return sv; -} - -SV * -Perl_vnewSVpvf(pTHX_ const char* pat, va_list* args) -{ - register SV *sv; - new_SV(sv); - sv_vsetpvfn(sv, pat, strlen(pat), args, Null(SV**), 0, Null(bool*)); - return sv; -} - -/* -=for apidoc newSVnv - -Creates a new SV and copies a floating point value into it. -The reference count for the SV is set to 1. - -=cut -*/ - -SV * -Perl_newSVnv(pTHX_ NV n) -{ - register SV *sv; - - new_SV(sv); - sv_setnv(sv,n); - return sv; -} - -/* -=for apidoc newSViv - -Creates a new SV and copies an integer into it. The reference count for the -SV is set to 1. - -=cut -*/ - -SV * -Perl_newSViv(pTHX_ IV i) -{ - register SV *sv; - - new_SV(sv); - sv_setiv(sv,i); - return sv; -} - -/* -=for apidoc newSVuv - -Creates a new SV and copies an unsigned integer into it. -The reference count for the SV is set to 1. - -=cut -*/ - -SV * -Perl_newSVuv(pTHX_ UV u) -{ - register SV *sv; - - new_SV(sv); - sv_setuv(sv,u); - return sv; -} - -/* -=for apidoc newRV_noinc - -Creates an RV wrapper for an SV. The reference count for the original -SV is B<not> incremented. - -=cut -*/ - -SV * -Perl_newRV_noinc(pTHX_ SV *tmpRef) -{ - register SV *sv; - - new_SV(sv); - sv_upgrade(sv, SVt_RV); - SvTEMP_off(tmpRef); - SvRV(sv) = tmpRef; - SvROK_on(sv); - return sv; -} - -/* newRV_inc is #defined to newRV in sv.h */ -SV * -Perl_newRV(pTHX_ SV *tmpRef) -{ - return newRV_noinc(SvREFCNT_inc(tmpRef)); -} - -/* -=for apidoc newSVsv - -Creates a new SV which is an exact duplicate of the original SV. - -=cut -*/ - -/* make an exact duplicate of old */ - -SV * -Perl_newSVsv(pTHX_ register SV *old) -{ - register SV *sv; - - if (!old) - return Nullsv; - if (SvTYPE(old) == SVTYPEMASK) { - if (ckWARN_d(WARN_INTERNAL)) - Perl_warner(aTHX_ WARN_INTERNAL, "semi-panic: attempt to dup freed string"); - return Nullsv; - } - new_SV(sv); - if (SvTEMP(old)) { - SvTEMP_off(old); - sv_setsv(sv,old); - SvTEMP_on(old); - } - else - sv_setsv(sv,old); - return sv; -} - -void -Perl_sv_reset(pTHX_ register char *s, HV *stash) -{ - register HE *entry; - register GV *gv; - register SV *sv; - register I32 i; - register PMOP *pm; - register I32 max; - char todo[PERL_UCHAR_MAX+1]; - - if (!stash) - return; - - if (!*s) { /* reset ?? searches */ - for (pm = HvPMROOT(stash); pm; pm = pm->op_pmnext) { - pm->op_pmdynflags &= ~PMdf_USED; - } - return; - } - - /* reset variables */ - - if (!HvARRAY(stash)) - return; - - Zero(todo, 256, char); - while (*s) { - i = (unsigned char)*s; - if (s[1] == '-') { - s += 2; - } - max = (unsigned char)*s++; - for ( ; i <= max; i++) { - todo[i] = 1; - } - for (i = 0; i <= (I32) HvMAX(stash); i++) { - for (entry = HvARRAY(stash)[i]; - entry; - entry = HeNEXT(entry)) - { - if (!todo[(U8)*HeKEY(entry)]) - continue; - gv = (GV*)HeVAL(entry); - sv = GvSV(gv); - if (SvTHINKFIRST(sv)) { - if (!SvREADONLY(sv) && SvROK(sv)) - sv_unref(sv); - continue; - } - (void)SvOK_off(sv); - if (SvTYPE(sv) >= SVt_PV) { - SvCUR_set(sv, 0); - if (SvPVX(sv) != Nullch) - *SvPVX(sv) = '\0'; - SvTAINT(sv); - } - if (GvAV(gv)) { - av_clear(GvAV(gv)); - } - if (GvHV(gv) && !HvNAME(GvHV(gv))) { - hv_clear(GvHV(gv)); -#ifdef USE_ENVIRON_ARRAY - if (gv == PL_envgv) - environ[0] = Nullch; -#endif - } - } - } - } -} - -IO* -Perl_sv_2io(pTHX_ SV *sv) -{ - IO* io; - GV* gv; - STRLEN n_a; - - switch (SvTYPE(sv)) { - case SVt_PVIO: - io = (IO*)sv; - break; - case SVt_PVGV: - gv = (GV*)sv; - io = GvIO(gv); - if (!io) - Perl_croak(aTHX_ "Bad filehandle: %s", GvNAME(gv)); - break; - default: - if (!SvOK(sv)) - Perl_croak(aTHX_ PL_no_usym, "filehandle"); - if (SvROK(sv)) - return sv_2io(SvRV(sv)); - gv = gv_fetchpv(SvPV(sv,n_a), FALSE, SVt_PVIO); - if (gv) - io = GvIO(gv); - else - io = 0; - if (!io) - Perl_croak(aTHX_ "Bad filehandle: %s", SvPV(sv,n_a)); - break; - } - return io; -} - -CV * -Perl_sv_2cv(pTHX_ SV *sv, HV **st, GV **gvp, I32 lref) -{ - GV *gv; - CV *cv; - STRLEN n_a; - - if (!sv) - return *gvp = Nullgv, Nullcv; - switch (SvTYPE(sv)) { - case SVt_PVCV: - *st = CvSTASH(sv); - *gvp = Nullgv; - return (CV*)sv; - case SVt_PVHV: - case SVt_PVAV: - *gvp = Nullgv; - return Nullcv; - case SVt_PVGV: - gv = (GV*)sv; - *gvp = gv; - *st = GvESTASH(gv); - goto fix_gv; - - default: - if (SvGMAGICAL(sv)) - mg_get(sv); - if (SvROK(sv)) { - SV **sp = &sv; /* Used in tryAMAGICunDEREF macro. */ - tryAMAGICunDEREF(to_cv); - - sv = SvRV(sv); - if (SvTYPE(sv) == SVt_PVCV) { - cv = (CV*)sv; - *gvp = Nullgv; - *st = CvSTASH(cv); - return cv; - } - else if(isGV(sv)) - gv = (GV*)sv; - else - Perl_croak(aTHX_ "Not a subroutine reference"); - } - else if (isGV(sv)) - gv = (GV*)sv; - else - gv = gv_fetchpv(SvPV(sv, n_a), lref, SVt_PVCV); - *gvp = gv; - if (!gv) - return Nullcv; - *st = GvESTASH(gv); - fix_gv: - if (lref && !GvCVu(gv)) { - SV *tmpsv; - ENTER; - tmpsv = NEWSV(704,0); - gv_efullname3(tmpsv, gv, Nullch); - /* XXX this is probably not what they think they're getting. - * It has the same effect as "sub name;", i.e. just a forward - * declaration! */ - newSUB(start_subparse(FALSE, 0), - newSVOP(OP_CONST, 0, tmpsv), - Nullop, - Nullop); - LEAVE; - if (!GvCVu(gv)) - Perl_croak(aTHX_ "Unable to create sub named \"%s\"", SvPV(sv,n_a)); - } - return GvCVu(gv); - } -} - -/* -=for apidoc sv_true - -Returns true if the SV has a true value by Perl's rules. - -=cut -*/ - -I32 -Perl_sv_true(pTHX_ register SV *sv) -{ - if (!sv) - return 0; - if (SvPOK(sv)) { - register XPV* tXpv; - if ((tXpv = (XPV*)SvANY(sv)) && - (tXpv->xpv_cur > 1 || - (tXpv->xpv_cur && *tXpv->xpv_pv != '0'))) - return 1; - else - return 0; - } - else { - if (SvIOK(sv)) - return SvIVX(sv) != 0; - else { - if (SvNOK(sv)) - return SvNVX(sv) != 0.0; - else - return sv_2bool(sv); - } - } -} - -IV -Perl_sv_iv(pTHX_ register SV *sv) -{ - if (SvIOK(sv)) { - if (SvIsUV(sv)) - return (IV)SvUVX(sv); - return SvIVX(sv); - } - return sv_2iv(sv); -} - -UV -Perl_sv_uv(pTHX_ register SV *sv) -{ - if (SvIOK(sv)) { - if (SvIsUV(sv)) - return SvUVX(sv); - return (UV)SvIVX(sv); - } - return sv_2uv(sv); -} - -NV -Perl_sv_nv(pTHX_ register SV *sv) -{ - if (SvNOK(sv)) - return SvNVX(sv); - return sv_2nv(sv); -} - -char * -Perl_sv_pv(pTHX_ SV *sv) -{ - STRLEN n_a; - - if (SvPOK(sv)) - return SvPVX(sv); - - return sv_2pv(sv, &n_a); -} - -char * -Perl_sv_pvn(pTHX_ SV *sv, STRLEN *lp) -{ - if (SvPOK(sv)) { - *lp = SvCUR(sv); - return SvPVX(sv); - } - return sv_2pv(sv, lp); -} - -/* -=for apidoc sv_pvn_force - -Get a sensible string out of the SV somehow. - -=cut -*/ - -char * -Perl_sv_pvn_force(pTHX_ SV *sv, STRLEN *lp) -{ - char *s; - - if (SvTHINKFIRST(sv) && !SvROK(sv)) - sv_force_normal(sv); - - if (SvPOK(sv)) { - *lp = SvCUR(sv); - } - else { - if (SvTYPE(sv) > SVt_PVLV && SvTYPE(sv) != SVt_PVFM) { - Perl_croak(aTHX_ "Can't coerce %s to string in %s", sv_reftype(sv,0), - PL_op_name[PL_op->op_type]); - } - else - s = sv_2pv(sv, lp); - if (s != SvPVX(sv)) { /* Almost, but not quite, sv_setpvn() */ - STRLEN len = *lp; - - if (SvROK(sv)) - sv_unref(sv); - (void)SvUPGRADE(sv, SVt_PV); /* Never FALSE */ - SvGROW(sv, len + 1); - Move(s,SvPVX(sv),len,char); - SvCUR_set(sv, len); - *SvEND(sv) = '\0'; - } - if (!SvPOK(sv)) { - SvPOK_on(sv); /* validate pointer */ - SvTAINT(sv); - DEBUG_c(PerlIO_printf(Perl_debug_log, "0x%"UVxf" 2pv(%s)\n", - PTR2UV(sv),SvPVX(sv))); - } - } - return SvPVX(sv); -} - -char * -Perl_sv_pvbyte(pTHX_ SV *sv) -{ - return sv_pv(sv); -} - -char * -Perl_sv_pvbyten(pTHX_ SV *sv, STRLEN *lp) -{ - return sv_pvn(sv,lp); -} - -char * -Perl_sv_pvbyten_force(pTHX_ SV *sv, STRLEN *lp) -{ - return sv_pvn_force(sv,lp); -} - -char * -Perl_sv_pvutf8(pTHX_ SV *sv) -{ - sv_utf8_upgrade(sv); - return sv_pv(sv); -} - -char * -Perl_sv_pvutf8n(pTHX_ SV *sv, STRLEN *lp) -{ - sv_utf8_upgrade(sv); - return sv_pvn(sv,lp); -} - -/* -=for apidoc sv_pvutf8n_force - -Get a sensible UTF8-encoded string out of the SV somehow. See -L</sv_pvn_force>. - -=cut -*/ - -char * -Perl_sv_pvutf8n_force(pTHX_ SV *sv, STRLEN *lp) -{ - sv_utf8_upgrade(sv); - return sv_pvn_force(sv,lp); -} - -/* -=for apidoc sv_reftype - -Returns a string describing what the SV is a reference to. - -=cut -*/ - -char * -Perl_sv_reftype(pTHX_ SV *sv, int ob) -{ - if (ob && SvOBJECT(sv)) - return HvNAME(SvSTASH(sv)); - else { - switch (SvTYPE(sv)) { - case SVt_NULL: - case SVt_IV: - case SVt_NV: - case SVt_RV: - case SVt_PV: - case SVt_PVIV: - case SVt_PVNV: - case SVt_PVMG: - case SVt_PVBM: - if (SvROK(sv)) - return "REF"; - else - return "SCALAR"; - case SVt_PVLV: return "LVALUE"; - case SVt_PVAV: return "ARRAY"; - case SVt_PVHV: return "HASH"; - case SVt_PVCV: return "CODE"; - case SVt_PVGV: return "GLOB"; - case SVt_PVFM: return "FORMAT"; - case SVt_PVIO: return "IO"; - default: return "UNKNOWN"; - } - } -} - -/* -=for apidoc sv_isobject - -Returns a boolean indicating whether the SV is an RV pointing to a blessed -object. If the SV is not an RV, or if the object is not blessed, then this -will return false. - -=cut -*/ - -int -Perl_sv_isobject(pTHX_ SV *sv) -{ - if (!sv) - return 0; - if (SvGMAGICAL(sv)) - mg_get(sv); - if (!SvROK(sv)) - return 0; - sv = (SV*)SvRV(sv); - if (!SvOBJECT(sv)) - return 0; - return 1; -} - -/* -=for apidoc sv_isa - -Returns a boolean indicating whether the SV is blessed into the specified -class. This does not check for subtypes; use C<sv_derived_from> to verify -an inheritance relationship. - -=cut -*/ - -int -Perl_sv_isa(pTHX_ SV *sv, const char *name) -{ - if (!sv) - return 0; - if (SvGMAGICAL(sv)) - mg_get(sv); - if (!SvROK(sv)) - return 0; - sv = (SV*)SvRV(sv); - if (!SvOBJECT(sv)) - return 0; - - return strEQ(HvNAME(SvSTASH(sv)), name); -} - -/* -=for apidoc newSVrv - -Creates a new SV for the RV, C<rv>, to point to. If C<rv> is not an RV then -it will be upgraded to one. If C<classname> is non-null then the new SV will -be blessed in the specified package. The new SV is returned and its -reference count is 1. - -=cut -*/ - -SV* -Perl_newSVrv(pTHX_ SV *rv, const char *classname) -{ - SV *sv; - - new_SV(sv); - - SV_CHECK_THINKFIRST(rv); - SvAMAGIC_off(rv); - - if (SvTYPE(rv) >= SVt_PVMG) { - U32 refcnt = SvREFCNT(rv); - SvREFCNT(rv) = 0; - sv_clear(rv); - SvFLAGS(rv) = 0; - SvREFCNT(rv) = refcnt; - } - - if (SvTYPE(rv) < SVt_RV) - sv_upgrade(rv, SVt_RV); - else if (SvTYPE(rv) > SVt_RV) { - (void)SvOOK_off(rv); - if (SvPVX(rv) && SvLEN(rv)) - Safefree(SvPVX(rv)); - SvCUR_set(rv, 0); - SvLEN_set(rv, 0); - } - - (void)SvOK_off(rv); - SvRV(rv) = sv; - SvROK_on(rv); - - if (classname) { - HV* stash = gv_stashpv(classname, TRUE); - (void)sv_bless(rv, stash); - } - return sv; -} - -/* -=for apidoc sv_setref_pv - -Copies a pointer into a new SV, optionally blessing the SV. The C<rv> -argument will be upgraded to an RV. That RV will be modified to point to -the new SV. If the C<pv> argument is NULL then C<PL_sv_undef> will be placed -into the SV. The C<classname> argument indicates the package for the -blessing. Set C<classname> to C<Nullch> to avoid the blessing. The new SV -will be returned and will have a reference count of 1. - -Do not use with other Perl types such as HV, AV, SV, CV, because those -objects will become corrupted by the pointer copy process. - -Note that C<sv_setref_pvn> copies the string while this copies the pointer. - -=cut -*/ - -SV* -Perl_sv_setref_pv(pTHX_ SV *rv, const char *classname, void *pv) -{ - if (!pv) { - sv_setsv(rv, &PL_sv_undef); - SvSETMAGIC(rv); - } - else - sv_setiv(newSVrv(rv,classname), PTR2IV(pv)); - return rv; -} - -/* -=for apidoc sv_setref_iv - -Copies an integer into a new SV, optionally blessing the SV. The C<rv> -argument will be upgraded to an RV. That RV will be modified to point to -the new SV. The C<classname> argument indicates the package for the -blessing. Set C<classname> to C<Nullch> to avoid the blessing. The new SV -will be returned and will have a reference count of 1. - -=cut -*/ - -SV* -Perl_sv_setref_iv(pTHX_ SV *rv, const char *classname, IV iv) -{ - sv_setiv(newSVrv(rv,classname), iv); - return rv; -} - -/* -=for apidoc sv_setref_nv - -Copies a double into a new SV, optionally blessing the SV. The C<rv> -argument will be upgraded to an RV. That RV will be modified to point to -the new SV. The C<classname> argument indicates the package for the -blessing. Set C<classname> to C<Nullch> to avoid the blessing. The new SV -will be returned and will have a reference count of 1. - -=cut -*/ - -SV* -Perl_sv_setref_nv(pTHX_ SV *rv, const char *classname, NV nv) -{ - sv_setnv(newSVrv(rv,classname), nv); - return rv; -} - -/* -=for apidoc sv_setref_pvn - -Copies a string into a new SV, optionally blessing the SV. The length of the -string must be specified with C<n>. The C<rv> argument will be upgraded to -an RV. That RV will be modified to point to the new SV. The C<classname> -argument indicates the package for the blessing. Set C<classname> to -C<Nullch> to avoid the blessing. The new SV will be returned and will have -a reference count of 1. - -Note that C<sv_setref_pv> copies the pointer while this copies the string. - -=cut -*/ - -SV* -Perl_sv_setref_pvn(pTHX_ SV *rv, const char *classname, char *pv, STRLEN n) -{ - sv_setpvn(newSVrv(rv,classname), pv, n); - return rv; -} - -/* -=for apidoc sv_bless - -Blesses an SV into a specified package. The SV must be an RV. The package -must be designated by its stash (see C<gv_stashpv()>). The reference count -of the SV is unaffected. - -=cut -*/ - -SV* -Perl_sv_bless(pTHX_ SV *sv, HV *stash) -{ - SV *tmpRef; - if (!SvROK(sv)) - Perl_croak(aTHX_ "Can't bless non-reference value"); - tmpRef = SvRV(sv); - if (SvFLAGS(tmpRef) & (SVs_OBJECT|SVf_READONLY)) { - if (SvREADONLY(tmpRef)) - Perl_croak(aTHX_ PL_no_modify); - if (SvOBJECT(tmpRef)) { - if (SvTYPE(tmpRef) != SVt_PVIO) - --PL_sv_objcount; - SvREFCNT_dec(SvSTASH(tmpRef)); - } - } - SvOBJECT_on(tmpRef); - if (SvTYPE(tmpRef) != SVt_PVIO) - ++PL_sv_objcount; - (void)SvUPGRADE(tmpRef, SVt_PVMG); - SvSTASH(tmpRef) = (HV*)SvREFCNT_inc(stash); - - if (Gv_AMG(stash)) - SvAMAGIC_on(sv); - else - SvAMAGIC_off(sv); - - return sv; -} - -STATIC void -S_sv_unglob(pTHX_ SV *sv) -{ - void *xpvmg; - - assert(SvTYPE(sv) == SVt_PVGV); - SvFAKE_off(sv); - if (GvGP(sv)) - gp_free((GV*)sv); - if (GvSTASH(sv)) { - SvREFCNT_dec(GvSTASH(sv)); - GvSTASH(sv) = Nullhv; - } - sv_unmagic(sv, '*'); - Safefree(GvNAME(sv)); - GvMULTI_off(sv); - - /* need to keep SvANY(sv) in the right arena */ - xpvmg = new_XPVMG(); - StructCopy(SvANY(sv), xpvmg, XPVMG); - del_XPVGV(SvANY(sv)); - SvANY(sv) = xpvmg; - - SvFLAGS(sv) &= ~SVTYPEMASK; - SvFLAGS(sv) |= SVt_PVMG; -} - -/* -=for apidoc sv_unref - -Unsets the RV status of the SV, and decrements the reference count of -whatever was being referenced by the RV. This can almost be thought of -as a reversal of C<newSVrv>. See C<SvROK_off>. - -=cut -*/ - -void -Perl_sv_unref(pTHX_ SV *sv) -{ - SV* rv = SvRV(sv); - - if (SvWEAKREF(sv)) { - sv_del_backref(sv); - SvWEAKREF_off(sv); - SvRV(sv) = 0; - return; - } - SvRV(sv) = 0; - SvROK_off(sv); - if (SvREFCNT(rv) != 1 || SvREADONLY(rv)) - SvREFCNT_dec(rv); - else - sv_2mortal(rv); /* Schedule for freeing later */ -} - -void -Perl_sv_taint(pTHX_ SV *sv) -{ - sv_magic((sv), Nullsv, 't', Nullch, 0); -} - -void -Perl_sv_untaint(pTHX_ SV *sv) -{ - if (SvTYPE(sv) >= SVt_PVMG && SvMAGIC(sv)) { - MAGIC *mg = mg_find(sv, 't'); - if (mg) - mg->mg_len &= ~1; - } -} - -bool -Perl_sv_tainted(pTHX_ SV *sv) -{ - if (SvTYPE(sv) >= SVt_PVMG && SvMAGIC(sv)) { - MAGIC *mg = mg_find(sv, 't'); - if (mg && ((mg->mg_len & 1) || ((mg->mg_len & 2) && mg->mg_obj == sv))) - return TRUE; - } - return FALSE; -} - -/* -=for apidoc sv_setpviv - -Copies an integer into the given SV, also updating its string value. -Does not handle 'set' magic. See C<sv_setpviv_mg>. - -=cut -*/ - -void -Perl_sv_setpviv(pTHX_ SV *sv, IV iv) -{ - char buf[TYPE_CHARS(UV)]; - char *ebuf; - char *ptr = uiv_2buf(buf, iv, 0, 0, &ebuf); - - sv_setpvn(sv, ptr, ebuf - ptr); -} - - -/* -=for apidoc sv_setpviv_mg - -Like C<sv_setpviv>, but also handles 'set' magic. - -=cut -*/ - -void -Perl_sv_setpviv_mg(pTHX_ SV *sv, IV iv) -{ - char buf[TYPE_CHARS(UV)]; - char *ebuf; - char *ptr = uiv_2buf(buf, iv, 0, 0, &ebuf); - - sv_setpvn(sv, ptr, ebuf - ptr); - SvSETMAGIC(sv); -} - -#if defined(PERL_IMPLICIT_CONTEXT) -void -Perl_sv_setpvf_nocontext(SV *sv, const char* pat, ...) -{ - dTHX; - va_list args; - va_start(args, pat); - sv_vsetpvf(sv, pat, &args); - va_end(args); -} - - -void -Perl_sv_setpvf_mg_nocontext(SV *sv, const char* pat, ...) -{ - dTHX; - va_list args; - va_start(args, pat); - sv_vsetpvf_mg(sv, pat, &args); - va_end(args); -} -#endif - -/* -=for apidoc sv_setpvf - -Processes its arguments like C<sprintf> and sets an SV to the formatted -output. Does not handle 'set' magic. See C<sv_setpvf_mg>. - -=cut -*/ - -void -Perl_sv_setpvf(pTHX_ SV *sv, const char* pat, ...) -{ - va_list args; - va_start(args, pat); - sv_vsetpvf(sv, pat, &args); - va_end(args); -} - -void -Perl_sv_vsetpvf(pTHX_ SV *sv, const char* pat, va_list* args) -{ - sv_vsetpvfn(sv, pat, strlen(pat), args, Null(SV**), 0, Null(bool*)); -} - -/* -=for apidoc sv_setpvf_mg - -Like C<sv_setpvf>, but also handles 'set' magic. - -=cut -*/ - -void -Perl_sv_setpvf_mg(pTHX_ SV *sv, const char* pat, ...) -{ - va_list args; - va_start(args, pat); - sv_vsetpvf_mg(sv, pat, &args); - va_end(args); -} - -void -Perl_sv_vsetpvf_mg(pTHX_ SV *sv, const char* pat, va_list* args) -{ - sv_vsetpvfn(sv, pat, strlen(pat), args, Null(SV**), 0, Null(bool*)); - SvSETMAGIC(sv); -} - -#if defined(PERL_IMPLICIT_CONTEXT) -void -Perl_sv_catpvf_nocontext(SV *sv, const char* pat, ...) -{ - dTHX; - va_list args; - va_start(args, pat); - sv_vcatpvf(sv, pat, &args); - va_end(args); -} - -void -Perl_sv_catpvf_mg_nocontext(SV *sv, const char* pat, ...) -{ - dTHX; - va_list args; - va_start(args, pat); - sv_vcatpvf_mg(sv, pat, &args); - va_end(args); -} -#endif - -/* -=for apidoc sv_catpvf - -Processes its arguments like C<sprintf> and appends the formatted output -to an SV. Handles 'get' magic, but not 'set' magic. C<SvSETMAGIC()> must -typically be called after calling this function to handle 'set' magic. - -=cut -*/ - -void -Perl_sv_catpvf(pTHX_ SV *sv, const char* pat, ...) -{ - va_list args; - va_start(args, pat); - sv_vcatpvf(sv, pat, &args); - va_end(args); -} - -void -Perl_sv_vcatpvf(pTHX_ SV *sv, const char* pat, va_list* args) -{ - sv_vcatpvfn(sv, pat, strlen(pat), args, Null(SV**), 0, Null(bool*)); -} - -/* -=for apidoc sv_catpvf_mg - -Like C<sv_catpvf>, but also handles 'set' magic. - -=cut -*/ - -void -Perl_sv_catpvf_mg(pTHX_ SV *sv, const char* pat, ...) -{ - va_list args; - va_start(args, pat); - sv_vcatpvf_mg(sv, pat, &args); - va_end(args); -} - -void -Perl_sv_vcatpvf_mg(pTHX_ SV *sv, const char* pat, va_list* args) -{ - sv_vcatpvfn(sv, pat, strlen(pat), args, Null(SV**), 0, Null(bool*)); - SvSETMAGIC(sv); -} - -/* -=for apidoc sv_vsetpvfn - -Works like C<vcatpvfn> but copies the text into the SV instead of -appending it. - -=cut -*/ - -void -Perl_sv_vsetpvfn(pTHX_ SV *sv, const char *pat, STRLEN patlen, va_list *args, SV **svargs, I32 svmax, bool *maybe_tainted) -{ - sv_setpvn(sv, "", 0); - sv_vcatpvfn(sv, pat, patlen, args, svargs, svmax, maybe_tainted); -} - -/* -=for apidoc sv_vcatpvfn - -Processes its arguments like C<vsprintf> and appends the formatted output -to an SV. Uses an array of SVs if the C style variable argument list is -missing (NULL). When running with taint checks enabled, indicates via -C<maybe_tainted> if results are untrustworthy (often due to the use of -locales). - -=cut -*/ - -void -Perl_sv_vcatpvfn(pTHX_ SV *sv, const char *pat, STRLEN patlen, va_list *args, SV **svargs, I32 svmax, bool *maybe_tainted) -{ - char *p; - char *q; - char *patend; - STRLEN origlen; - I32 svix = 0; - static char nullstr[] = "(null)"; - SV *argsv; - - /* no matter what, this is a string now */ - (void)SvPV_force(sv, origlen); - - /* special-case "", "%s", and "%_" */ - if (patlen == 0) - return; - if (patlen == 2 && pat[0] == '%') { - switch (pat[1]) { - case 's': - if (args) { - char *s = va_arg(*args, char*); - sv_catpv(sv, s ? s : nullstr); - } - else if (svix < svmax) { - sv_catsv(sv, *svargs); - if (DO_UTF8(*svargs)) - SvUTF8_on(sv); - } - return; - case '_': - if (args) { - argsv = va_arg(*args, SV*); - sv_catsv(sv, argsv); - if (DO_UTF8(argsv)) - SvUTF8_on(sv); - return; - } - /* See comment on '_' below */ - break; - } - } - - patend = (char*)pat + patlen; - for (p = (char*)pat; p < patend; p = q) { - bool alt = FALSE; - bool left = FALSE; - bool vectorize = FALSE; - bool utf = FALSE; - char fill = ' '; - char plus = 0; - char intsize = 0; - STRLEN width = 0; - STRLEN zeros = 0; - bool has_precis = FALSE; - STRLEN precis = 0; - bool is_utf = FALSE; - - char esignbuf[4]; - U8 utf8buf[UTF8_MAXLEN+1]; - STRLEN esignlen = 0; - - char *eptr = Nullch; - STRLEN elen = 0; - /* Times 4: a decimal digit takes more than 3 binary digits. - * NV_DIG: mantissa takes than many decimal digits. - * Plus 32: Playing safe. */ - char ebuf[IV_DIG * 4 + NV_DIG + 32]; - /* large enough for "%#.#f" --chip */ - /* what about long double NVs? --jhi */ - - SV *vecsv; - U8 *vecstr = Null(U8*); - STRLEN veclen = 0; - char c; - int i; - unsigned base; - IV iv; - UV uv; - NV nv; - STRLEN have; - STRLEN need; - STRLEN gap; - char *dotstr = "."; - STRLEN dotstrlen = 1; - - for (q = p; q < patend && *q != '%'; ++q) ; - if (q > p) { - sv_catpvn(sv, p, q - p); - p = q; - } - if (q++ >= patend) - break; - - /* FLAGS */ - - while (*q) { - switch (*q) { - case ' ': - case '+': - plus = *q++; - continue; - - case '-': - left = TRUE; - q++; - continue; - - case '0': - fill = *q++; - continue; - - case '#': - alt = TRUE; - q++; - continue; - - case '*': /* printf("%*vX",":",$ipv6addr) */ - if (q[1] != 'v') - break; - q++; - if (args) - vecsv = va_arg(*args, SV*); - else if (svix < svmax) - vecsv = svargs[svix++]; - else - continue; - dotstr = SvPVx(vecsv,dotstrlen); - if (DO_UTF8(vecsv)) - is_utf = TRUE; - /* FALL THROUGH */ - - case 'v': - vectorize = TRUE; - q++; - continue; - - default: - break; - } - break; - } - - /* WIDTH */ - - switch (*q) { - case '1': case '2': case '3': - case '4': case '5': case '6': - case '7': case '8': case '9': - width = 0; - while (isDIGIT(*q)) - width = width * 10 + (*q++ - '0'); - break; - - case '*': - if (args) - i = va_arg(*args, int); - else - i = (svix < svmax) ? SvIVx(svargs[svix++]) : 0; - left |= (i < 0); - width = (i < 0) ? -i : i; - q++; - break; - } - - /* PRECISION */ - - if (*q == '.') { - q++; - if (*q == '*') { - if (args) - i = va_arg(*args, int); - else - i = (svix < svmax) ? SvIVx(svargs[svix++]) : 0; - precis = (i < 0) ? 0 : i; - q++; - } - else { - precis = 0; - while (isDIGIT(*q)) - precis = precis * 10 + (*q++ - '0'); - } - has_precis = TRUE; - } - - if (vectorize) { - if (args) { - vecsv = va_arg(*args, SV*); - vecstr = (U8*)SvPVx(vecsv,veclen); - utf = DO_UTF8(vecsv); - } - else if (svix < svmax) { - vecsv = svargs[svix++]; - vecstr = (U8*)SvPVx(vecsv,veclen); - utf = DO_UTF8(vecsv); - } - else { - vecstr = (U8*)""; - veclen = 0; - } - } - - /* SIZE */ - - switch (*q) { -#if defined(HAS_QUAD) || (defined(HAS_LONG_DOUBLE) && defined(USE_LONG_DOUBLE)) - case 'L': /* Ld */ - /* FALL THROUGH */ -#endif -#ifdef HAS_QUAD - case 'q': /* qd */ - intsize = 'q'; - q++; - break; -#endif - case 'l': -#if defined(HAS_QUAD) || (defined(HAS_LONG_DOUBLE) && defined(USE_LONG_DOUBLE)) - if (*(q + 1) == 'l') { /* lld, llf */ - intsize = 'q'; - q += 2; - break; - } -#endif - /* FALL THROUGH */ - case 'h': - /* FALL THROUGH */ - case 'V': - intsize = *q++; - break; - } - - /* CONVERSION */ - - switch (c = *q++) { - - /* STRINGS */ - - case '%': - eptr = q - 1; - elen = 1; - goto string; - - case 'c': - if (args) - uv = va_arg(*args, int); - else - uv = (svix < svmax) ? SvIVx(svargs[svix++]) : 0; - if ((uv > 255 || (uv > 127 && SvUTF8(sv))) && !IN_BYTE) { - eptr = (char*)utf8buf; - elen = uv_to_utf8((U8*)eptr, uv) - utf8buf; - is_utf = TRUE; - } - else { - c = (char)uv; - eptr = &c; - elen = 1; - } - goto string; - - case 's': - if (args) { - eptr = va_arg(*args, char*); - if (eptr) -#ifdef MACOS_TRADITIONAL - /* On MacOS, %#s format is used for Pascal strings */ - if (alt) - elen = *eptr++; - else -#endif - elen = strlen(eptr); - else { - eptr = nullstr; - elen = sizeof nullstr - 1; - } - } - else if (svix < svmax) { - argsv = svargs[svix++]; - eptr = SvPVx(argsv, elen); - if (DO_UTF8(argsv)) { - if (has_precis && precis < elen) { - I32 p = precis; - sv_pos_u2b(argsv, &p, 0); /* sticks at end */ - precis = p; - } - if (width) { /* fudge width (can't fudge elen) */ - width += elen - sv_len_utf8(argsv); - } - is_utf = TRUE; - } - } - goto string; - - case '_': - /* - * The "%_" hack might have to be changed someday, - * if ISO or ANSI decide to use '_' for something. - * So we keep it hidden from users' code. - */ - if (!args) - goto unknown; - argsv = va_arg(*args,SV*); - eptr = SvPVx(argsv, elen); - if (DO_UTF8(argsv)) - is_utf = TRUE; - - string: - vectorize = FALSE; - if (has_precis && elen > precis) - elen = precis; - break; - - /* INTEGERS */ - - case 'p': - if (alt) - goto unknown; - if (args) - uv = PTR2UV(va_arg(*args, void*)); - else - uv = (svix < svmax) ? PTR2UV(svargs[svix++]) : 0; - base = 16; - goto integer; - - case 'D': -#ifdef IV_IS_QUAD - intsize = 'q'; -#else - intsize = 'l'; -#endif - /* FALL THROUGH */ - case 'd': - case 'i': - if (vectorize) { - STRLEN ulen; - if (!veclen) { - vectorize = FALSE; - break; - } - if (utf) - iv = (IV)utf8_to_uv(vecstr, veclen, &ulen, 0); - else { - iv = *vecstr; - ulen = 1; - } - vecstr += ulen; - veclen -= ulen; - } - else if (args) { - switch (intsize) { - case 'h': iv = (short)va_arg(*args, int); break; - default: iv = va_arg(*args, int); break; - case 'l': iv = va_arg(*args, long); break; - case 'V': iv = va_arg(*args, IV); break; -#ifdef HAS_QUAD - case 'q': iv = va_arg(*args, Quad_t); break; -#endif - } - } - else { - iv = (svix < svmax) ? SvIVx(svargs[svix++]) : 0; - switch (intsize) { - case 'h': iv = (short)iv; break; - default: break; - case 'l': iv = (long)iv; break; - case 'V': break; -#ifdef HAS_QUAD - case 'q': iv = (Quad_t)iv; break; -#endif - } - } - if (iv >= 0) { - uv = iv; - if (plus) - esignbuf[esignlen++] = plus; - } - else { - uv = -iv; - esignbuf[esignlen++] = '-'; - } - base = 10; - goto integer; - - case 'U': -#ifdef IV_IS_QUAD - intsize = 'q'; -#else - intsize = 'l'; -#endif - /* FALL THROUGH */ - case 'u': - base = 10; - goto uns_integer; - - case 'b': - base = 2; - goto uns_integer; - - case 'O': -#ifdef IV_IS_QUAD - intsize = 'q'; -#else - intsize = 'l'; -#endif - /* FALL THROUGH */ - case 'o': - base = 8; - goto uns_integer; - - case 'X': - case 'x': - base = 16; - - uns_integer: - if (vectorize) { - STRLEN ulen; - vector: - if (!veclen) { - vectorize = FALSE; - break; - } - if (utf) - uv = utf8_to_uv(vecstr, veclen, &ulen, 0); - else { - uv = *vecstr; - ulen = 1; - } - vecstr += ulen; - veclen -= ulen; - } - else if (args) { - switch (intsize) { - case 'h': uv = (unsigned short)va_arg(*args, unsigned); break; - default: uv = va_arg(*args, unsigned); break; - case 'l': uv = va_arg(*args, unsigned long); break; - case 'V': uv = va_arg(*args, UV); break; -#ifdef HAS_QUAD - case 'q': uv = va_arg(*args, Quad_t); break; -#endif - } - } - else { - uv = (svix < svmax) ? SvUVx(svargs[svix++]) : 0; - switch (intsize) { - case 'h': uv = (unsigned short)uv; break; - default: break; - case 'l': uv = (unsigned long)uv; break; - case 'V': break; -#ifdef HAS_QUAD - case 'q': uv = (Quad_t)uv; break; -#endif - } - } - - integer: - eptr = ebuf + sizeof ebuf; - switch (base) { - unsigned dig; - case 16: - if (!uv) - alt = FALSE; - p = (char*)((c == 'X') - ? "0123456789ABCDEF" : "0123456789abcdef"); - do { - dig = uv & 15; - *--eptr = p[dig]; - } while (uv >>= 4); - if (alt) { - esignbuf[esignlen++] = '0'; - esignbuf[esignlen++] = c; /* 'x' or 'X' */ - } - break; - case 8: - do { - dig = uv & 7; - *--eptr = '0' + dig; - } while (uv >>= 3); - if (alt && *eptr != '0') - *--eptr = '0'; - break; - case 2: - do { - dig = uv & 1; - *--eptr = '0' + dig; - } while (uv >>= 1); - if (alt) { - esignbuf[esignlen++] = '0'; - esignbuf[esignlen++] = 'b'; - } - break; - default: /* it had better be ten or less */ -#if defined(PERL_Y2KWARN) - if (ckWARN(WARN_Y2K)) { - STRLEN n; - char *s = SvPV(sv,n); - if (n >= 2 && s[n-2] == '1' && s[n-1] == '9' - && (n == 2 || !isDIGIT(s[n-3]))) - { - Perl_warner(aTHX_ WARN_Y2K, - "Possible Y2K bug: %%%c %s", - c, "format string following '19'"); - } - } -#endif - do { - dig = uv % base; - *--eptr = '0' + dig; - } while (uv /= base); - break; - } - elen = (ebuf + sizeof ebuf) - eptr; - if (has_precis) { - if (precis > elen) - zeros = precis - elen; - else if (precis == 0 && elen == 1 && *eptr == '0') - elen = 0; - } - break; - - /* FLOATING POINT */ - - case 'F': - c = 'f'; /* maybe %F isn't supported here */ - /* FALL THROUGH */ - case 'e': case 'E': - case 'f': - case 'g': case 'G': - - /* This is evil, but floating point is even more evil */ - - vectorize = FALSE; - if (args) - nv = va_arg(*args, NV); - else - nv = (svix < svmax) ? SvNVx(svargs[svix++]) : 0.0; - - need = 0; - if (c != 'e' && c != 'E') { - i = PERL_INT_MIN; - (void)Perl_frexp(nv, &i); - if (i == PERL_INT_MIN) - Perl_die(aTHX_ "panic: frexp"); - if (i > 0) - need = BIT_DIGITS(i); - } - need += has_precis ? precis : 6; /* known default */ - if (need < width) - need = width; - - need += 20; /* fudge factor */ - if (PL_efloatsize < need) { - Safefree(PL_efloatbuf); - PL_efloatsize = need + 20; /* more fudge */ - New(906, PL_efloatbuf, PL_efloatsize, char); - PL_efloatbuf[0] = '\0'; - } - - eptr = ebuf + sizeof ebuf; - *--eptr = '\0'; - *--eptr = c; -#if defined(USE_LONG_DOUBLE) && defined(PERL_PRIfldbl) - { - /* Copy the one or more characters in a long double - * format before the 'base' ([efgEFG]) character to - * the format string. */ - static char const prifldbl[] = PERL_PRIfldbl; - char const *p = prifldbl + sizeof(prifldbl) - 3; - while (p >= prifldbl) { *--eptr = *p--; } - } -#endif - if (has_precis) { - base = precis; - do { *--eptr = '0' + (base % 10); } while (base /= 10); - *--eptr = '.'; - } - if (width) { - base = width; - do { *--eptr = '0' + (base % 10); } while (base /= 10); - } - if (fill == '0') - *--eptr = fill; - if (left) - *--eptr = '-'; - if (plus) - *--eptr = plus; - if (alt) - *--eptr = '#'; - *--eptr = '%'; - - /* No taint. Otherwise we are in the strange situation - * where printf() taints but print($float) doesn't. - * --jhi */ - (void)sprintf(PL_efloatbuf, eptr, nv); - - eptr = PL_efloatbuf; - elen = strlen(PL_efloatbuf); - break; - - /* SPECIAL */ - - case 'n': - vectorize = FALSE; - i = SvCUR(sv) - origlen; - if (args) { - switch (intsize) { - case 'h': *(va_arg(*args, short*)) = i; break; - default: *(va_arg(*args, int*)) = i; break; - case 'l': *(va_arg(*args, long*)) = i; break; - case 'V': *(va_arg(*args, IV*)) = i; break; -#ifdef HAS_QUAD - case 'q': *(va_arg(*args, Quad_t*)) = i; break; -#endif - } - } - else if (svix < svmax) - sv_setuv_mg(svargs[svix++], (UV)i); - continue; /* not "break" */ - - /* UNKNOWN */ - - default: - unknown: - vectorize = FALSE; - if (!args && ckWARN(WARN_PRINTF) && - (PL_op->op_type == OP_PRTF || PL_op->op_type == OP_SPRINTF)) { - SV *msg = sv_newmortal(); - Perl_sv_setpvf(aTHX_ msg, "Invalid conversion in %s: ", - (PL_op->op_type == OP_PRTF) ? "printf" : "sprintf"); - if (c) { - if (isPRINT(c)) - Perl_sv_catpvf(aTHX_ msg, - "\"%%%c\"", c & 0xFF); - else - Perl_sv_catpvf(aTHX_ msg, - "\"%%\\%03"UVof"\"", - (UV)c & 0xFF); - } else - sv_catpv(msg, "end of string"); - Perl_warner(aTHX_ WARN_PRINTF, "%"SVf, msg); /* yes, this is reentrant */ - } - - /* output mangled stuff ... */ - if (c == '\0') - --q; - eptr = p; - elen = q - p; - - /* ... right here, because formatting flags should not apply */ - SvGROW(sv, SvCUR(sv) + elen + 1); - p = SvEND(sv); - memcpy(p, eptr, elen); - p += elen; - *p = '\0'; - SvCUR(sv) = p - SvPVX(sv); - continue; /* not "break" */ - } - - have = esignlen + zeros + elen; - need = (have > width ? have : width); - gap = need - have; - - SvGROW(sv, SvCUR(sv) + need + dotstrlen + 1); - p = SvEND(sv); - if (esignlen && fill == '0') { - for (i = 0; i < esignlen; i++) - *p++ = esignbuf[i]; - } - if (gap && !left) { - memset(p, fill, gap); - p += gap; - } - if (esignlen && fill != '0') { - for (i = 0; i < esignlen; i++) - *p++ = esignbuf[i]; - } - if (zeros) { - for (i = zeros; i; i--) - *p++ = '0'; - } - if (elen) { - memcpy(p, eptr, elen); - p += elen; - } - if (gap && left) { - memset(p, ' ', gap); - p += gap; - } - if (vectorize) { - if (veclen) { - memcpy(p, dotstr, dotstrlen); - p += dotstrlen; - } - else - vectorize = FALSE; /* done iterating over vecstr */ - } - if (is_utf) - SvUTF8_on(sv); - *p = '\0'; - SvCUR(sv) = p - SvPVX(sv); - if (vectorize) { - esignlen = 0; - goto vector; - } - } -} - -#if defined(USE_ITHREADS) - -#if defined(USE_THREADS) -# include "error: USE_THREADS and USE_ITHREADS are incompatible" -#endif - -#ifndef GpREFCNT_inc -# define GpREFCNT_inc(gp) ((gp) ? (++(gp)->gp_refcnt, (gp)) : (GP*)NULL) -#endif - - -#define sv_dup_inc(s) SvREFCNT_inc(sv_dup(s)) -#define av_dup(s) (AV*)sv_dup((SV*)s) -#define av_dup_inc(s) (AV*)SvREFCNT_inc(sv_dup((SV*)s)) -#define hv_dup(s) (HV*)sv_dup((SV*)s) -#define hv_dup_inc(s) (HV*)SvREFCNT_inc(sv_dup((SV*)s)) -#define cv_dup(s) (CV*)sv_dup((SV*)s) -#define cv_dup_inc(s) (CV*)SvREFCNT_inc(sv_dup((SV*)s)) -#define io_dup(s) (IO*)sv_dup((SV*)s) -#define io_dup_inc(s) (IO*)SvREFCNT_inc(sv_dup((SV*)s)) -#define gv_dup(s) (GV*)sv_dup((SV*)s) -#define gv_dup_inc(s) (GV*)SvREFCNT_inc(sv_dup((SV*)s)) -#define SAVEPV(p) (p ? savepv(p) : Nullch) -#define SAVEPVN(p,n) (p ? savepvn(p,n) : Nullch) - -REGEXP * -Perl_re_dup(pTHX_ REGEXP *r) -{ - /* XXX fix when pmop->op_pmregexp becomes shared */ - return ReREFCNT_inc(r); -} - -PerlIO * -Perl_fp_dup(pTHX_ PerlIO *fp, char type) -{ - PerlIO *ret; - if (!fp) - return (PerlIO*)NULL; - - /* look for it in the table first */ - ret = (PerlIO*)ptr_table_fetch(PL_ptr_table, fp); - if (ret) - return ret; - - /* create anew and remember what it is */ - ret = PerlIO_fdupopen(fp); - ptr_table_store(PL_ptr_table, fp, ret); - return ret; -} - -DIR * -Perl_dirp_dup(pTHX_ DIR *dp) -{ - if (!dp) - return (DIR*)NULL; - /* XXX TODO */ - return dp; -} - -GP * -Perl_gp_dup(pTHX_ GP *gp) -{ - GP *ret; - if (!gp) - return (GP*)NULL; - /* look for it in the table first */ - ret = (GP*)ptr_table_fetch(PL_ptr_table, gp); - if (ret) - return ret; - - /* create anew and remember what it is */ - Newz(0, ret, 1, GP); - ptr_table_store(PL_ptr_table, gp, ret); - - /* clone */ - ret->gp_refcnt = 0; /* must be before any other dups! */ - ret->gp_sv = sv_dup_inc(gp->gp_sv); - ret->gp_io = io_dup_inc(gp->gp_io); - ret->gp_form = cv_dup_inc(gp->gp_form); - ret->gp_av = av_dup_inc(gp->gp_av); - ret->gp_hv = hv_dup_inc(gp->gp_hv); - ret->gp_egv = gv_dup(gp->gp_egv); /* GvEGV is not refcounted */ - ret->gp_cv = cv_dup_inc(gp->gp_cv); - ret->gp_cvgen = gp->gp_cvgen; - ret->gp_flags = gp->gp_flags; - ret->gp_line = gp->gp_line; - ret->gp_file = gp->gp_file; /* points to COP.cop_file */ - return ret; -} - -MAGIC * -Perl_mg_dup(pTHX_ MAGIC *mg) -{ - MAGIC *mgprev = (MAGIC*)NULL; - MAGIC *mgret; - if (!mg) - return (MAGIC*)NULL; - /* look for it in the table first */ - mgret = (MAGIC*)ptr_table_fetch(PL_ptr_table, mg); - if (mgret) - return mgret; - - for (; mg; mg = mg->mg_moremagic) { - MAGIC *nmg; - Newz(0, nmg, 1, MAGIC); - if (mgprev) - mgprev->mg_moremagic = nmg; - else - mgret = nmg; - nmg->mg_virtual = mg->mg_virtual; /* XXX copy dynamic vtable? */ - nmg->mg_private = mg->mg_private; - nmg->mg_type = mg->mg_type; - nmg->mg_flags = mg->mg_flags; - if (mg->mg_type == 'r') { - nmg->mg_obj = (SV*)re_dup((REGEXP*)mg->mg_obj); - } - else { - nmg->mg_obj = (mg->mg_flags & MGf_REFCOUNTED) - ? sv_dup_inc(mg->mg_obj) - : sv_dup(mg->mg_obj); - } - nmg->mg_len = mg->mg_len; - nmg->mg_ptr = mg->mg_ptr; /* XXX random ptr? */ - if (mg->mg_ptr && mg->mg_type != 'g') { - if (mg->mg_len >= 0) { - nmg->mg_ptr = SAVEPVN(mg->mg_ptr, mg->mg_len); - if (mg->mg_type == 'c' && AMT_AMAGIC((AMT*)mg->mg_ptr)) { - AMT *amtp = (AMT*)mg->mg_ptr; - AMT *namtp = (AMT*)nmg->mg_ptr; - I32 i; - for (i = 1; i < NofAMmeth; i++) { - namtp->table[i] = cv_dup_inc(amtp->table[i]); - } - } - } - else if (mg->mg_len == HEf_SVKEY) - nmg->mg_ptr = (char*)sv_dup_inc((SV*)mg->mg_ptr); - } - mgprev = nmg; - } - return mgret; -} - -PTR_TBL_t * -Perl_ptr_table_new(pTHX) -{ - PTR_TBL_t *tbl; - Newz(0, tbl, 1, PTR_TBL_t); - tbl->tbl_max = 511; - tbl->tbl_items = 0; - Newz(0, tbl->tbl_ary, tbl->tbl_max + 1, PTR_TBL_ENT_t*); - return tbl; -} - -void * -Perl_ptr_table_fetch(pTHX_ PTR_TBL_t *tbl, void *sv) -{ - PTR_TBL_ENT_t *tblent; - UV hash = PTR2UV(sv); - assert(tbl); - tblent = tbl->tbl_ary[hash & tbl->tbl_max]; - for (; tblent; tblent = tblent->next) { - if (tblent->oldval == sv) - return tblent->newval; - } - return (void*)NULL; -} - -void -Perl_ptr_table_store(pTHX_ PTR_TBL_t *tbl, void *oldv, void *newv) -{ - PTR_TBL_ENT_t *tblent, **otblent; - /* XXX this may be pessimal on platforms where pointers aren't good - * hash values e.g. if they grow faster in the most significant - * bits */ - UV hash = PTR2UV(oldv); - bool i = 1; - - assert(tbl); - otblent = &tbl->tbl_ary[hash & tbl->tbl_max]; - for (tblent = *otblent; tblent; i=0, tblent = tblent->next) { - if (tblent->oldval == oldv) { - tblent->newval = newv; - tbl->tbl_items++; - return; - } - } - Newz(0, tblent, 1, PTR_TBL_ENT_t); - tblent->oldval = oldv; - tblent->newval = newv; - tblent->next = *otblent; - *otblent = tblent; - tbl->tbl_items++; - if (i && tbl->tbl_items > tbl->tbl_max) - ptr_table_split(tbl); -} - -void -Perl_ptr_table_split(pTHX_ PTR_TBL_t *tbl) -{ - PTR_TBL_ENT_t **ary = tbl->tbl_ary; - UV oldsize = tbl->tbl_max + 1; - UV newsize = oldsize * 2; - UV i; - - Renew(ary, newsize, PTR_TBL_ENT_t*); - Zero(&ary[oldsize], newsize-oldsize, PTR_TBL_ENT_t*); - tbl->tbl_max = --newsize; - tbl->tbl_ary = ary; - for (i=0; i < oldsize; i++, ary++) { - PTR_TBL_ENT_t **curentp, **entp, *ent; - if (!*ary) - continue; - curentp = ary + oldsize; - for (entp = ary, ent = *ary; ent; ent = *entp) { - if ((newsize & PTR2UV(ent->oldval)) != i) { - *entp = ent->next; - ent->next = *curentp; - *curentp = ent; - continue; - } - else - entp = &ent->next; - } - } -} - -void -Perl_ptr_table_clear(pTHX_ PTR_TBL_t *tbl) -{ - register PTR_TBL_ENT_t **array; - register PTR_TBL_ENT_t *entry; - register PTR_TBL_ENT_t *oentry = Null(PTR_TBL_ENT_t*); - UV riter = 0; - UV max; - - if (!tbl || !tbl->tbl_items) { - return; - } - - array = tbl->tbl_ary; - entry = array[0]; - max = tbl->tbl_max; - - for (;;) { - if (entry) { - oentry = entry; - entry = entry->next; - Safefree(oentry); - } - if (!entry) { - if (++riter > max) { - break; - } - entry = array[riter]; - } - } - - tbl->tbl_items = 0; -} - -void -Perl_ptr_table_free(pTHX_ PTR_TBL_t *tbl) -{ - if (!tbl) { - return; - } - ptr_table_clear(tbl); - Safefree(tbl->tbl_ary); - Safefree(tbl); -} - -#ifdef DEBUGGING -char *PL_watch_pvx; -#endif - -SV * -Perl_sv_dup(pTHX_ SV *sstr) -{ - SV *dstr; - - if (!sstr || SvTYPE(sstr) == SVTYPEMASK) - return Nullsv; - /* look for it in the table first */ - dstr = (SV*)ptr_table_fetch(PL_ptr_table, sstr); - if (dstr) - return dstr; - - /* create anew and remember what it is */ - new_SV(dstr); - ptr_table_store(PL_ptr_table, sstr, dstr); - - /* clone */ - SvFLAGS(dstr) = SvFLAGS(sstr); - SvFLAGS(dstr) &= ~SVf_OOK; /* don't propagate OOK hack */ - SvREFCNT(dstr) = 0; /* must be before any other dups! */ - -#ifdef DEBUGGING - if (SvANY(sstr) && PL_watch_pvx && SvPVX(sstr) == PL_watch_pvx) - PerlIO_printf(Perl_debug_log, "watch at %p hit, found string \"%s\"\n", - PL_watch_pvx, SvPVX(sstr)); -#endif - - switch (SvTYPE(sstr)) { - case SVt_NULL: - SvANY(dstr) = NULL; - break; - case SVt_IV: - SvANY(dstr) = new_XIV(); - SvIVX(dstr) = SvIVX(sstr); - break; - case SVt_NV: - SvANY(dstr) = new_XNV(); - SvNVX(dstr) = SvNVX(sstr); - break; - case SVt_RV: - SvANY(dstr) = new_XRV(); - SvRV(dstr) = sv_dup_inc(SvRV(sstr)); - break; - case SVt_PV: - SvANY(dstr) = new_XPV(); - SvCUR(dstr) = SvCUR(sstr); - SvLEN(dstr) = SvLEN(sstr); - if (SvROK(sstr)) - SvRV(dstr) = sv_dup_inc(SvRV(sstr)); - else if (SvPVX(sstr) && SvLEN(sstr)) - SvPVX(dstr) = SAVEPVN(SvPVX(sstr), SvLEN(sstr)-1); - else - SvPVX(dstr) = SvPVX(sstr); /* XXX shared string/random ptr? */ - break; - case SVt_PVIV: - SvANY(dstr) = new_XPVIV(); - SvCUR(dstr) = SvCUR(sstr); - SvLEN(dstr) = SvLEN(sstr); - SvIVX(dstr) = SvIVX(sstr); - if (SvROK(sstr)) - SvRV(dstr) = sv_dup_inc(SvRV(sstr)); - else if (SvPVX(sstr) && SvLEN(sstr)) - SvPVX(dstr) = SAVEPVN(SvPVX(sstr), SvLEN(sstr)-1); - else - SvPVX(dstr) = SvPVX(sstr); /* XXX shared string/random ptr? */ - break; - case SVt_PVNV: - SvANY(dstr) = new_XPVNV(); - SvCUR(dstr) = SvCUR(sstr); - SvLEN(dstr) = SvLEN(sstr); - SvIVX(dstr) = SvIVX(sstr); - SvNVX(dstr) = SvNVX(sstr); - if (SvROK(sstr)) - SvRV(dstr) = sv_dup_inc(SvRV(sstr)); - else if (SvPVX(sstr) && SvLEN(sstr)) - SvPVX(dstr) = SAVEPVN(SvPVX(sstr), SvLEN(sstr)-1); - else - SvPVX(dstr) = SvPVX(sstr); /* XXX shared string/random ptr? */ - break; - case SVt_PVMG: - SvANY(dstr) = new_XPVMG(); - SvCUR(dstr) = SvCUR(sstr); - SvLEN(dstr) = SvLEN(sstr); - SvIVX(dstr) = SvIVX(sstr); - SvNVX(dstr) = SvNVX(sstr); - SvMAGIC(dstr) = mg_dup(SvMAGIC(sstr)); - SvSTASH(dstr) = hv_dup_inc(SvSTASH(sstr)); - if (SvROK(sstr)) - SvRV(dstr) = sv_dup_inc(SvRV(sstr)); - else if (SvPVX(sstr) && SvLEN(sstr)) - SvPVX(dstr) = SAVEPVN(SvPVX(sstr), SvLEN(sstr)-1); - else - SvPVX(dstr) = SvPVX(sstr); /* XXX shared string/random ptr? */ - break; - case SVt_PVBM: - SvANY(dstr) = new_XPVBM(); - SvCUR(dstr) = SvCUR(sstr); - SvLEN(dstr) = SvLEN(sstr); - SvIVX(dstr) = SvIVX(sstr); - SvNVX(dstr) = SvNVX(sstr); - SvMAGIC(dstr) = mg_dup(SvMAGIC(sstr)); - SvSTASH(dstr) = hv_dup_inc(SvSTASH(sstr)); - if (SvROK(sstr)) - SvRV(dstr) = sv_dup_inc(SvRV(sstr)); - else if (SvPVX(sstr) && SvLEN(sstr)) - SvPVX(dstr) = SAVEPVN(SvPVX(sstr), SvLEN(sstr)-1); - else - SvPVX(dstr) = SvPVX(sstr); /* XXX shared string/random ptr? */ - BmRARE(dstr) = BmRARE(sstr); - BmUSEFUL(dstr) = BmUSEFUL(sstr); - BmPREVIOUS(dstr)= BmPREVIOUS(sstr); - break; - case SVt_PVLV: - SvANY(dstr) = new_XPVLV(); - SvCUR(dstr) = SvCUR(sstr); - SvLEN(dstr) = SvLEN(sstr); - SvIVX(dstr) = SvIVX(sstr); - SvNVX(dstr) = SvNVX(sstr); - SvMAGIC(dstr) = mg_dup(SvMAGIC(sstr)); - SvSTASH(dstr) = hv_dup_inc(SvSTASH(sstr)); - if (SvROK(sstr)) - SvRV(dstr) = sv_dup_inc(SvRV(sstr)); - else if (SvPVX(sstr) && SvLEN(sstr)) - SvPVX(dstr) = SAVEPVN(SvPVX(sstr), SvLEN(sstr)-1); - else - SvPVX(dstr) = SvPVX(sstr); /* XXX shared string/random ptr? */ - LvTARGOFF(dstr) = LvTARGOFF(sstr); /* XXX sometimes holds PMOP* when DEBUGGING */ - LvTARGLEN(dstr) = LvTARGLEN(sstr); - LvTARG(dstr) = sv_dup_inc(LvTARG(sstr)); - LvTYPE(dstr) = LvTYPE(sstr); - break; - case SVt_PVGV: - SvANY(dstr) = new_XPVGV(); - SvCUR(dstr) = SvCUR(sstr); - SvLEN(dstr) = SvLEN(sstr); - SvIVX(dstr) = SvIVX(sstr); - SvNVX(dstr) = SvNVX(sstr); - SvMAGIC(dstr) = mg_dup(SvMAGIC(sstr)); - SvSTASH(dstr) = hv_dup_inc(SvSTASH(sstr)); - if (SvROK(sstr)) - SvRV(dstr) = sv_dup_inc(SvRV(sstr)); - else if (SvPVX(sstr) && SvLEN(sstr)) - SvPVX(dstr) = SAVEPVN(SvPVX(sstr), SvLEN(sstr)-1); - else - SvPVX(dstr) = SvPVX(sstr); /* XXX shared string/random ptr? */ - GvNAMELEN(dstr) = GvNAMELEN(sstr); - GvNAME(dstr) = SAVEPVN(GvNAME(sstr), GvNAMELEN(sstr)); - GvSTASH(dstr) = hv_dup_inc(GvSTASH(sstr)); - GvFLAGS(dstr) = GvFLAGS(sstr); - GvGP(dstr) = gp_dup(GvGP(sstr)); - (void)GpREFCNT_inc(GvGP(dstr)); - break; - case SVt_PVIO: - SvANY(dstr) = new_XPVIO(); - SvCUR(dstr) = SvCUR(sstr); - SvLEN(dstr) = SvLEN(sstr); - SvIVX(dstr) = SvIVX(sstr); - SvNVX(dstr) = SvNVX(sstr); - SvMAGIC(dstr) = mg_dup(SvMAGIC(sstr)); - SvSTASH(dstr) = hv_dup_inc(SvSTASH(sstr)); - if (SvROK(sstr)) - SvRV(dstr) = sv_dup_inc(SvRV(sstr)); - else if (SvPVX(sstr) && SvLEN(sstr)) - SvPVX(dstr) = SAVEPVN(SvPVX(sstr), SvLEN(sstr)-1); - else - SvPVX(dstr) = SvPVX(sstr); /* XXX shared string/random ptr? */ - IoIFP(dstr) = fp_dup(IoIFP(sstr), IoTYPE(sstr)); - if (IoOFP(sstr) == IoIFP(sstr)) - IoOFP(dstr) = IoIFP(dstr); - else - IoOFP(dstr) = fp_dup(IoOFP(sstr), IoTYPE(sstr)); - /* PL_rsfp_filters entries have fake IoDIRP() */ - if (IoDIRP(sstr) && !(IoFLAGS(sstr) & IOf_FAKE_DIRP)) - IoDIRP(dstr) = dirp_dup(IoDIRP(sstr)); - else - IoDIRP(dstr) = IoDIRP(sstr); - IoLINES(dstr) = IoLINES(sstr); - IoPAGE(dstr) = IoPAGE(sstr); - IoPAGE_LEN(dstr) = IoPAGE_LEN(sstr); - IoLINES_LEFT(dstr) = IoLINES_LEFT(sstr); - IoTOP_NAME(dstr) = SAVEPV(IoTOP_NAME(sstr)); - IoTOP_GV(dstr) = gv_dup(IoTOP_GV(sstr)); - IoFMT_NAME(dstr) = SAVEPV(IoFMT_NAME(sstr)); - IoFMT_GV(dstr) = gv_dup(IoFMT_GV(sstr)); - IoBOTTOM_NAME(dstr) = SAVEPV(IoBOTTOM_NAME(sstr)); - IoBOTTOM_GV(dstr) = gv_dup(IoBOTTOM_GV(sstr)); - IoSUBPROCESS(dstr) = IoSUBPROCESS(sstr); - IoTYPE(dstr) = IoTYPE(sstr); - IoFLAGS(dstr) = IoFLAGS(sstr); - break; - case SVt_PVAV: - SvANY(dstr) = new_XPVAV(); - SvCUR(dstr) = SvCUR(sstr); - SvLEN(dstr) = SvLEN(sstr); - SvIVX(dstr) = SvIVX(sstr); - SvNVX(dstr) = SvNVX(sstr); - SvMAGIC(dstr) = mg_dup(SvMAGIC(sstr)); - SvSTASH(dstr) = hv_dup_inc(SvSTASH(sstr)); - AvARYLEN((AV*)dstr) = sv_dup_inc(AvARYLEN((AV*)sstr)); - AvFLAGS((AV*)dstr) = AvFLAGS((AV*)sstr); - if (AvARRAY((AV*)sstr)) { - SV **dst_ary, **src_ary; - SSize_t items = AvFILLp((AV*)sstr) + 1; - - src_ary = AvARRAY((AV*)sstr); - Newz(0, dst_ary, AvMAX((AV*)sstr)+1, SV*); - ptr_table_store(PL_ptr_table, src_ary, dst_ary); - SvPVX(dstr) = (char*)dst_ary; - AvALLOC((AV*)dstr) = dst_ary; - if (AvREAL((AV*)sstr)) { - while (items-- > 0) - *dst_ary++ = sv_dup_inc(*src_ary++); - } - else { - while (items-- > 0) - *dst_ary++ = sv_dup(*src_ary++); - } - items = AvMAX((AV*)sstr) - AvFILLp((AV*)sstr); - while (items-- > 0) { - *dst_ary++ = &PL_sv_undef; - } - } - else { - SvPVX(dstr) = Nullch; - AvALLOC((AV*)dstr) = (SV**)NULL; - } - break; - case SVt_PVHV: - SvANY(dstr) = new_XPVHV(); - SvCUR(dstr) = SvCUR(sstr); - SvLEN(dstr) = SvLEN(sstr); - SvIVX(dstr) = SvIVX(sstr); - SvNVX(dstr) = SvNVX(sstr); - SvMAGIC(dstr) = mg_dup(SvMAGIC(sstr)); - SvSTASH(dstr) = hv_dup_inc(SvSTASH(sstr)); - HvRITER((HV*)dstr) = HvRITER((HV*)sstr); - if (HvARRAY((HV*)sstr)) { - STRLEN i = 0; - XPVHV *dxhv = (XPVHV*)SvANY(dstr); - XPVHV *sxhv = (XPVHV*)SvANY(sstr); - Newz(0, dxhv->xhv_array, - PERL_HV_ARRAY_ALLOC_BYTES(dxhv->xhv_max+1), char); - while (i <= sxhv->xhv_max) { - ((HE**)dxhv->xhv_array)[i] = he_dup(((HE**)sxhv->xhv_array)[i], - !!HvSHAREKEYS(sstr)); - ++i; - } - dxhv->xhv_eiter = he_dup(sxhv->xhv_eiter, !!HvSHAREKEYS(sstr)); - } - else { - SvPVX(dstr) = Nullch; - HvEITER((HV*)dstr) = (HE*)NULL; - } - HvPMROOT((HV*)dstr) = HvPMROOT((HV*)sstr); /* XXX */ - HvNAME((HV*)dstr) = SAVEPV(HvNAME((HV*)sstr)); - break; - case SVt_PVFM: - SvANY(dstr) = new_XPVFM(); - FmLINES(dstr) = FmLINES(sstr); - goto dup_pvcv; - /* NOTREACHED */ - case SVt_PVCV: - SvANY(dstr) = new_XPVCV(); -dup_pvcv: - SvCUR(dstr) = SvCUR(sstr); - SvLEN(dstr) = SvLEN(sstr); - SvIVX(dstr) = SvIVX(sstr); - SvNVX(dstr) = SvNVX(sstr); - SvMAGIC(dstr) = mg_dup(SvMAGIC(sstr)); - SvSTASH(dstr) = hv_dup_inc(SvSTASH(sstr)); - if (SvPVX(sstr) && SvLEN(sstr)) - SvPVX(dstr) = SAVEPVN(SvPVX(sstr), SvLEN(sstr)-1); - else - SvPVX(dstr) = SvPVX(sstr); /* XXX shared string/random ptr? */ - CvSTASH(dstr) = hv_dup(CvSTASH(sstr));/* NOTE: not refcounted */ - CvSTART(dstr) = CvSTART(sstr); - CvROOT(dstr) = OpREFCNT_inc(CvROOT(sstr)); - CvXSUB(dstr) = CvXSUB(sstr); - CvXSUBANY(dstr) = CvXSUBANY(sstr); - CvGV(dstr) = gv_dup(CvGV(sstr)); - CvDEPTH(dstr) = CvDEPTH(sstr); - if (CvPADLIST(sstr) && !AvREAL(CvPADLIST(sstr))) { - /* XXX padlists are real, but pretend to be not */ - AvREAL_on(CvPADLIST(sstr)); - CvPADLIST(dstr) = av_dup_inc(CvPADLIST(sstr)); - AvREAL_off(CvPADLIST(sstr)); - AvREAL_off(CvPADLIST(dstr)); - } - else - CvPADLIST(dstr) = av_dup_inc(CvPADLIST(sstr)); - if (!CvANON(sstr) || CvCLONED(sstr)) - CvOUTSIDE(dstr) = cv_dup_inc(CvOUTSIDE(sstr)); - else - CvOUTSIDE(dstr) = cv_dup(CvOUTSIDE(sstr)); - CvFLAGS(dstr) = CvFLAGS(sstr); - break; - default: - Perl_croak(aTHX_ "Bizarre SvTYPE [%d]", SvTYPE(sstr)); - break; - } - - if (SvOBJECT(dstr) && SvTYPE(dstr) != SVt_PVIO) - ++PL_sv_objcount; - - return dstr; -} - -PERL_CONTEXT * -Perl_cx_dup(pTHX_ PERL_CONTEXT *cxs, I32 ix, I32 max) -{ - PERL_CONTEXT *ncxs; - - if (!cxs) - return (PERL_CONTEXT*)NULL; - - /* look for it in the table first */ - ncxs = (PERL_CONTEXT*)ptr_table_fetch(PL_ptr_table, cxs); - if (ncxs) - return ncxs; - - /* create anew and remember what it is */ - Newz(56, ncxs, max + 1, PERL_CONTEXT); - ptr_table_store(PL_ptr_table, cxs, ncxs); - - while (ix >= 0) { - PERL_CONTEXT *cx = &cxs[ix]; - PERL_CONTEXT *ncx = &ncxs[ix]; - ncx->cx_type = cx->cx_type; - if (CxTYPE(cx) == CXt_SUBST) { - Perl_croak(aTHX_ "Cloning substitution context is unimplemented"); - } - else { - ncx->blk_oldsp = cx->blk_oldsp; - ncx->blk_oldcop = cx->blk_oldcop; - ncx->blk_oldretsp = cx->blk_oldretsp; - ncx->blk_oldmarksp = cx->blk_oldmarksp; - ncx->blk_oldscopesp = cx->blk_oldscopesp; - ncx->blk_oldpm = cx->blk_oldpm; - ncx->blk_gimme = cx->blk_gimme; - switch (CxTYPE(cx)) { - case CXt_SUB: - ncx->blk_sub.cv = (cx->blk_sub.olddepth == 0 - ? cv_dup_inc(cx->blk_sub.cv) - : cv_dup(cx->blk_sub.cv)); - ncx->blk_sub.argarray = (cx->blk_sub.hasargs - ? av_dup_inc(cx->blk_sub.argarray) - : Nullav); - ncx->blk_sub.savearray = av_dup_inc(cx->blk_sub.savearray); - ncx->blk_sub.olddepth = cx->blk_sub.olddepth; - ncx->blk_sub.hasargs = cx->blk_sub.hasargs; - ncx->blk_sub.lval = cx->blk_sub.lval; - break; - case CXt_EVAL: - ncx->blk_eval.old_in_eval = cx->blk_eval.old_in_eval; - ncx->blk_eval.old_op_type = cx->blk_eval.old_op_type; - ncx->blk_eval.old_namesv = sv_dup_inc(cx->blk_eval.old_namesv); - ncx->blk_eval.old_eval_root = cx->blk_eval.old_eval_root; - ncx->blk_eval.cur_text = sv_dup(cx->blk_eval.cur_text); - break; - case CXt_LOOP: - ncx->blk_loop.label = cx->blk_loop.label; - ncx->blk_loop.resetsp = cx->blk_loop.resetsp; - ncx->blk_loop.redo_op = cx->blk_loop.redo_op; - ncx->blk_loop.next_op = cx->blk_loop.next_op; - ncx->blk_loop.last_op = cx->blk_loop.last_op; - ncx->blk_loop.iterdata = (CxPADLOOP(cx) - ? cx->blk_loop.iterdata - : gv_dup((GV*)cx->blk_loop.iterdata)); - ncx->blk_loop.oldcurpad - = (SV**)ptr_table_fetch(PL_ptr_table, - cx->blk_loop.oldcurpad); - ncx->blk_loop.itersave = sv_dup_inc(cx->blk_loop.itersave); - ncx->blk_loop.iterlval = sv_dup_inc(cx->blk_loop.iterlval); - ncx->blk_loop.iterary = av_dup_inc(cx->blk_loop.iterary); - ncx->blk_loop.iterix = cx->blk_loop.iterix; - ncx->blk_loop.itermax = cx->blk_loop.itermax; - break; - case CXt_FORMAT: - ncx->blk_sub.cv = cv_dup(cx->blk_sub.cv); - ncx->blk_sub.gv = gv_dup(cx->blk_sub.gv); - ncx->blk_sub.dfoutgv = gv_dup_inc(cx->blk_sub.dfoutgv); - ncx->blk_sub.hasargs = cx->blk_sub.hasargs; - break; - case CXt_BLOCK: - case CXt_NULL: - break; - } - } - --ix; - } - return ncxs; -} - -PERL_SI * -Perl_si_dup(pTHX_ PERL_SI *si) -{ - PERL_SI *nsi; - - if (!si) - return (PERL_SI*)NULL; - - /* look for it in the table first */ - nsi = (PERL_SI*)ptr_table_fetch(PL_ptr_table, si); - if (nsi) - return nsi; - - /* create anew and remember what it is */ - Newz(56, nsi, 1, PERL_SI); - ptr_table_store(PL_ptr_table, si, nsi); - - nsi->si_stack = av_dup_inc(si->si_stack); - nsi->si_cxix = si->si_cxix; - nsi->si_cxmax = si->si_cxmax; - nsi->si_cxstack = cx_dup(si->si_cxstack, si->si_cxix, si->si_cxmax); - nsi->si_type = si->si_type; - nsi->si_prev = si_dup(si->si_prev); - nsi->si_next = si_dup(si->si_next); - nsi->si_markoff = si->si_markoff; - - return nsi; -} - -#define POPINT(ss,ix) ((ss)[--(ix)].any_i32) -#define TOPINT(ss,ix) ((ss)[ix].any_i32) -#define POPLONG(ss,ix) ((ss)[--(ix)].any_long) -#define TOPLONG(ss,ix) ((ss)[ix].any_long) -#define POPIV(ss,ix) ((ss)[--(ix)].any_iv) -#define TOPIV(ss,ix) ((ss)[ix].any_iv) -#define POPPTR(ss,ix) ((ss)[--(ix)].any_ptr) -#define TOPPTR(ss,ix) ((ss)[ix].any_ptr) -#define POPDPTR(ss,ix) ((ss)[--(ix)].any_dptr) -#define TOPDPTR(ss,ix) ((ss)[ix].any_dptr) -#define POPDXPTR(ss,ix) ((ss)[--(ix)].any_dxptr) -#define TOPDXPTR(ss,ix) ((ss)[ix].any_dxptr) - -/* XXXXX todo */ -#define pv_dup_inc(p) SAVEPV(p) -#define pv_dup(p) SAVEPV(p) -#define svp_dup_inc(p,pp) any_dup(p,pp) - -void * -Perl_any_dup(pTHX_ void *v, PerlInterpreter *proto_perl) -{ - void *ret; - - if (!v) - return (void*)NULL; - - /* look for it in the table first */ - ret = ptr_table_fetch(PL_ptr_table, v); - if (ret) - return ret; - - /* see if it is part of the interpreter structure */ - if (v >= (void*)proto_perl && v < (void*)(proto_perl+1)) - ret = (void*)(((char*)aTHXo) + (((char*)v) - (char*)proto_perl)); - else - ret = v; - - return ret; -} - -ANY * -Perl_ss_dup(pTHX_ PerlInterpreter *proto_perl) -{ - ANY *ss = proto_perl->Tsavestack; - I32 ix = proto_perl->Tsavestack_ix; - I32 max = proto_perl->Tsavestack_max; - ANY *nss; - SV *sv; - GV *gv; - AV *av; - HV *hv; - void* ptr; - int intval; - long longval; - GP *gp; - IV iv; - I32 i; - char *c; - void (*dptr) (void*); - void (*dxptr) (pTHXo_ void*); - OP *o; - - Newz(54, nss, max, ANY); - - while (ix > 0) { - i = POPINT(ss,ix); - TOPINT(nss,ix) = i; - switch (i) { - case SAVEt_ITEM: /* normal string */ - sv = (SV*)POPPTR(ss,ix); - TOPPTR(nss,ix) = sv_dup_inc(sv); - sv = (SV*)POPPTR(ss,ix); - TOPPTR(nss,ix) = sv_dup_inc(sv); - break; - case SAVEt_SV: /* scalar reference */ - sv = (SV*)POPPTR(ss,ix); - TOPPTR(nss,ix) = sv_dup_inc(sv); - gv = (GV*)POPPTR(ss,ix); - TOPPTR(nss,ix) = gv_dup_inc(gv); - break; - case SAVEt_GENERIC_PVREF: /* generic char* */ - c = (char*)POPPTR(ss,ix); - TOPPTR(nss,ix) = pv_dup(c); - ptr = POPPTR(ss,ix); - TOPPTR(nss,ix) = any_dup(ptr, proto_perl); - break; - case SAVEt_GENERIC_SVREF: /* generic sv */ - case SAVEt_SVREF: /* scalar reference */ - sv = (SV*)POPPTR(ss,ix); - TOPPTR(nss,ix) = sv_dup_inc(sv); - ptr = POPPTR(ss,ix); - TOPPTR(nss,ix) = svp_dup_inc((SV**)ptr, proto_perl);/* XXXXX */ - break; - case SAVEt_AV: /* array reference */ - av = (AV*)POPPTR(ss,ix); - TOPPTR(nss,ix) = av_dup_inc(av); - gv = (GV*)POPPTR(ss,ix); - TOPPTR(nss,ix) = gv_dup(gv); - break; - case SAVEt_HV: /* hash reference */ - hv = (HV*)POPPTR(ss,ix); - TOPPTR(nss,ix) = hv_dup_inc(hv); - gv = (GV*)POPPTR(ss,ix); - TOPPTR(nss,ix) = gv_dup(gv); - break; - case SAVEt_INT: /* int reference */ - ptr = POPPTR(ss,ix); - TOPPTR(nss,ix) = any_dup(ptr, proto_perl); - intval = (int)POPINT(ss,ix); - TOPINT(nss,ix) = intval; - break; - case SAVEt_LONG: /* long reference */ - ptr = POPPTR(ss,ix); - TOPPTR(nss,ix) = any_dup(ptr, proto_perl); - longval = (long)POPLONG(ss,ix); - TOPLONG(nss,ix) = longval; - break; - case SAVEt_I32: /* I32 reference */ - case SAVEt_I16: /* I16 reference */ - case SAVEt_I8: /* I8 reference */ - ptr = POPPTR(ss,ix); - TOPPTR(nss,ix) = any_dup(ptr, proto_perl); - i = POPINT(ss,ix); - TOPINT(nss,ix) = i; - break; - case SAVEt_IV: /* IV reference */ - ptr = POPPTR(ss,ix); - TOPPTR(nss,ix) = any_dup(ptr, proto_perl); - iv = POPIV(ss,ix); - TOPIV(nss,ix) = iv; - break; - case SAVEt_SPTR: /* SV* reference */ - ptr = POPPTR(ss,ix); - TOPPTR(nss,ix) = any_dup(ptr, proto_perl); - sv = (SV*)POPPTR(ss,ix); - TOPPTR(nss,ix) = sv_dup(sv); - break; - case SAVEt_VPTR: /* random* reference */ - ptr = POPPTR(ss,ix); - TOPPTR(nss,ix) = any_dup(ptr, proto_perl); - ptr = POPPTR(ss,ix); - TOPPTR(nss,ix) = any_dup(ptr, proto_perl); - break; - case SAVEt_PPTR: /* char* reference */ - ptr = POPPTR(ss,ix); - TOPPTR(nss,ix) = any_dup(ptr, proto_perl); - c = (char*)POPPTR(ss,ix); - TOPPTR(nss,ix) = pv_dup(c); - break; - case SAVEt_HPTR: /* HV* reference */ - ptr = POPPTR(ss,ix); - TOPPTR(nss,ix) = any_dup(ptr, proto_perl); - hv = (HV*)POPPTR(ss,ix); - TOPPTR(nss,ix) = hv_dup(hv); - break; - case SAVEt_APTR: /* AV* reference */ - ptr = POPPTR(ss,ix); - TOPPTR(nss,ix) = any_dup(ptr, proto_perl); - av = (AV*)POPPTR(ss,ix); - TOPPTR(nss,ix) = av_dup(av); - break; - case SAVEt_NSTAB: - gv = (GV*)POPPTR(ss,ix); - TOPPTR(nss,ix) = gv_dup(gv); - break; - case SAVEt_GP: /* scalar reference */ - gp = (GP*)POPPTR(ss,ix); - TOPPTR(nss,ix) = gp = gp_dup(gp); - (void)GpREFCNT_inc(gp); - gv = (GV*)POPPTR(ss,ix); - TOPPTR(nss,ix) = gv_dup_inc(c); - c = (char*)POPPTR(ss,ix); - TOPPTR(nss,ix) = pv_dup(c); - iv = POPIV(ss,ix); - TOPIV(nss,ix) = iv; - iv = POPIV(ss,ix); - TOPIV(nss,ix) = iv; - break; - case SAVEt_FREESV: - case SAVEt_MORTALIZESV: - sv = (SV*)POPPTR(ss,ix); - TOPPTR(nss,ix) = sv_dup_inc(sv); - break; - case SAVEt_FREEOP: - ptr = POPPTR(ss,ix); - if (ptr && (((OP*)ptr)->op_private & OPpREFCOUNTED)) { - /* these are assumed to be refcounted properly */ - switch (((OP*)ptr)->op_type) { - case OP_LEAVESUB: - case OP_LEAVESUBLV: - case OP_LEAVEEVAL: - case OP_LEAVE: - case OP_SCOPE: - case OP_LEAVEWRITE: - TOPPTR(nss,ix) = ptr; - o = (OP*)ptr; - OpREFCNT_inc(o); - break; - default: - TOPPTR(nss,ix) = Nullop; - break; - } - } - else - TOPPTR(nss,ix) = Nullop; - break; - case SAVEt_FREEPV: - c = (char*)POPPTR(ss,ix); - TOPPTR(nss,ix) = pv_dup_inc(c); - break; - case SAVEt_CLEARSV: - longval = POPLONG(ss,ix); - TOPLONG(nss,ix) = longval; - break; - case SAVEt_DELETE: - hv = (HV*)POPPTR(ss,ix); - TOPPTR(nss,ix) = hv_dup_inc(hv); - c = (char*)POPPTR(ss,ix); - TOPPTR(nss,ix) = pv_dup_inc(c); - i = POPINT(ss,ix); - TOPINT(nss,ix) = i; - break; - case SAVEt_DESTRUCTOR: - ptr = POPPTR(ss,ix); - TOPPTR(nss,ix) = any_dup(ptr, proto_perl); /* XXX quite arbitrary */ - dptr = POPDPTR(ss,ix); - TOPDPTR(nss,ix) = (void (*)(void*))any_dup((void *)dptr, proto_perl); - break; - case SAVEt_DESTRUCTOR_X: - ptr = POPPTR(ss,ix); - TOPPTR(nss,ix) = any_dup(ptr, proto_perl); /* XXX quite arbitrary */ - dxptr = POPDXPTR(ss,ix); - TOPDXPTR(nss,ix) = (void (*)(pTHXo_ void*))any_dup((void *)dxptr, proto_perl); - break; - case SAVEt_REGCONTEXT: - case SAVEt_ALLOC: - i = POPINT(ss,ix); - TOPINT(nss,ix) = i; - ix -= i; - break; - case SAVEt_STACK_POS: /* Position on Perl stack */ - i = POPINT(ss,ix); - TOPINT(nss,ix) = i; - break; - case SAVEt_AELEM: /* array element */ - sv = (SV*)POPPTR(ss,ix); - TOPPTR(nss,ix) = sv_dup_inc(sv); - i = POPINT(ss,ix); - TOPINT(nss,ix) = i; - av = (AV*)POPPTR(ss,ix); - TOPPTR(nss,ix) = av_dup_inc(av); - break; - case SAVEt_HELEM: /* hash element */ - sv = (SV*)POPPTR(ss,ix); - TOPPTR(nss,ix) = sv_dup_inc(sv); - sv = (SV*)POPPTR(ss,ix); - TOPPTR(nss,ix) = sv_dup_inc(sv); - hv = (HV*)POPPTR(ss,ix); - TOPPTR(nss,ix) = hv_dup_inc(hv); - break; - case SAVEt_OP: - ptr = POPPTR(ss,ix); - TOPPTR(nss,ix) = ptr; - break; - case SAVEt_HINTS: - i = POPINT(ss,ix); - TOPINT(nss,ix) = i; - break; - case SAVEt_COMPPAD: - av = (AV*)POPPTR(ss,ix); - TOPPTR(nss,ix) = av_dup(av); - break; - case SAVEt_PADSV: - longval = (long)POPLONG(ss,ix); - TOPLONG(nss,ix) = longval; - ptr = POPPTR(ss,ix); - TOPPTR(nss,ix) = any_dup(ptr, proto_perl); - sv = (SV*)POPPTR(ss,ix); - TOPPTR(nss,ix) = sv_dup(sv); - break; - default: - Perl_croak(aTHX_ "panic: ss_dup inconsistency"); - } - } - - return nss; -} - -#ifdef PERL_OBJECT -#include "XSUB.h" -#endif - -PerlInterpreter * -perl_clone(PerlInterpreter *proto_perl, UV flags) -{ -#ifdef PERL_OBJECT - CPerlObj *pPerl = (CPerlObj*)proto_perl; -#endif - -#ifdef PERL_IMPLICIT_SYS - return perl_clone_using(proto_perl, flags, - proto_perl->IMem, - proto_perl->IMemShared, - proto_perl->IMemParse, - proto_perl->IEnv, - proto_perl->IStdIO, - proto_perl->ILIO, - proto_perl->IDir, - proto_perl->ISock, - proto_perl->IProc); -} - -PerlInterpreter * -perl_clone_using(PerlInterpreter *proto_perl, UV flags, - struct IPerlMem* ipM, struct IPerlMem* ipMS, - struct IPerlMem* ipMP, struct IPerlEnv* ipE, - struct IPerlStdIO* ipStd, struct IPerlLIO* ipLIO, - struct IPerlDir* ipD, struct IPerlSock* ipS, - struct IPerlProc* ipP) -{ - /* XXX many of the string copies here can be optimized if they're - * constants; they need to be allocated as common memory and just - * their pointers copied. */ - - IV i; -# ifdef PERL_OBJECT - CPerlObj *pPerl = new(ipM) CPerlObj(ipM, ipMS, ipMP, ipE, ipStd, ipLIO, - ipD, ipS, ipP); - PERL_SET_THX(pPerl); -# else /* !PERL_OBJECT */ - PerlInterpreter *my_perl = (PerlInterpreter*)(*ipM->pMalloc)(ipM, sizeof(PerlInterpreter)); - PERL_SET_THX(my_perl); - -# ifdef DEBUGGING - memset(my_perl, 0xab, sizeof(PerlInterpreter)); - PL_markstack = 0; - PL_scopestack = 0; - PL_savestack = 0; - PL_retstack = 0; -# else /* !DEBUGGING */ - Zero(my_perl, 1, PerlInterpreter); -# endif /* DEBUGGING */ - - /* host pointers */ - PL_Mem = ipM; - PL_MemShared = ipMS; - PL_MemParse = ipMP; - PL_Env = ipE; - PL_StdIO = ipStd; - PL_LIO = ipLIO; - PL_Dir = ipD; - PL_Sock = ipS; - PL_Proc = ipP; -# endif /* PERL_OBJECT */ -#else /* !PERL_IMPLICIT_SYS */ - IV i; - PerlInterpreter *my_perl = (PerlInterpreter*)PerlMem_malloc(sizeof(PerlInterpreter)); - PERL_SET_THX(my_perl); - -# ifdef DEBUGGING - memset(my_perl, 0xab, sizeof(PerlInterpreter)); - PL_markstack = 0; - PL_scopestack = 0; - PL_savestack = 0; - PL_retstack = 0; -# else /* !DEBUGGING */ - Zero(my_perl, 1, PerlInterpreter); -# endif /* DEBUGGING */ -#endif /* PERL_IMPLICIT_SYS */ - - /* arena roots */ - PL_xiv_arenaroot = NULL; - PL_xiv_root = NULL; - PL_xnv_arenaroot = NULL; - PL_xnv_root = NULL; - PL_xrv_arenaroot = NULL; - PL_xrv_root = NULL; - PL_xpv_arenaroot = NULL; - PL_xpv_root = NULL; - PL_xpviv_arenaroot = NULL; - PL_xpviv_root = NULL; - PL_xpvnv_arenaroot = NULL; - PL_xpvnv_root = NULL; - PL_xpvcv_arenaroot = NULL; - PL_xpvcv_root = NULL; - PL_xpvav_arenaroot = NULL; - PL_xpvav_root = NULL; - PL_xpvhv_arenaroot = NULL; - PL_xpvhv_root = NULL; - PL_xpvmg_arenaroot = NULL; - PL_xpvmg_root = NULL; - PL_xpvlv_arenaroot = NULL; - PL_xpvlv_root = NULL; - PL_xpvbm_arenaroot = NULL; - PL_xpvbm_root = NULL; - PL_he_arenaroot = NULL; - PL_he_root = NULL; - PL_nice_chunk = NULL; - PL_nice_chunk_size = 0; - PL_sv_count = 0; - PL_sv_objcount = 0; - PL_sv_root = Nullsv; - PL_sv_arenaroot = Nullsv; - - PL_debug = proto_perl->Idebug; - - /* create SV map for pointer relocation */ - PL_ptr_table = ptr_table_new(); - - /* initialize these special pointers as early as possible */ - SvANY(&PL_sv_undef) = NULL; - SvREFCNT(&PL_sv_undef) = (~(U32)0)/2; - SvFLAGS(&PL_sv_undef) = SVf_READONLY|SVt_NULL; - ptr_table_store(PL_ptr_table, &proto_perl->Isv_undef, &PL_sv_undef); - -#ifdef PERL_OBJECT - SvUPGRADE(&PL_sv_no, SVt_PVNV); -#else - SvANY(&PL_sv_no) = new_XPVNV(); -#endif - SvREFCNT(&PL_sv_no) = (~(U32)0)/2; - SvFLAGS(&PL_sv_no) = SVp_NOK|SVf_NOK|SVp_POK|SVf_POK|SVf_READONLY|SVt_PVNV; - SvPVX(&PL_sv_no) = SAVEPVN(PL_No, 0); - SvCUR(&PL_sv_no) = 0; - SvLEN(&PL_sv_no) = 1; - SvNVX(&PL_sv_no) = 0; - ptr_table_store(PL_ptr_table, &proto_perl->Isv_no, &PL_sv_no); - -#ifdef PERL_OBJECT - SvUPGRADE(&PL_sv_yes, SVt_PVNV); -#else - SvANY(&PL_sv_yes) = new_XPVNV(); -#endif - SvREFCNT(&PL_sv_yes) = (~(U32)0)/2; - SvFLAGS(&PL_sv_yes) = SVp_NOK|SVf_NOK|SVp_POK|SVf_POK|SVf_READONLY|SVt_PVNV; - SvPVX(&PL_sv_yes) = SAVEPVN(PL_Yes, 1); - SvCUR(&PL_sv_yes) = 1; - SvLEN(&PL_sv_yes) = 2; - SvNVX(&PL_sv_yes) = 1; - ptr_table_store(PL_ptr_table, &proto_perl->Isv_yes, &PL_sv_yes); - - /* create shared string table */ - PL_strtab = newHV(); - HvSHAREKEYS_off(PL_strtab); - hv_ksplit(PL_strtab, 512); - ptr_table_store(PL_ptr_table, proto_perl->Istrtab, PL_strtab); - - PL_compiling = proto_perl->Icompiling; - PL_compiling.cop_stashpv = SAVEPV(PL_compiling.cop_stashpv); - PL_compiling.cop_file = SAVEPV(PL_compiling.cop_file); - ptr_table_store(PL_ptr_table, &proto_perl->Icompiling, &PL_compiling); - if (!specialWARN(PL_compiling.cop_warnings)) - PL_compiling.cop_warnings = sv_dup_inc(PL_compiling.cop_warnings); - PL_curcop = (COP*)any_dup(proto_perl->Tcurcop, proto_perl); - - /* pseudo environmental stuff */ - PL_origargc = proto_perl->Iorigargc; - i = PL_origargc; - New(0, PL_origargv, i+1, char*); - PL_origargv[i] = '\0'; - while (i-- > 0) { - PL_origargv[i] = SAVEPV(proto_perl->Iorigargv[i]); - } - PL_envgv = gv_dup(proto_perl->Ienvgv); - PL_incgv = gv_dup(proto_perl->Iincgv); - PL_hintgv = gv_dup(proto_perl->Ihintgv); - PL_origfilename = SAVEPV(proto_perl->Iorigfilename); - PL_diehook = sv_dup_inc(proto_perl->Idiehook); - PL_warnhook = sv_dup_inc(proto_perl->Iwarnhook); - - /* switches */ - PL_minus_c = proto_perl->Iminus_c; - PL_patchlevel = sv_dup_inc(proto_perl->Ipatchlevel); - PL_localpatches = proto_perl->Ilocalpatches; - PL_splitstr = proto_perl->Isplitstr; - PL_preprocess = proto_perl->Ipreprocess; - PL_minus_n = proto_perl->Iminus_n; - PL_minus_p = proto_perl->Iminus_p; - PL_minus_l = proto_perl->Iminus_l; - PL_minus_a = proto_perl->Iminus_a; - PL_minus_F = proto_perl->Iminus_F; - PL_doswitches = proto_perl->Idoswitches; - PL_dowarn = proto_perl->Idowarn; - PL_doextract = proto_perl->Idoextract; - PL_sawampersand = proto_perl->Isawampersand; - PL_unsafe = proto_perl->Iunsafe; - PL_inplace = SAVEPV(proto_perl->Iinplace); - PL_e_script = sv_dup_inc(proto_perl->Ie_script); - PL_perldb = proto_perl->Iperldb; - PL_perl_destruct_level = proto_perl->Iperl_destruct_level; - - /* magical thingies */ - /* XXX time(&PL_basetime) when asked for? */ - PL_basetime = proto_perl->Ibasetime; - PL_formfeed = sv_dup(proto_perl->Iformfeed); - - PL_maxsysfd = proto_perl->Imaxsysfd; - PL_multiline = proto_perl->Imultiline; - PL_statusvalue = proto_perl->Istatusvalue; -#ifdef VMS - PL_statusvalue_vms = proto_perl->Istatusvalue_vms; -#endif - - /* shortcuts to various I/O objects */ - PL_stdingv = gv_dup(proto_perl->Istdingv); - PL_stderrgv = gv_dup(proto_perl->Istderrgv); - PL_defgv = gv_dup(proto_perl->Idefgv); - PL_argvgv = gv_dup(proto_perl->Iargvgv); - PL_argvoutgv = gv_dup(proto_perl->Iargvoutgv); - PL_argvout_stack = av_dup_inc(proto_perl->Iargvout_stack); - - /* shortcuts to regexp stuff */ - PL_replgv = gv_dup(proto_perl->Ireplgv); - - /* shortcuts to misc objects */ - PL_errgv = gv_dup(proto_perl->Ierrgv); - - /* shortcuts to debugging objects */ - PL_DBgv = gv_dup(proto_perl->IDBgv); - PL_DBline = gv_dup(proto_perl->IDBline); - PL_DBsub = gv_dup(proto_perl->IDBsub); - PL_DBsingle = sv_dup(proto_perl->IDBsingle); - PL_DBtrace = sv_dup(proto_perl->IDBtrace); - PL_DBsignal = sv_dup(proto_perl->IDBsignal); - PL_lineary = av_dup(proto_perl->Ilineary); - PL_dbargs = av_dup(proto_perl->Idbargs); - - /* symbol tables */ - PL_defstash = hv_dup_inc(proto_perl->Tdefstash); - PL_curstash = hv_dup(proto_perl->Tcurstash); - PL_debstash = hv_dup(proto_perl->Idebstash); - PL_globalstash = hv_dup(proto_perl->Iglobalstash); - PL_curstname = sv_dup_inc(proto_perl->Icurstname); - - PL_beginav = av_dup_inc(proto_perl->Ibeginav); - PL_endav = av_dup_inc(proto_perl->Iendav); - PL_checkav = av_dup_inc(proto_perl->Icheckav); - PL_initav = av_dup_inc(proto_perl->Iinitav); - - PL_sub_generation = proto_perl->Isub_generation; - - /* funky return mechanisms */ - PL_forkprocess = proto_perl->Iforkprocess; - - /* subprocess state */ - PL_fdpid = av_dup_inc(proto_perl->Ifdpid); - - /* internal state */ - PL_tainting = proto_perl->Itainting; - PL_maxo = proto_perl->Imaxo; - if (proto_perl->Iop_mask) - PL_op_mask = SAVEPVN(proto_perl->Iop_mask, PL_maxo); - else - PL_op_mask = Nullch; - - /* current interpreter roots */ - PL_main_cv = cv_dup_inc(proto_perl->Imain_cv); - PL_main_root = OpREFCNT_inc(proto_perl->Imain_root); - PL_main_start = proto_perl->Imain_start; - PL_eval_root = proto_perl->Ieval_root; - PL_eval_start = proto_perl->Ieval_start; - - /* runtime control stuff */ - PL_curcopdb = (COP*)any_dup(proto_perl->Icurcopdb, proto_perl); - PL_copline = proto_perl->Icopline; - - PL_filemode = proto_perl->Ifilemode; - PL_lastfd = proto_perl->Ilastfd; - PL_oldname = proto_perl->Ioldname; /* XXX not quite right */ - PL_Argv = NULL; - PL_Cmd = Nullch; - PL_gensym = proto_perl->Igensym; - PL_preambled = proto_perl->Ipreambled; - PL_preambleav = av_dup_inc(proto_perl->Ipreambleav); - PL_laststatval = proto_perl->Ilaststatval; - PL_laststype = proto_perl->Ilaststype; - PL_mess_sv = Nullsv; - - PL_orslen = proto_perl->Iorslen; - PL_ors = SAVEPVN(proto_perl->Iors, PL_orslen); - PL_ofmt = SAVEPV(proto_perl->Iofmt); - - /* interpreter atexit processing */ - PL_exitlistlen = proto_perl->Iexitlistlen; - if (PL_exitlistlen) { - New(0, PL_exitlist, PL_exitlistlen, PerlExitListEntry); - Copy(proto_perl->Iexitlist, PL_exitlist, PL_exitlistlen, PerlExitListEntry); - } - else - PL_exitlist = (PerlExitListEntry*)NULL; - PL_modglobal = hv_dup_inc(proto_perl->Imodglobal); - - PL_profiledata = NULL; - PL_rsfp = fp_dup(proto_perl->Irsfp, '<'); - /* PL_rsfp_filters entries have fake IoDIRP() */ - PL_rsfp_filters = av_dup_inc(proto_perl->Irsfp_filters); - - PL_compcv = cv_dup(proto_perl->Icompcv); - PL_comppad = av_dup(proto_perl->Icomppad); - PL_comppad_name = av_dup(proto_perl->Icomppad_name); - PL_comppad_name_fill = proto_perl->Icomppad_name_fill; - PL_comppad_name_floor = proto_perl->Icomppad_name_floor; - PL_curpad = (SV**)ptr_table_fetch(PL_ptr_table, - proto_perl->Tcurpad); - -#ifdef HAVE_INTERP_INTERN - sys_intern_dup(&proto_perl->Isys_intern, &PL_sys_intern); -#endif - - /* more statics moved here */ - PL_generation = proto_perl->Igeneration; - PL_DBcv = cv_dup(proto_perl->IDBcv); - - PL_in_clean_objs = proto_perl->Iin_clean_objs; - PL_in_clean_all = proto_perl->Iin_clean_all; - - PL_uid = proto_perl->Iuid; - PL_euid = proto_perl->Ieuid; - PL_gid = proto_perl->Igid; - PL_egid = proto_perl->Iegid; - PL_nomemok = proto_perl->Inomemok; - PL_an = proto_perl->Ian; - PL_cop_seqmax = proto_perl->Icop_seqmax; - PL_op_seqmax = proto_perl->Iop_seqmax; - PL_evalseq = proto_perl->Ievalseq; - PL_origenviron = proto_perl->Iorigenviron; /* XXX not quite right */ - PL_origalen = proto_perl->Iorigalen; - PL_pidstatus = newHV(); /* XXX flag for cloning? */ - PL_osname = SAVEPV(proto_perl->Iosname); - PL_sh_path = SAVEPV(proto_perl->Ish_path); - PL_sighandlerp = proto_perl->Isighandlerp; - - - PL_runops = proto_perl->Irunops; - - Copy(proto_perl->Itokenbuf, PL_tokenbuf, 256, char); - -#ifdef CSH - PL_cshlen = proto_perl->Icshlen; - PL_cshname = SAVEPVN(proto_perl->Icshname, PL_cshlen); -#endif - - PL_lex_state = proto_perl->Ilex_state; - PL_lex_defer = proto_perl->Ilex_defer; - PL_lex_expect = proto_perl->Ilex_expect; - PL_lex_formbrack = proto_perl->Ilex_formbrack; - PL_lex_dojoin = proto_perl->Ilex_dojoin; - PL_lex_starts = proto_perl->Ilex_starts; - PL_lex_stuff = sv_dup_inc(proto_perl->Ilex_stuff); - PL_lex_repl = sv_dup_inc(proto_perl->Ilex_repl); - PL_lex_op = proto_perl->Ilex_op; - PL_lex_inpat = proto_perl->Ilex_inpat; - PL_lex_inwhat = proto_perl->Ilex_inwhat; - PL_lex_brackets = proto_perl->Ilex_brackets; - i = (PL_lex_brackets < 120 ? 120 : PL_lex_brackets); - PL_lex_brackstack = SAVEPVN(proto_perl->Ilex_brackstack,i); - PL_lex_casemods = proto_perl->Ilex_casemods; - i = (PL_lex_casemods < 12 ? 12 : PL_lex_casemods); - PL_lex_casestack = SAVEPVN(proto_perl->Ilex_casestack,i); - - Copy(proto_perl->Inextval, PL_nextval, 5, YYSTYPE); - Copy(proto_perl->Inexttype, PL_nexttype, 5, I32); - PL_nexttoke = proto_perl->Inexttoke; - - PL_linestr = sv_dup_inc(proto_perl->Ilinestr); - i = proto_perl->Ibufptr - SvPVX(proto_perl->Ilinestr); - PL_bufptr = SvPVX(PL_linestr) + (i < 0 ? 0 : i); - i = proto_perl->Ioldbufptr - SvPVX(proto_perl->Ilinestr); - PL_oldbufptr = SvPVX(PL_linestr) + (i < 0 ? 0 : i); - i = proto_perl->Ioldoldbufptr - SvPVX(proto_perl->Ilinestr); - PL_oldoldbufptr = SvPVX(PL_linestr) + (i < 0 ? 0 : i); - PL_bufend = SvPVX(PL_linestr) + SvCUR(PL_linestr); - i = proto_perl->Ilinestart - SvPVX(proto_perl->Ilinestr); - PL_linestart = SvPVX(PL_linestr) + (i < 0 ? 0 : i); - PL_pending_ident = proto_perl->Ipending_ident; - PL_sublex_info = proto_perl->Isublex_info; /* XXX not quite right */ - - PL_expect = proto_perl->Iexpect; - - PL_multi_start = proto_perl->Imulti_start; - PL_multi_end = proto_perl->Imulti_end; - PL_multi_open = proto_perl->Imulti_open; - PL_multi_close = proto_perl->Imulti_close; - - PL_error_count = proto_perl->Ierror_count; - PL_subline = proto_perl->Isubline; - PL_subname = sv_dup_inc(proto_perl->Isubname); - - PL_min_intro_pending = proto_perl->Imin_intro_pending; - PL_max_intro_pending = proto_perl->Imax_intro_pending; - PL_padix = proto_perl->Ipadix; - PL_padix_floor = proto_perl->Ipadix_floor; - PL_pad_reset_pending = proto_perl->Ipad_reset_pending; - - i = proto_perl->Ilast_uni - SvPVX(proto_perl->Ilinestr); - PL_last_uni = SvPVX(PL_linestr) + (i < 0 ? 0 : i); - i = proto_perl->Ilast_lop - SvPVX(proto_perl->Ilinestr); - PL_last_lop = SvPVX(PL_linestr) + (i < 0 ? 0 : i); - PL_last_lop_op = proto_perl->Ilast_lop_op; - PL_in_my = proto_perl->Iin_my; - PL_in_my_stash = hv_dup(proto_perl->Iin_my_stash); -#ifdef FCRYPT - PL_cryptseen = proto_perl->Icryptseen; -#endif - - PL_hints = proto_perl->Ihints; - - PL_amagic_generation = proto_perl->Iamagic_generation; - -#ifdef USE_LOCALE_COLLATE - PL_collation_ix = proto_perl->Icollation_ix; - PL_collation_name = SAVEPV(proto_perl->Icollation_name); - PL_collation_standard = proto_perl->Icollation_standard; - PL_collxfrm_base = proto_perl->Icollxfrm_base; - PL_collxfrm_mult = proto_perl->Icollxfrm_mult; -#endif /* USE_LOCALE_COLLATE */ - -#ifdef USE_LOCALE_NUMERIC - PL_numeric_name = SAVEPV(proto_perl->Inumeric_name); - PL_numeric_standard = proto_perl->Inumeric_standard; - PL_numeric_local = proto_perl->Inumeric_local; - PL_numeric_radix_sv = sv_dup_inc(proto_perl->Inumeric_radix_sv); -#endif /* !USE_LOCALE_NUMERIC */ - - /* utf8 character classes */ - PL_utf8_alnum = sv_dup_inc(proto_perl->Iutf8_alnum); - PL_utf8_alnumc = sv_dup_inc(proto_perl->Iutf8_alnumc); - PL_utf8_ascii = sv_dup_inc(proto_perl->Iutf8_ascii); - PL_utf8_alpha = sv_dup_inc(proto_perl->Iutf8_alpha); - PL_utf8_space = sv_dup_inc(proto_perl->Iutf8_space); - PL_utf8_cntrl = sv_dup_inc(proto_perl->Iutf8_cntrl); - PL_utf8_graph = sv_dup_inc(proto_perl->Iutf8_graph); - PL_utf8_digit = sv_dup_inc(proto_perl->Iutf8_digit); - PL_utf8_upper = sv_dup_inc(proto_perl->Iutf8_upper); - PL_utf8_lower = sv_dup_inc(proto_perl->Iutf8_lower); - PL_utf8_print = sv_dup_inc(proto_perl->Iutf8_print); - PL_utf8_punct = sv_dup_inc(proto_perl->Iutf8_punct); - PL_utf8_xdigit = sv_dup_inc(proto_perl->Iutf8_xdigit); - PL_utf8_mark = sv_dup_inc(proto_perl->Iutf8_mark); - PL_utf8_toupper = sv_dup_inc(proto_perl->Iutf8_toupper); - PL_utf8_totitle = sv_dup_inc(proto_perl->Iutf8_totitle); - PL_utf8_tolower = sv_dup_inc(proto_perl->Iutf8_tolower); - - /* swatch cache */ - PL_last_swash_hv = Nullhv; /* reinits on demand */ - PL_last_swash_klen = 0; - PL_last_swash_key[0]= '\0'; - PL_last_swash_tmps = (U8*)NULL; - PL_last_swash_slen = 0; - - /* perly.c globals */ - PL_yydebug = proto_perl->Iyydebug; - PL_yynerrs = proto_perl->Iyynerrs; - PL_yyerrflag = proto_perl->Iyyerrflag; - PL_yychar = proto_perl->Iyychar; - PL_yyval = proto_perl->Iyyval; - PL_yylval = proto_perl->Iyylval; - - PL_glob_index = proto_perl->Iglob_index; - PL_srand_called = proto_perl->Isrand_called; - PL_uudmap['M'] = 0; /* reinits on demand */ - PL_bitcount = Nullch; /* reinits on demand */ - - if (proto_perl->Ipsig_ptr) { - int sig_num[] = { SIG_NUM }; - Newz(0, PL_psig_ptr, sizeof(sig_num)/sizeof(*sig_num), SV*); - Newz(0, PL_psig_name, sizeof(sig_num)/sizeof(*sig_num), SV*); - for (i = 1; PL_sig_name[i]; i++) { - PL_psig_ptr[i] = sv_dup_inc(proto_perl->Ipsig_ptr[i]); - PL_psig_name[i] = sv_dup_inc(proto_perl->Ipsig_name[i]); - } - } - else { - PL_psig_ptr = (SV**)NULL; - PL_psig_name = (SV**)NULL; - } - - /* thrdvar.h stuff */ - - if (flags & CLONEf_COPY_STACKS) { - /* next allocation will be PL_tmps_stack[PL_tmps_ix+1] */ - PL_tmps_ix = proto_perl->Ttmps_ix; - PL_tmps_max = proto_perl->Ttmps_max; - PL_tmps_floor = proto_perl->Ttmps_floor; - Newz(50, PL_tmps_stack, PL_tmps_max, SV*); - i = 0; - while (i <= PL_tmps_ix) { - PL_tmps_stack[i] = sv_dup_inc(proto_perl->Ttmps_stack[i]); - ++i; - } - - /* next PUSHMARK() sets *(PL_markstack_ptr+1) */ - i = proto_perl->Tmarkstack_max - proto_perl->Tmarkstack; - Newz(54, PL_markstack, i, I32); - PL_markstack_max = PL_markstack + (proto_perl->Tmarkstack_max - - proto_perl->Tmarkstack); - PL_markstack_ptr = PL_markstack + (proto_perl->Tmarkstack_ptr - - proto_perl->Tmarkstack); - Copy(proto_perl->Tmarkstack, PL_markstack, - PL_markstack_ptr - PL_markstack + 1, I32); - - /* next push_scope()/ENTER sets PL_scopestack[PL_scopestack_ix] - * NOTE: unlike the others! */ - PL_scopestack_ix = proto_perl->Tscopestack_ix; - PL_scopestack_max = proto_perl->Tscopestack_max; - Newz(54, PL_scopestack, PL_scopestack_max, I32); - Copy(proto_perl->Tscopestack, PL_scopestack, PL_scopestack_ix, I32); - - /* next push_return() sets PL_retstack[PL_retstack_ix] - * NOTE: unlike the others! */ - PL_retstack_ix = proto_perl->Tretstack_ix; - PL_retstack_max = proto_perl->Tretstack_max; - Newz(54, PL_retstack, PL_retstack_max, OP*); - Copy(proto_perl->Tretstack, PL_retstack, PL_retstack_ix, I32); - - /* NOTE: si_dup() looks at PL_markstack */ - PL_curstackinfo = si_dup(proto_perl->Tcurstackinfo); - - /* PL_curstack = PL_curstackinfo->si_stack; */ - PL_curstack = av_dup(proto_perl->Tcurstack); - PL_mainstack = av_dup(proto_perl->Tmainstack); - - /* next PUSHs() etc. set *(PL_stack_sp+1) */ - PL_stack_base = AvARRAY(PL_curstack); - PL_stack_sp = PL_stack_base + (proto_perl->Tstack_sp - - proto_perl->Tstack_base); - PL_stack_max = PL_stack_base + AvMAX(PL_curstack); - - /* next SSPUSHFOO() sets PL_savestack[PL_savestack_ix] - * NOTE: unlike the others! */ - PL_savestack_ix = proto_perl->Tsavestack_ix; - PL_savestack_max = proto_perl->Tsavestack_max; - /*Newz(54, PL_savestack, PL_savestack_max, ANY);*/ - PL_savestack = ss_dup(proto_perl); - } - else { - init_stacks(); - ENTER; /* perl_destruct() wants to LEAVE; */ - } - - PL_start_env = proto_perl->Tstart_env; /* XXXXXX */ - PL_top_env = &PL_start_env; - - PL_op = proto_perl->Top; - - PL_Sv = Nullsv; - PL_Xpv = (XPV*)NULL; - PL_na = proto_perl->Tna; - - PL_statbuf = proto_perl->Tstatbuf; - PL_statcache = proto_perl->Tstatcache; - PL_statgv = gv_dup(proto_perl->Tstatgv); - PL_statname = sv_dup_inc(proto_perl->Tstatname); -#ifdef HAS_TIMES - PL_timesbuf = proto_perl->Ttimesbuf; -#endif - - PL_tainted = proto_perl->Ttainted; - PL_curpm = proto_perl->Tcurpm; /* XXX No PMOP ref count */ - PL_nrs = sv_dup_inc(proto_perl->Tnrs); - PL_rs = sv_dup_inc(proto_perl->Trs); - PL_last_in_gv = gv_dup(proto_perl->Tlast_in_gv); - PL_ofslen = proto_perl->Tofslen; - PL_ofs = SAVEPVN(proto_perl->Tofs, PL_ofslen); - PL_defoutgv = gv_dup_inc(proto_perl->Tdefoutgv); - PL_chopset = proto_perl->Tchopset; /* XXX never deallocated */ - PL_toptarget = sv_dup_inc(proto_perl->Ttoptarget); - PL_bodytarget = sv_dup_inc(proto_perl->Tbodytarget); - PL_formtarget = sv_dup(proto_perl->Tformtarget); - - PL_restartop = proto_perl->Trestartop; - PL_in_eval = proto_perl->Tin_eval; - PL_delaymagic = proto_perl->Tdelaymagic; - PL_dirty = proto_perl->Tdirty; - PL_localizing = proto_perl->Tlocalizing; - -#ifdef PERL_FLEXIBLE_EXCEPTIONS - PL_protect = proto_perl->Tprotect; -#endif - PL_errors = sv_dup_inc(proto_perl->Terrors); - PL_av_fetch_sv = Nullsv; - PL_hv_fetch_sv = Nullsv; - Zero(&PL_hv_fetch_ent_mh, 1, HE); /* XXX */ - PL_modcount = proto_perl->Tmodcount; - PL_lastgotoprobe = Nullop; - PL_dumpindent = proto_perl->Tdumpindent; - - PL_sortcop = (OP*)any_dup(proto_perl->Tsortcop, proto_perl); - PL_sortstash = hv_dup(proto_perl->Tsortstash); - PL_firstgv = gv_dup(proto_perl->Tfirstgv); - PL_secondgv = gv_dup(proto_perl->Tsecondgv); - PL_sortcxix = proto_perl->Tsortcxix; - PL_efloatbuf = Nullch; /* reinits on demand */ - PL_efloatsize = 0; /* reinits on demand */ - - /* regex stuff */ - - PL_screamfirst = NULL; - PL_screamnext = NULL; - PL_maxscream = -1; /* reinits on demand */ - PL_lastscream = Nullsv; - - PL_watchaddr = NULL; - PL_watchok = Nullch; - - PL_regdummy = proto_perl->Tregdummy; - PL_regcomp_parse = Nullch; - PL_regxend = Nullch; - PL_regcode = (regnode*)NULL; - PL_regnaughty = 0; - PL_regsawback = 0; - PL_regprecomp = Nullch; - PL_regnpar = 0; - PL_regsize = 0; - PL_regflags = 0; - PL_regseen = 0; - PL_seen_zerolen = 0; - PL_seen_evals = 0; - PL_regcomp_rx = (regexp*)NULL; - PL_extralen = 0; - PL_colorset = 0; /* reinits PL_colors[] */ - /*PL_colors[6] = {0,0,0,0,0,0};*/ - PL_reg_whilem_seen = 0; - PL_reginput = Nullch; - PL_regbol = Nullch; - PL_regeol = Nullch; - PL_regstartp = (I32*)NULL; - PL_regendp = (I32*)NULL; - PL_reglastparen = (U32*)NULL; - PL_regtill = Nullch; - PL_regprev = '\n'; - PL_reg_start_tmp = (char**)NULL; - PL_reg_start_tmpl = 0; - PL_regdata = (struct reg_data*)NULL; - PL_bostr = Nullch; - PL_reg_flags = 0; - PL_reg_eval_set = 0; - PL_regnarrate = 0; - PL_regprogram = (regnode*)NULL; - PL_regindent = 0; - PL_regcc = (CURCUR*)NULL; - PL_reg_call_cc = (struct re_cc_state*)NULL; - PL_reg_re = (regexp*)NULL; - PL_reg_ganch = Nullch; - PL_reg_sv = Nullsv; - PL_reg_magic = (MAGIC*)NULL; - PL_reg_oldpos = 0; - PL_reg_oldcurpm = (PMOP*)NULL; - PL_reg_curpm = (PMOP*)NULL; - PL_reg_oldsaved = Nullch; - PL_reg_oldsavedlen = 0; - PL_reg_maxiter = 0; - PL_reg_leftiter = 0; - PL_reg_poscache = Nullch; - PL_reg_poscache_size= 0; - - /* RE engine - function pointers */ - PL_regcompp = proto_perl->Tregcompp; - PL_regexecp = proto_perl->Tregexecp; - PL_regint_start = proto_perl->Tregint_start; - PL_regint_string = proto_perl->Tregint_string; - PL_regfree = proto_perl->Tregfree; - - PL_reginterp_cnt = 0; - PL_reg_starttry = 0; - - if (!(flags & CLONEf_KEEP_PTR_TABLE)) { - ptr_table_free(PL_ptr_table); - PL_ptr_table = NULL; - } - -#ifdef PERL_OBJECT - return (PerlInterpreter*)pPerl; -#else - return my_perl; -#endif -} - -#else /* !USE_ITHREADS */ - -#ifdef PERL_OBJECT -#include "XSUB.h" -#endif - -#endif /* USE_ITHREADS */ - -static void -do_report_used(pTHXo_ SV *sv) -{ - if (SvTYPE(sv) != SVTYPEMASK) { - PerlIO_printf(Perl_debug_log, "****\n"); - sv_dump(sv); - } -} - -static void -do_clean_objs(pTHXo_ SV *sv) -{ - SV* rv; - - if (SvROK(sv) && SvOBJECT(rv = SvRV(sv))) { - DEBUG_D((PerlIO_printf(Perl_debug_log, "Cleaning object ref:\n "), sv_dump(sv));) - if (SvWEAKREF(sv)) { - sv_del_backref(sv); - SvWEAKREF_off(sv); - SvRV(sv) = 0; - } else { - SvROK_off(sv); - SvRV(sv) = 0; - SvREFCNT_dec(rv); - } - } - - /* XXX Might want to check arrays, etc. */ -} - -#ifndef DISABLE_DESTRUCTOR_KLUDGE -static void -do_clean_named_objs(pTHXo_ SV *sv) -{ - if (SvTYPE(sv) == SVt_PVGV && GvGP(sv)) { - if ( SvOBJECT(GvSV(sv)) || - (GvAV(sv) && SvOBJECT(GvAV(sv))) || - (GvHV(sv) && SvOBJECT(GvHV(sv))) || - (GvIO(sv) && SvOBJECT(GvIO(sv))) || - (GvCV(sv) && SvOBJECT(GvCV(sv))) ) - { - DEBUG_D((PerlIO_printf(Perl_debug_log, "Cleaning named glob object:\n "), sv_dump(sv));) - SvREFCNT_dec(sv); - } - } -} -#endif - -static void -do_clean_all(pTHXo_ SV *sv) -{ - DEBUG_D((PerlIO_printf(Perl_debug_log, "Cleaning loops: SV at 0x%"UVxf"\n", PTR2UV(sv)) );) - SvFLAGS(sv) |= SVf_BREAK; - SvREFCNT_dec(sv); -} - |