summaryrefslogtreecommitdiff
path: root/pp.c
diff options
context:
space:
mode:
authorFather Chrysostomos <sprout@cpan.org>2012-06-29 17:34:38 -0700
committerFather Chrysostomos <sprout@cpan.org>2012-06-29 22:20:13 -0700
commit1c2b3fd6f10f07e101845ead8e14f613c1b487de (patch)
treebdbb14755292143fa14bacd4d2d03f412509b9a9 /pp.c
parentf87fa3355a3a1f41c9bc2160d98d7e7e16bdd9ea (diff)
downloadperl-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.c42
1 files changed, 26 insertions, 16 deletions
diff --git a/pp.c b/pp.c
index 1742baa2cb..0324c19aaa 100644
--- a/pp.c
+++ b/pp.c
@@ -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);