- sp--; /* get TARGET from below PL_stack_sp */ \
- { \
- dTARGETSTACKED; \
- dSP; \
- SV *tmpsv; \
- SV *arg= sp[shift]; \
- if (SvAMAGIC(arg) && \
- (tmpsv = amagic_call(arg, &PL_sv_undef, CAT2(meth,_amg), \
- AMGf_noright | AMGf_unary))) { \
- SPAGAIN; \
- sp += shift; \
- sv_setsv(TARG, tmpsv); \
- SETTARG; \
- RETURN; \
+ SV *tmpsv; \
+ SV *arg= *sp; \
+ int gimme = GIMME_V; \
+ if (UNLIKELY(SvAMAGIC(arg) && \
+ (tmpsv = amagic_call(arg, &PL_sv_undef, meth, \
+ AMGf_want_list | AMGf_noright \
+ |AMGf_unary)))) \
+ { \
+ SPAGAIN; \
+ if (gimme == G_VOID) { \
+ (void)POPs; /* XXX ??? */ \
+ } \
+ else if (gimme == G_ARRAY) { \
+ SSize_t i; \
+ SSize_t len; \
+ assert(SvTYPE(tmpsv) == SVt_PVAV); \
+ len = av_tindex((AV *)tmpsv) + 1; \
+ (void)POPs; /* get rid of the arg */ \
+ EXTEND(sp, len); \
+ for (i = 0; i < len; ++i) \
+ PUSHs(av_shift((AV *)tmpsv)); \
+ } \
+ else { /* AMGf_want_scalar */ \
+ dATARGET; /* just use the arg's location */ \
+ sv_setsv(TARG, tmpsv); \
+ if (opASSIGN) \
+ sp--; \
+ SETTARG; \
+ } \
+ PUTBACK; \
+ if (jump) { \
+ OP *jump_o = NORMAL->op_next; \
+ while (jump_o->op_type == OP_NULL) \
+ jump_o = jump_o->op_next; \
+ assert(jump_o->op_type == OP_ENTERSUB); \
+ PL_markstack_ptr--; \
+ return jump_o->op_next; \