#define PERL_NO_GET_CONTEXT
#include <EXTERN.h>
#include <perl.h>
#include <XSUB.h>
#define HINT_KEY "Acme::RequireModule"
U32 my_depth = 0;
SV* my_hint_key;
U32 my_hint_key_hash;
Perl_check_t my_old_ck_require;
static OP*
my_pp_require(pTHX){
dVAR; dSP;
if(PL_op->op_flags & OPf_SPECIAL && PL_op->op_type == OP_REQUIRE){
SV* const sv = sv_newmortal();
char* pv;
const char* end;
sv_copypv(sv, POPs);
pv = SvPV_nolen(sv);
end = SvEND(sv); /* ptr to the last character */
while(pv != end){
if(*pv == ':' && *(pv+1) == ':'){
*pv = '/';
Move(pv+2, pv+1, end - pv - 1, char);
end--;
}
pv++;
}
SvEND_set(sv, end);
sv_catpvs(sv, ".pm");
PUSHs(sv);
}
return PL_ppaddr[OP_REQUIRE](aTHX);
}
static OP*
my_ck_require(pTHX_ OP* o){
HE* he = hv_fetch_ent(GvHV(PL_hintgv), my_hint_key, FALSE, my_hint_key_hash);
if( he && SvTRUE(HeVAL(he)) ){
SVOP * const kid = (SVOP*)cUNOPo->op_first;
/* require $foo or "Foo", not require BareWord */
if( !(kid->op_private & OPpCONST_BARE) ){
o->op_flags |= OPf_SPECIAL;
o->op_ppaddr = my_pp_require;
}
}
return my_old_ck_require(aTHX_ o);
}
MODULE = Acme::RequireModule PACKAGE = Acme::RequireModule
PROTOTYPES: DISABLE
BOOT:
my_hint_key = newSVpvs(HINT_KEY);
PERL_HASH(my_hint_key_hash, HINT_KEY, sizeof(HINT_KEY)-1);
SV*
_enter(...)
CODE:
PERL_UNUSED_ARG(items);
if(my_depth == 0){
my_old_ck_require = PL_check[OP_REQUIRE];
PL_check[OP_REQUIRE] = my_ck_require;
}
my_depth++;
RETVAL = newSV(0);
sv_setref_uv(RETVAL, HINT_KEY, my_depth);
OUTPUT:
RETVAL
void
DESTROY(...)
CODE:
PERL_UNUSED_ARG(items);
if(my_depth == 0){
Perl_croak(aTHX_ "panic: %s scope underflow", HINT_KEY);
}
if(my_depth == 1){
PL_check[OP_REQUIRE] = my_old_ck_require;
}
my_depth--;