X-Git-Url: https://perl5.git.perl.org/perl5.git/blobdiff_plain/31e9e0a31e04057108f257ef918a257afbb2e038..d8b64acd91ca01174385604e24833694829f6e8b:/pp_sort.c diff --git a/pp_sort.c b/pp_sort.c index 9fe0dad..ed9c809 100644 --- a/pp_sort.c +++ b/pp_sort.c @@ -1,7 +1,7 @@ /* pp_sort.c * - * Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, - * 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 by Larry Wall and others + * Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, + * 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 by Larry Wall and others * * You may distribute under the terms of either the GNU General Public * License or the Artistic License, as specified in the README file. @@ -9,8 +9,10 @@ */ /* - * ...they shuffled back towards the rear of the line. 'No, not at the - * rear!' the slave-driver shouted. 'Three files up. And stay there... + * ...they shuffled back towards the rear of the line. 'No, not at the + * rear!' the slave-driver shouted. 'Three files up. And stay there... + * + * [p.931 of _The Lord of the Rings_, VI/ii: "The Land of Shadow"] */ /* This file contains pp ("push/pop") functions that @@ -204,7 +206,7 @@ dynprep(pTHX_ gptr *list1, gptr *list2, size_t nmemb, const SVCOMPARE_t cmp) if (r >= t) p = r = t; /* too short to care about */ else { while (((cmp(aTHX_ *(p-1), *p) > 0) == sense) && - ((p -= 2) > q)); + ((p -= 2) > q)) {} if (p <= q) { /* b through r is a (long) run. ** Extend it as far as possible. @@ -1289,7 +1291,7 @@ S_qsortsvu(pTHX_ SV ** array, size_t num_elts, SVCOMPARE_t compare) * by the original comparison routine on the elements pointed to. * Because we don't move the elements of list1 around through * this phase, we can break ties on elements that compare equal - * using their address in the list1 array, ensuring stabilty. + * using their address in the list1 array, ensuring stability. * This leaves us with something looking like * * indir list1 @@ -1516,7 +1518,7 @@ PP(pp_sort) else { cv = sv_2cv(*++MARK, &stash, &gv, 0); if (cv && SvPOK(cv)) { - const char * const proto = SvPV_nolen_const((SV*)cv); + const char * const proto = SvPV_nolen_const(MUTABLE_SV(cv)); if (proto && strEQ(proto, "$$")) { hasargs = TRUE; } @@ -1553,19 +1555,20 @@ PP(pp_sort) if (priv & OPpSORT_INPLACE) { assert( MARK+1 == SP && *SP && SvTYPE(*SP) == SVt_PVAV); (void)POPMARK; /* remove mark associated with ex-OP_AASSIGN */ - av = (AV*)(*SP); + av = MUTABLE_AV((*SP)); max = AvFILL(av) + 1; if (SvMAGICAL(av)) { MEXTEND(SP, max); - p2 = SP; for (i=0; i < max; i++) { SV **svp = av_fetch(av, i, FALSE); *SP++ = (svp) ? *svp : NULL; } + SP--; + p1 = p2 = SP - (max-1); } else { if (SvREADONLY(av)) - Perl_croak(aTHX_ PL_no_modify); + Perl_croak_no_modify(aTHX); else SvREADONLY_on(av); p1 = p2 = AvARRAY(av); @@ -1586,33 +1589,23 @@ PP(pp_sort) if (!PL_sortcop) { if (priv & OPpSORT_NUMERIC) { if (priv & OPpSORT_INTEGER) { - if (!SvIOK(*p1)) { - if (SvAMAGIC(*p1)) - overloading = 1; - else - (void)sv_2iv(*p1); - } + if (!SvIOK(*p1)) + (void)sv_2iv_flags(*p1, SV_GMAGIC|SV_SKIP_OVERLOAD); } else { - if (!SvNSIOK(*p1)) { - if (SvAMAGIC(*p1)) - overloading = 1; - else - (void)sv_2nv(*p1); - } + if (!SvNSIOK(*p1)) + (void)sv_2nv_flags(*p1, SV_GMAGIC|SV_SKIP_OVERLOAD); if (all_SIVs && !SvSIOK(*p1)) all_SIVs = 0; } } else { - if (!SvPOK(*p1)) { - if (SvAMAGIC(*p1)) - overloading = 1; - else - (void)sv_2pv_flags(*p1, 0, - SV_GMAGIC|SV_CONST_RETURN); - } + if (!SvPOK(*p1)) + (void)sv_2pv_flags(*p1, 0, + SV_GMAGIC|SV_CONST_RETURN|SV_SKIP_OVERLOAD); } + if (SvAMAGIC(*p1)) + overloading = 1; } p1++; } @@ -1649,6 +1642,11 @@ PP(pp_sort) if (!(flags & OPf_SPECIAL)) { cx->cx_type = CXt_SUB; cx->blk_gimme = G_SCALAR; + /* If our comparison routine is already active (CvDEPTH is + * is not 0), then PUSHSUB does not increase the refcount, + * so we have to do it ourselves, because the LEAVESUB fur- + * ther down lowers it. */ + if (CvDEPTH(cv)) SvREFCNT_inc_simple_void_NN(cv); PUSHSUB(cx); if (!is_xsub) { AV* const padlist = CvPADLIST(cv); @@ -1662,10 +1660,10 @@ PP(pp_sort) if (hasargs) { /* This is mostly copied from pp_entersub */ - AV * const av = (AV*)PAD_SVl(0); + AV * const av = MUTABLE_AV(PAD_SVl(0)); cx->blk_sub.savearray = GvAV(PL_defgv); - GvAV(PL_defgv) = (AV*)SvREFCNT_inc_simple(av); + GvAV(PL_defgv) = MUTABLE_AV(SvREFCNT_inc_simple(av)); CX_CURPAD_SAVE(cx->blk_sub); cx->blk_sub.argarray = av; } @@ -1680,9 +1678,9 @@ PP(pp_sort) sort_flags); if (!(flags & OPf_SPECIAL)) { - LEAVESUB(cv); - if (!is_xsub) - CvDEPTH(cv)--; + SV *sv; + POPSUB(cx, sv); + LEAVESUB(sv); } POPBLOCK(cx,PL_curpm); PL_stack_sp = newsp; @@ -1717,7 +1715,7 @@ PP(pp_sort) SvREADONLY_off(av); else if (av && !sorting_av) { /* simulate pp_aassign of tied AV */ - SV** const base = ORIGMARK+1; + SV** const base = MARK+1; for (i=0; i < max; i++) { base[i] = newSVsv(base[i]); } @@ -1754,8 +1752,6 @@ S_sortcv(pTHX_ SV *const a, SV *const b) CALLRUNOPS(aTHX); if (PL_stack_sp != PL_stack_base + 1) Perl_croak(aTHX_ "Sort subroutine didn't return single value"); - if (!SvNIOKp(*PL_stack_sp)) - Perl_croak(aTHX_ "Sort subroutine didn't return a numeric value"); result = SvIV(*PL_stack_sp); while (PL_scopestack_ix > oldscopeix) { LEAVE; @@ -1775,8 +1771,13 @@ S_sortcv_stacked(pTHX_ SV *const a, SV *const b) PERL_ARGS_ASSERT_SORTCV_STACKED; + if (AvREAL(av)) { + av_clear(av); + AvREAL_off(av); + AvREIFY_on(av); + } if (AvMAX(av) < 1) { - SV** ary = AvALLOC(av); + SV **ary = AvALLOC(av); if (AvARRAY(av) != ary) { AvMAX(av) += AvARRAY(av) - AvALLOC(av); AvARRAY(av) = ary; @@ -1785,6 +1786,7 @@ S_sortcv_stacked(pTHX_ SV *const a, SV *const b) AvMAX(av) = 1; Renew(ary,2,SV*); AvARRAY(av) = ary; + AvALLOC(av) = ary; } } AvFILLp(av) = 1; @@ -1796,8 +1798,6 @@ S_sortcv_stacked(pTHX_ SV *const a, SV *const b) CALLRUNOPS(aTHX); if (PL_stack_sp != PL_stack_base + 1) Perl_croak(aTHX_ "Sort subroutine didn't return single value"); - if (!SvNIOKp(*PL_stack_sp)) - Perl_croak(aTHX_ "Sort subroutine didn't return a numeric value"); result = SvIV(*PL_stack_sp); while (PL_scopestack_ix > oldscopeix) { LEAVE; @@ -1812,7 +1812,7 @@ S_sortcv_xsub(pTHX_ SV *const a, SV *const b) dVAR; dSP; const I32 oldsaveix = PL_savestack_ix; const I32 oldscopeix = PL_scopestack_ix; - CV * const cv=(CV*)PL_sortcop; + CV * const cv=MUTABLE_CV(PL_sortcop); I32 result; PERL_ARGS_ASSERT_SORTCV_XSUB; @@ -1826,8 +1826,6 @@ S_sortcv_xsub(pTHX_ SV *const a, SV *const b) (void)(*CvXSUB(cv))(aTHX_ cv); if (PL_stack_sp != PL_stack_base + 1) Perl_croak(aTHX_ "Sort subroutine didn't return single value"); - if (!SvNIOKp(*PL_stack_sp)) - Perl_croak(aTHX_ "Sort subroutine didn't return a numeric value"); result = SvIV(*PL_stack_sp); while (PL_scopestack_ix > oldscopeix) { LEAVE;