#include <xs.h>
#include <xs/merge.h>
using xs::Sv;
using xs::merge;
typedef OP* (*opcheck_t) (pTHX_ OP* op);
static opcheck_t orig_opcheck = NULL;
static OP* pp_sassign (pTHX) {
dSP;
Sv left = *SP;
Sv right = *(SP-1);
if (PL_op->op_private & OPpASSIGN_BACKWARDS) swap(left, right);
if (left.is_hash_ref() && right.is_hash_ref()) {
xs::merge(left, right);
POPs; SETs(left);
return NORMAL;
}
return PL_ppaddr[PL_op->op_type](aTHX);
}
static OP* opcheck (pTHX_ OP* op) {
OP* ret = orig_opcheck ? orig_opcheck(aTHX_ op) : op;
const char* packname = SvPVX(PL_curstname);
STRLEN packlen = SvCUR(PL_curstname);
if (packlen < 2 || packname[0] != 'N' || packname[1] != 'S') return ret;
if (packlen > 2 && (packname[2] != ':' || packname[3] != ':')) return ret;
ret->op_ppaddr = pp_sassign;
return ret;
}
static void enable_op_tracking (pTHX) {
if (PL_check[OP_SASSIGN] == opcheck) return;
orig_opcheck = PL_check[OP_SASSIGN];
PL_check[OP_SASSIGN] = opcheck;
}
static void disable_op_tracking (pTHX) {
if (PL_check[OP_SASSIGN] != opcheck) return;
PL_check[OP_SASSIGN] = orig_opcheck;
orig_opcheck = NULL;
}
MODULE = Config::MorePerl PACKAGE = Config::MorePerl
PROTOTYPES: DISABLE
void enable_op_tracking () {
enable_op_tracking(aTHX);
}
void disable_op_tracking () {
disable_op_tracking(aTHX);
}