#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"
#include "ppport.h"
#include "hook_op_check.h"
#include "hook_op_ppaddr.h"
#define PERL_VERSION_DECIMAL(r,v,s) (r*1000000 + v*1000 + s)
#define PERL_DECIMAL_VERSION \
PERL_VERSION_DECIMAL(PERL_REVISION,PERL_VERSION,PERL_SUBVERSION)
#define PERL_VERSION_GE(r,v,s) \
(PERL_DECIMAL_VERSION >= PERL_VERSION_DECIMAL(r,v,s))
STATIC SV * dispatch = NULL;
STATIC OP *
execute_call_back (pTHX_ OP *op,
void
*user_data) {
dSP;
SV* result;
int
ret;
ENTER;
SAVETMPS;
PUSHMARK(SP - 1);
XPUSHs(sv_2mortal(newSVpv(PL_op_name[op->op_type], 0)));
PUTBACK;
if
(dispatch == NULL) {
dispatch = (SV *) get_cv(
"Unicode::Casing::_dispatch"
, 0);
}
if
((ret = call_sv(dispatch, GIMME_V)) != 1) {
Perl_croak(aTHX_
"panic: Unicode::Casing::_dispatch returned %d values instead of 1\n"
, ret);
}
SPAGAIN;
result = POPs;
SvREFCNT_inc(result);
FREETMPS;
LEAVE;
SvTEMP_on(result);
XPUSHs(result);
RETURN;
}
STATIC
OP *
check_call_back(pTHX_ OP *op,
void
*user_data) {
hook_op_ppaddr (op, execute_call_back, user_data);
return
op;
}
STATIC
opcode
opcode_from_name(pTHX_
const
char
*
const
name) {
if
(*name ==
'u'
) {
if
(
strlen
(name) > 2) {
return
OP_UCFIRST;
}
else
{
return
OP_UC;
}
}
#if PERL_VERSION_GE(5,15,8)
else
if
(*name ==
'f'
) {
return
OP_FC;
}
#endif
else
if
(
strlen
(name) > 2) {
return
OP_LCFIRST;
}
return
OP_LC;
}
MODULE = Unicode::Casing PACKAGE = Unicode::Casing
UV
setup(type)
char
* type;
PROTOTYPE: $
CODE:
RETVAL = (UV) hook_op_check(opcode_from_name(aTHX_ type),
check_call_back,
NULL);
OUTPUT:
RETVAL
void
teardown(type, id)
char
*type
UV id;
CODE:
hook_op_check_remove(opcode_from_name(aTHX_ type), id);