X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=doop.c;h=e527cdee1812613a55db47ca45166ff863c10bb6;hb=4a71ed0cc11f5be9a856b29b19af5c91a1bd76cb;hp=5042e3ca1a431122efb530f78d53e10e4a01c408;hpb=8ac853655d9b744749adcb9687c13d99cdd6e9fb;p=p5sagit%2Fp5-mst-13.2.git diff --git a/doop.c b/doop.c index 5042e3c..e527cde 100644 --- a/doop.c +++ b/doop.c @@ -29,9 +29,10 @@ do_trans(SV *sv, OP *arg) register I32 ch; register I32 matches = 0; register I32 squash = op->op_private & OPpTRANS_SQUASH; + register U8 *p; STRLEN len; - if (SvREADONLY(sv)) + if (SvREADONLY(sv) && !(op->op_private & OPpTRANS_COUNTONLY)) croak(no_modify); tbl = (short*)cPVOP->op_pv; s = (U8*)SvPV(sv, len); @@ -52,17 +53,27 @@ do_trans(SV *sv, OP *arg) } s++; } + SvSETMAGIC(sv); + } + else if (op->op_private & OPpTRANS_COUNTONLY) { + while (s < send) { + if (tbl[*s] >= 0) + matches++; + s++; + } } else { d = s; + p = send; while (s < send) { if ((ch = tbl[*s]) >= 0) { *d = ch; - if (matches++ && squash) { - if (d[-1] == *d) + matches++; + if (squash) { + if (p == d - 1 && *p == *d) matches--; else - d++; + p = d++; } else d++; @@ -74,8 +85,8 @@ do_trans(SV *sv, OP *arg) matches += send - d; /* account for disappeared chars */ *d = '\0'; SvCUR_set(sv, d - (U8*)SvPVX(sv)); + SvSETMAGIC(sv); } - SvSETMAGIC(sv); return matches; } @@ -95,7 +106,7 @@ do_join(register SV *sv, SV *del, register SV **mark, register SV **sp) sv_upgrade(sv, SVt_PV); if (SvLEN(sv) < len + items) { /* current length is way too short */ while (items-- > 0) { - if (*mark) { + if (*mark && !SvGMAGICAL(*mark) && SvOK(*mark)) { SvPV(*mark, tmplen); len += tmplen; } @@ -244,6 +255,7 @@ do_chop(register SV *astr, register SV *sv) I32 do_chomp(register SV *sv) { + dTHR; register I32 count; STRLEN len; char *s; @@ -317,6 +329,7 @@ do_chomp(register SV *sv) void do_vop(I32 optype, SV *sv, SV *left, SV *right) { + dTHR; /* just for taint */ #ifdef LIBERAL register long *dl; register long *ll; @@ -430,7 +443,7 @@ do_vop(I32 optype, SV *sv, SV *left, SV *right) OP * do_kv(ARGSproto) { - dSP; + djSP; HV *hv = (HV*)POPs; register HE *entry; SV *tmpstr; @@ -461,7 +474,7 @@ do_kv(ARGSproto) RETURN; if (gimme == G_SCALAR) { - I32 i; + IV i; dTARGET; if (op->op_flags & OPf_MOD) { /* lvalue */ @@ -470,7 +483,11 @@ do_kv(ARGSproto) sv_magic(TARG, Nullsv, 'k', Nullch, 0); } LvTYPE(TARG) = 'k'; - LvTARG(TARG) = (SV*)hv; + if (LvTARG(TARG) != (SV*)hv) { + if (LvTARG(TARG)) + SvREFCNT_dec(LvTARG(TARG)); + LvTARG(TARG) = SvREFCNT_inc(hv); + } PUSHs(TARG); RETURN; } @@ -489,7 +506,7 @@ do_kv(ARGSproto) } /* Guess how much room we need. hv_max may be a few too many. Oh well. */ - EXTEND(sp, HvMAX(hv) * (dokeys + dovalues)); + EXTEND(SP, HvMAX(hv) * (dokeys + dovalues)); PUTBACK; /* hv_iternext and hv_iterval might clobber stack_sp */ while (entry = realhv ? hv_iternext(hv) : avhv_iternext((AV*)hv)) { @@ -512,3 +529,4 @@ do_kv(ARGSproto) } return NORMAL; } +