diff options
author | Father Chrysostomos <sprout@cpan.org> | 2012-06-29 17:34:38 -0700 |
---|---|---|
committer | Father Chrysostomos <sprout@cpan.org> | 2012-06-29 22:20:13 -0700 |
commit | 1c2b3fd6f10f07e101845ead8e14f613c1b487de (patch) | |
tree | bdbb14755292143fa14bacd4d2d03f412509b9a9 /pp.c | |
parent | f87fa3355a3a1f41c9bc2160d98d7e7e16bdd9ea (diff) | |
download | perl-1c2b3fd6f10f07e101845ead8e14f613c1b487de.tar.gz |
[perl #113012] String negation under ‘use integer’
This makes the negation operator under the integer pragma (i_int) use
the same logic for determining whether to do string negation as the
regular negation operator.
Before, this did not happen at all under the integer pragma, except
for barewords, resulting in strange inconsistencies:
$ perl -le 'use integer; print -foo'
-foo
$ perl -le 'use integer; print -"foo"'
0
The code for string negation is now in a static routine in pp.c and is
used by both types of negation.
Diffstat (limited to 'pp.c')
-rw-r--r-- | pp.c | 42 |
1 files changed, 26 insertions, 16 deletions
@@ -2149,10 +2149,34 @@ PP(pp_bit_or) } } +PERL_STATIC_INLINE bool +S_negate_string(pTHX) +{ + dTARGET; dSP; + STRLEN len; + const char *s; + SV * const sv = TOPs; + if (!SvPOKp(sv) || SvNIOK(sv) || (!SvPOK(sv) && SvNIOKp(sv))) + return FALSE; + s = SvPV_nomg_const(sv, len); + if (isIDFIRST(*s)) { + sv_setpvs(TARG, "-"); + sv_catsv(TARG, sv); + } + else if (*s == '+' || (*s == '-' && !looks_like_number(sv))) { + sv_setsv_nomg(TARG, sv); + *SvPV_force_nomg(TARG, len) = *s == '-' ? '+' : '-'; + } + else return FALSE; + SETTARG; PUTBACK; + return TRUE; +} + PP(pp_negate) { dVAR; dSP; dTARGET; tryAMAGICun_MG(neg_amg, AMGf_numeric); + if (S_negate_string(aTHX)) return NORMAL; { SV * const sv = TOPs; @@ -2183,23 +2207,8 @@ PP(pp_negate) } if (SvNIOKp(sv) && (SvNIOK(sv) || !SvPOK(sv))) SETn(-SvNV_nomg(sv)); - else if (SvPOKp(sv)) { - STRLEN len; - const char * const s = SvPV_nomg_const(sv, len); - if (isIDFIRST(*s)) { - sv_setpvs(TARG, "-"); - sv_catsv(TARG, sv); - } - else if (*s == '+' || (*s == '-' && !looks_like_number(sv))) { - sv_setsv_nomg(TARG, sv); - *SvPV_force_nomg(TARG, len) = *s == '-' ? '+' : '-'; - } - else if (SvIV_please_nomg(sv)) + else if (SvPOKp(sv) && SvIV_please_nomg(sv)) goto oops_its_an_int; - else - sv_setnv(TARG, -SvNV_nomg(sv)); - SETTARG; - } else SETn(-SvNV_nomg(sv)); } @@ -2550,6 +2559,7 @@ PP(pp_i_negate) { dVAR; dSP; dTARGET; tryAMAGICun_MG(neg_amg, 0); + if (S_negate_string(aTHX)) return NORMAL; { SV * const sv = TOPs; IV const i = SvIV_nomg(sv); |