XEop |bool |try_amagic_bin |int method|int flags
XEop |bool |try_amagic_un |int method|int flags
Ap |SV* |amagic_call |NN SV* left|NN SV* right|int method|int dir
+Ap |SV * |amagic_deref_call|NN SV *ref|int method
Ap |int |Gv_AMupdate |NN HV* stash|bool destructing
ApR |CV* |gv_handler |NULLOK HV* stash|I32 id
Apd |OP* |op_append_elem |I32 optype|NULLOK OP* first|NULLOK OP* last
#define Gv_AMupdate(a,b) Perl_Gv_AMupdate(aTHX_ a,b)
#define amagic_call(a,b,c,d) Perl_amagic_call(aTHX_ a,b,c,d)
+#define amagic_deref_call(a,b) Perl_amagic_deref_call(aTHX_ a,b)
#define apply_attrs_string(a,b,c,d) Perl_apply_attrs_string(aTHX_ a,b,c,d)
#define atfork_lock Perl_atfork_lock
#define atfork_unlock Perl_atfork_unlock
MODULE = XS::APItest:Overload PACKAGE = XS::APItest::Overload
SV *
-tryAMAGICunDEREF_var(sv, what)
+amagic_deref_call(sv, what)
SV *sv
int what
PPCODE:
- {
- SV **sp = &sv;
- tryAMAGICunDEREF_var(what);
- }
/* The reference is owned by something else. */
- PUSHs(sv);
+ PUSHs(amagic_deref_call(sv, what));
MODULE = XS::APItest PACKAGE = XS::APItest::XSUB
foreach (@non_ref, @ref,
) {
my ($desc, $input) = @$_;
- my $got = tryAMAGICunDEREF_var($input, $enum);
+ my $got = amagic_deref_call($input, $enum);
is($got, $input, "Expect no change for to_$type $desc");
}
foreach (@non_ref) {
my ($desc, $sucker) = @$_;
my $input = bless [$sucker], 'Chain';
- is(eval {tryAMAGICunDEREF_var($input, $enum)}, undef,
+ is(eval {amagic_deref_call($input, $enum)}, undef,
"Chain to $desc for to_$type");
like($@, qr/Overloaded dereference did not return a reference/,
'expected error');
) {
my ($desc, $sucker) = @$_;
my $input = bless [$sucker], 'Chain';
- my $got = tryAMAGICunDEREF_var($input, $enum);
+ my $got = amagic_deref_call($input, $enum);
is($got, $sucker, "Chain to $desc for to_$type");
$input = bless [bless [$sucker], 'Chain'], 'Chain';
- my $got = tryAMAGICunDEREF_var($input, $enum);
+ my $got = amagic_deref_call($input, $enum);
is($got, $sucker, "Chain to chain to $desc for to_$type");
}
}
Perl_Gv_AMupdate
Perl_PerlIO_context_layers
Perl_amagic_call
+Perl_amagic_deref_call
Perl_apply_attrs_string
Perl_atfork_lock
Perl_atfork_unlock
return FALSE;
}
+SV *
+Perl_amagic_deref_call(pTHX_ SV *ref, int method) {
+ SV *tmpsv = NULL;
+
+ PERL_ARGS_ASSERT_AMAGIC_DEREF_CALL;
+
+ while (SvAMAGIC(ref) &&
+ (tmpsv = amagic_call(ref, &PL_sv_undef, method,
+ AMGf_noright | AMGf_unary))) {
+ if (!SvROK(tmpsv))
+ Perl_croak(aTHX_ "Overloaded dereference did not return a reference");
+ if (tmpsv == ref || SvRV(tmpsv) == SvRV(ref)) {
+ /* Bail out if it returns us the same reference. */
+ return tmpsv;
+ }
+ ref = tmpsv;
+ }
+ return tmpsv ? tmpsv : ref;
+}
SV*
Perl_amagic_call(pTHX_ SV *left, SV *right, int method, int flags)
#define tryAMAGICunDEREF_var(meth_enum) \
STMT_START { \
- SV *tmpsv; \
- SV *arg = *sp; \
- while (SvAMAGIC(arg) && \
- (tmpsv = amagic_call(arg, &PL_sv_undef, meth_enum, \
- AMGf_noright | AMGf_unary))) { \
- SPAGAIN; \
- sv = tmpsv; \
- if (!SvROK(tmpsv)) \
- Perl_croak(aTHX_ "Overloaded dereference did not return a reference"); \
- if (tmpsv == arg || SvRV(tmpsv) == SvRV(arg)) { \
- /* Bail out if it returns us the same reference. */ \
- break; \
- } \
- arg = tmpsv; \
- } \
+ sv = amagic_deref_call(aTHX_ *sp, meth_enum); \
+ SPAGAIN; \
} STMT_END
#define tryAMAGICunDEREF(meth) tryAMAGICunDEREF_var(CAT2(meth,_amg))
#define PERL_ARGS_ASSERT_AMAGIC_CALL \
assert(left); assert(right)
+PERL_CALLCONV SV * Perl_amagic_deref_call(pTHX_ SV *ref, int method)
+ __attribute__nonnull__(pTHX_1);
+#define PERL_ARGS_ASSERT_AMAGIC_DEREF_CALL \
+ assert(ref)
+
PERL_CALLCONV I32 Perl_apply(pTHX_ I32 type, SV** mark, SV** sp)
__attribute__nonnull__(pTHX_2)
__attribute__nonnull__(pTHX_3);