X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=pp_sort.c;h=7588625aa794b16ec9816b1706674c364892746d;hb=e670e57a01f4348af67815ccc0b2b168b078d7bd;hp=3d9b0d9c44c8bedd65fa831fe4eab7e81cfe043e;hpb=a882b6a267ba65cf612aaa239eac8f9b5fb407c4;p=p5sagit%2Fp5-mst-13.2.git diff --git a/pp_sort.c b/pp_sort.c index 3d9b0d9..7588625 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, by Larry Wall and others + * 2000, 2001, 2002, 2003, 2004, 2005, 2006, 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. @@ -36,13 +36,15 @@ #define sv_cmp_static Perl_sv_cmp #define sv_cmp_locale_static Perl_sv_cmp_locale -#define dSORTHINTS SV *hintsv = GvSV(gv_fetchpv("sort::hints", GV_ADDMULTI, SVt_IV)) -#define SORTHINTS (SvIOK(hintsv) ? ((I32)SvIV(hintsv)) : 0) - #ifndef SMALLSORT #define SMALLSORT (200) #endif +/* Flags for qsortsv and mergesortsv */ +#define SORTf_DESC 1 +#define SORTf_STABLE 2 +#define SORTf_QSORT 4 + /* * The mergesort implementation is by Peter M. Mcilroy . * @@ -339,12 +341,14 @@ typedef struct { static I32 cmp_desc(pTHX_ gptr a, gptr b) { + dVAR; return -PL_sort_RealCmp(aTHX_ a, b); } STATIC void S_mergesortsv(pTHX_ gptr *base, size_t nmemb, SVCOMPARE_t cmp, U32 flags) { + dVAR; IV i, run, offset; I32 sense, level; register gptr *f1, *f2, *t, *b, *p; @@ -1312,6 +1316,7 @@ S_qsortsvu(pTHX_ SV ** array, size_t num_elts, SVCOMPARE_t compare) static I32 cmpindir(pTHX_ gptr a, gptr b) { + dVAR; gptr * const ap = (gptr *)a; gptr * const bp = (gptr *)b; const I32 sense = PL_sort_RealCmp(aTHX_ *ap, *bp); @@ -1324,6 +1329,7 @@ cmpindir(pTHX_ gptr a, gptr b) static I32 cmpindir_desc(pTHX_ gptr a, gptr b) { + dVAR; gptr * const ap = (gptr *)a; gptr * const bp = (gptr *)b; const I32 sense = PL_sort_RealCmp(aTHX_ *ap, *bp); @@ -1339,10 +1345,8 @@ cmpindir_desc(pTHX_ gptr a, gptr b) STATIC void S_qsortsv(pTHX_ gptr *list1, size_t nmemb, SVCOMPARE_t cmp, U32 flags) { - - dSORTHINTS; - - if (SORTHINTS & HINT_SORT_STABLE) { + dVAR; + if ((flags & SORTf_STABLE) != 0) { register gptr **pp, *q; register size_t n, j, i; gptr *small[SMALLSORT], **indir, tmp; @@ -1361,7 +1365,7 @@ S_qsortsv(pTHX_ gptr *list1, size_t nmemb, SVCOMPARE_t cmp, U32 flags) /* sort, with indirection */ S_qsortsvu(aTHX_ (gptr *)indir, nmemb, - flags ? cmpindir_desc : cmpindir); + ((flags & SORTf_DESC) != 0 ? cmpindir_desc : cmpindir)); pp = indir; q = list1; @@ -1404,7 +1408,7 @@ S_qsortsv(pTHX_ gptr *list1, size_t nmemb, SVCOMPARE_t cmp, U32 flags) if (indir != small) { Safefree(indir); } /* restore prevailing comparison routine */ PL_sort_RealCmp = savecmp; - } else if (flags) { + } else if ((flags & SORTf_DESC) != 0) { SVCOMPARE_t savecmp = PL_sort_RealCmp; /* Save current comparison routine, if any */ PL_sort_RealCmp = cmp; /* Put comparison routine where cmp_desc can find it */ cmp = cmp_desc; @@ -1425,7 +1429,8 @@ Sort an array. Here is an example: sortsv(AvARRAY(av), av_len(av)+1, Perl_sv_cmp_locale); -See lib/sort.pm for details about controlling the sorting algorithm. +Currently this always uses mergesort. See sortsv_flags for a more +flexible routine. =cut */ @@ -1433,38 +1438,23 @@ See lib/sort.pm for details about controlling the sorting algorithm. void Perl_sortsv(pTHX_ SV **array, size_t nmemb, SVCOMPARE_t cmp) { - void (*sortsvp)(pTHX_ SV **array, size_t nmemb, SVCOMPARE_t cmp, U32 flags) - = S_mergesortsv; - dSORTHINTS; - const I32 hints = SORTHINTS; - if (hints & HINT_SORT_QUICKSORT) { - sortsvp = S_qsortsv; - } - else { - /* The default as of 5.8.0 is mergesort */ - sortsvp = S_mergesortsv; - } - - sortsvp(aTHX_ array, nmemb, cmp, 0); + sortsv_flags(array, nmemb, cmp, 0); } +/* +=for apidoc sortsv_flags -static void -S_sortsv_desc(pTHX_ SV **array, size_t nmemb, SVCOMPARE_t cmp) +Sort an array, with various options. + +=cut +*/ +void +Perl_sortsv_flags(pTHX_ SV **array, size_t nmemb, SVCOMPARE_t cmp, U32 flags) { void (*sortsvp)(pTHX_ SV **array, size_t nmemb, SVCOMPARE_t cmp, U32 flags) - = S_mergesortsv; - dSORTHINTS; - const I32 hints = SORTHINTS; - if (hints & HINT_SORT_QUICKSORT) { - sortsvp = S_qsortsv; - } - else { - /* The default as of 5.8.0 is mergesort */ - sortsvp = S_mergesortsv; - } + = ((flags & SORTf_QSORT) != 0 ? S_qsortsv : S_mergesortsv); - sortsvp(aTHX_ array, nmemb, cmp, 1); + sortsvp(aTHX_ array, nmemb, cmp, flags); } #define SvNSIOK(sv) ((SvFLAGS(sv) & SVf_NOK) || ((SvFLAGS(sv) & (SVf_IOK|SVf_IVisUV)) == SVf_IOK)) @@ -1476,10 +1466,10 @@ PP(pp_sort) dVAR; dSP; dMARK; dORIGMARK; register SV **p1 = ORIGMARK+1, **p2; register I32 max, i; - AV* av = Nullav; + AV* av = NULL; HV *stash; GV *gv; - CV *cv = 0; + CV *cv = NULL; I32 gimme = GIMME; OP* const nextop = PL_op->op_next; I32 overloading = 0; @@ -1488,10 +1478,18 @@ PP(pp_sort) I32 sorting_av = 0; const U8 priv = PL_op->op_private; const U8 flags = PL_op->op_flags; - void (*sortsvp)(pTHX_ SV **array, size_t nmemb, SVCOMPARE_t cmp) - = Perl_sortsv; + U32 sort_flags = 0; + void (*sortsvp)(pTHX_ SV **array, size_t nmemb, SVCOMPARE_t cmp, U32 flags) + = Perl_sortsv_flags; I32 all_SIVs = 1; + if ((priv & OPpSORT_DESCEND) != 0) + sort_flags |= SORTf_DESC; + if ((priv & OPpSORT_QSORT) != 0) + sort_flags |= SORTf_QSORT; + if ((priv & OPpSORT_STABLE) != 0) + sort_flags |= SORTf_STABLE; + if (gimme != G_ARRAY) { SP = MARK; EXTEND(SP,1); @@ -1572,10 +1570,6 @@ PP(pp_sort) max = SP - MARK; } - if (priv & OPpSORT_DESCEND) { - sortsvp = S_sortsv_desc; - } - /* shuffle stack down, removing optional initial cv (p1!=p2), plus * any nulls; also stringify or converting to integer or number as * required any args */ @@ -1675,7 +1669,8 @@ PP(pp_sort) start = p1 - max; sortsvp(aTHX_ start, max, - is_xsub ? S_sortcv_xsub : hasargs ? S_sortcv_stacked : S_sortcv); + (is_xsub ? S_sortcv_xsub : hasargs ? S_sortcv_stacked : S_sortcv), + sort_flags); if (!(flags & OPf_SPECIAL)) { LEAVESUB(cv); @@ -1686,7 +1681,6 @@ PP(pp_sort) PL_stack_sp = newsp; POPSTACK; CATCH_SET(oldcatch); - FREETMPS; } else { MEXTEND(SP, 20); /* Can't afford stack realloc on signal. */ @@ -1700,9 +1694,10 @@ PP(pp_sort) ? ( overloading ? S_amagic_cmp_locale : sv_cmp_locale_static) - : ( overloading ? S_amagic_cmp : sv_cmp_static))); + : ( overloading ? S_amagic_cmp : sv_cmp_static)), + sort_flags); } - if (priv & OPpSORT_REVERSE) { + if ((priv & OPpSORT_REVERSE) != 0) { SV **q = start+max-1; while (start < q) { SV * const tmp = *start; @@ -1852,6 +1847,7 @@ S_sv_i_ncmp(pTHX_ SV *a, SV *b) static I32 S_amagic_ncmp(pTHX_ register SV *a, register SV *b) { + dVAR; SV * const tmpsv = tryCALL_AMAGICbin(a,b,ncmp); if (tmpsv) { if (SvIOK(tmpsv)) { @@ -1873,6 +1869,7 @@ S_amagic_ncmp(pTHX_ register SV *a, register SV *b) static I32 S_amagic_i_ncmp(pTHX_ register SV *a, register SV *b) { + dVAR; SV * const tmpsv = tryCALL_AMAGICbin(a,b,ncmp); if (tmpsv) { if (SvIOK(tmpsv)) { @@ -1894,6 +1891,7 @@ S_amagic_i_ncmp(pTHX_ register SV *a, register SV *b) static I32 S_amagic_cmp(pTHX_ register SV *str1, register SV *str2) { + dVAR; SV * const tmpsv = tryCALL_AMAGICbin(str1,str2,scmp); if (tmpsv) { if (SvIOK(tmpsv)) { @@ -1915,6 +1913,7 @@ S_amagic_cmp(pTHX_ register SV *str1, register SV *str2) static I32 S_amagic_cmp_locale(pTHX_ register SV *str1, register SV *str2) { + dVAR; SV * const tmpsv = tryCALL_AMAGICbin(str1,str2,scmp); if (tmpsv) { if (SvIOK(tmpsv)) {