|
Packit |
b3426c |
#define PERL_NO_GET_CONTEXT 1
|
|
Packit |
b3426c |
#include "EXTERN.h"
|
|
Packit |
b3426c |
#include "perl.h"
|
|
Packit |
b3426c |
#include "callck_callchecker0.h"
|
|
Packit |
b3426c |
#include "XSUB.h"
|
|
Packit |
b3426c |
|
|
Packit |
b3426c |
#define PERL_VERSION_DECIMAL(r,v,s) (r*1000000 + v*1000 + s)
|
|
Packit |
b3426c |
#define PERL_DECIMAL_VERSION \
|
|
Packit |
b3426c |
PERL_VERSION_DECIMAL(PERL_REVISION,PERL_VERSION,PERL_SUBVERSION)
|
|
Packit |
b3426c |
#define PERL_VERSION_GE(r,v,s) \
|
|
Packit |
b3426c |
(PERL_DECIMAL_VERSION >= PERL_VERSION_DECIMAL(r,v,s))
|
|
Packit |
b3426c |
|
|
Packit |
b3426c |
#ifndef cBOOL
|
|
Packit |
b3426c |
# define cBOOL(x) ((bool)!!(x))
|
|
Packit |
b3426c |
#endif /* !cBOOL */
|
|
Packit |
b3426c |
|
|
Packit |
b3426c |
#ifndef PERL_UNUSED_VAR
|
|
Packit |
b3426c |
# define PERL_UNUSED_VAR(x) ((void)x)
|
|
Packit |
b3426c |
#endif /* !PERL_UNUSED_VAR */
|
|
Packit |
b3426c |
|
|
Packit |
b3426c |
#ifndef PERL_UNUSED_ARG
|
|
Packit |
b3426c |
# define PERL_UNUSED_ARG(x) PERL_UNUSED_VAR(x)
|
|
Packit |
b3426c |
#endif /* !PERL_UNUSED_ARG */
|
|
Packit |
b3426c |
|
|
Packit |
b3426c |
#ifndef FPTR2DPTR
|
|
Packit |
b3426c |
# define FPTR2DPTR(t,x) ((t)(UV)(x))
|
|
Packit |
b3426c |
#endif /* !FPTR2DPTR */
|
|
Packit |
b3426c |
|
|
Packit |
b3426c |
#ifndef OpMORESIB_set
|
|
Packit |
b3426c |
# define OpMORESIB_set(o, sib) ((o)->op_sibling = (sib))
|
|
Packit |
b3426c |
# define OpLASTSIB_set(o, parent) ((o)->op_sibling = NULL)
|
|
Packit |
b3426c |
# define OpMAYBESIB_set(o, sib, parent) ((o)->op_sibling = (sib))
|
|
Packit |
b3426c |
#endif /* !OpMORESIB_set */
|
|
Packit |
b3426c |
#ifndef OpSIBLING
|
|
Packit |
b3426c |
# define OpHAS_SIBLING(o) (cBOOL((o)->op_sibling))
|
|
Packit |
b3426c |
# define OpSIBLING(o) (0 + (o)->op_sibling)
|
|
Packit |
b3426c |
#endif /* !OpSIBLING */
|
|
Packit |
b3426c |
|
|
Packit |
b3426c |
#ifndef op_contextualize
|
|
Packit |
b3426c |
# define op_contextualize(o, c) THX_op_contextualize(aTHX_ o, c)
|
|
Packit |
b3426c |
static OP *THX_op_contextualize(pTHX_ OP *o, I32 c)
|
|
Packit |
b3426c |
{
|
|
Packit |
b3426c |
if(c == G_SCALAR) {
|
|
Packit |
b3426c |
OP *sib, *assop, *nullop;
|
|
Packit |
b3426c |
sib = o->op_sibling;
|
|
Packit |
b3426c |
o->op_sibling = NULL;
|
|
Packit |
b3426c |
assop = newASSIGNOP(0, newOP(OP_NULL, 0), 0, o);
|
|
Packit |
b3426c |
o = cBINOPx(assop)->op_first;
|
|
Packit |
b3426c |
nullop = newOP(OP_NULL, 0);
|
|
Packit |
b3426c |
nullop->op_sibling = o->op_sibling;
|
|
Packit |
b3426c |
cBINOPx(assop)->op_first = nullop;
|
|
Packit |
b3426c |
if(!nullop->op_sibling) cBINOPx(assop)->op_last = nullop;
|
|
Packit |
b3426c |
op_free(assop);
|
|
Packit |
b3426c |
o->op_sibling = sib;
|
|
Packit |
b3426c |
return o;
|
|
Packit |
b3426c |
} else {
|
|
Packit |
b3426c |
croak("reserve op_contextualize abused");
|
|
Packit |
b3426c |
}
|
|
Packit |
b3426c |
}
|
|
Packit |
b3426c |
#endif /* !op_contextualize */
|
|
Packit |
b3426c |
|
|
Packit |
b3426c |
static OP *THX_ck_entersub_args_lists(pTHX_ OP *entersubop,
|
|
Packit |
b3426c |
GV *namegv, SV *ckobj)
|
|
Packit |
b3426c |
{
|
|
Packit |
b3426c |
PERL_UNUSED_ARG(namegv);
|
|
Packit |
b3426c |
PERL_UNUSED_ARG(ckobj);
|
|
Packit |
b3426c |
return ck_entersub_args_list(entersubop);
|
|
Packit |
b3426c |
}
|
|
Packit |
b3426c |
|
|
Packit |
b3426c |
static OP *THX_ck_entersub_args_scalars(pTHX_ OP *entersubop,
|
|
Packit |
b3426c |
GV *namegv, SV *ckobj)
|
|
Packit |
b3426c |
{
|
|
Packit |
b3426c |
OP *aop = cUNOPx(entersubop)->op_first;
|
|
Packit |
b3426c |
PERL_UNUSED_ARG(namegv);
|
|
Packit |
b3426c |
PERL_UNUSED_ARG(ckobj);
|
|
Packit |
b3426c |
if (!OpHAS_SIBLING(aop))
|
|
Packit |
b3426c |
aop = cUNOPx(aop)->op_first;
|
|
Packit |
b3426c |
for (aop = OpSIBLING(aop); OpHAS_SIBLING(aop); aop = OpSIBLING(aop)) {
|
|
Packit |
b3426c |
op_contextualize(aop, G_SCALAR);
|
|
Packit |
b3426c |
}
|
|
Packit |
b3426c |
return entersubop;
|
|
Packit |
b3426c |
}
|
|
Packit |
b3426c |
|
|
Packit |
b3426c |
static OP *THX_ck_entersub_multi_sum(pTHX_ OP *entersubop,
|
|
Packit |
b3426c |
GV *namegv, SV *ckobj)
|
|
Packit |
b3426c |
{
|
|
Packit |
b3426c |
OP *sumop = NULL;
|
|
Packit |
b3426c |
OP *pushop = cUNOPx(entersubop)->op_first;
|
|
Packit |
b3426c |
PERL_UNUSED_ARG(namegv);
|
|
Packit |
b3426c |
PERL_UNUSED_ARG(ckobj);
|
|
Packit |
b3426c |
if (!OpHAS_SIBLING(pushop))
|
|
Packit |
b3426c |
pushop = cUNOPx(pushop)->op_first;
|
|
Packit |
b3426c |
while (1) {
|
|
Packit |
b3426c |
OP *aop = OpSIBLING(pushop);
|
|
Packit |
b3426c |
OP *as;
|
|
Packit |
b3426c |
if (!OpHAS_SIBLING(aop)) break;
|
|
Packit |
b3426c |
as = OpSIBLING(aop);
|
|
Packit |
b3426c |
OpMORESIB_set(pushop, as);
|
|
Packit |
b3426c |
OpLASTSIB_set(aop, NULL);
|
|
Packit |
b3426c |
op_contextualize(aop, G_SCALAR);
|
|
Packit |
b3426c |
if (sumop) {
|
|
Packit |
b3426c |
sumop = newBINOP(OP_ADD, 0, sumop, aop);
|
|
Packit |
b3426c |
} else {
|
|
Packit |
b3426c |
sumop = aop;
|
|
Packit |
b3426c |
}
|
|
Packit |
b3426c |
}
|
|
Packit |
b3426c |
if (!sumop)
|
|
Packit |
b3426c |
sumop = newSVOP(OP_CONST, 0, newSViv(0));
|
|
Packit |
b3426c |
op_free(entersubop);
|
|
Packit |
b3426c |
return sumop;
|
|
Packit |
b3426c |
}
|
|
Packit |
b3426c |
|
|
Packit |
b3426c |
MODULE = t::callck PACKAGE = t::callck
|
|
Packit |
b3426c |
|
|
Packit |
b3426c |
PROTOTYPES: DISABLE
|
|
Packit |
b3426c |
|
|
Packit |
b3426c |
void
|
|
Packit |
b3426c |
test_cv_getset_call_checker()
|
|
Packit |
b3426c |
PROTOTYPE:
|
|
Packit |
b3426c |
PREINIT:
|
|
Packit |
b3426c |
CV *t0_cv, *t1_cv;
|
|
Packit |
b3426c |
Perl_call_checker ckfun;
|
|
Packit |
b3426c |
SV *ckobj;
|
|
Packit |
b3426c |
CODE:
|
|
Packit |
b3426c |
#define croak_fail() croak("fail at " __FILE__ " line %d", __LINE__)
|
|
Packit |
b3426c |
#define croak_fail_ne(h, w) \
|
|
Packit |
b3426c |
croak("fail %p!=%p at " __FILE__ " line %d", (h), (w), __LINE__)
|
|
Packit |
b3426c |
#define check_cc(cv, xckfun, xckobj) \
|
|
Packit |
b3426c |
do { \
|
|
Packit |
b3426c |
cv_get_call_checker((cv), &ckfun, &ckobj); \
|
|
Packit |
b3426c |
if (ckfun != (xckfun)) \
|
|
Packit |
b3426c |
croak_fail_ne(FPTR2DPTR(void *, ckfun), xckfun); \
|
|
Packit |
b3426c |
if (ckobj != (xckobj)) \
|
|
Packit |
b3426c |
croak_fail_ne(FPTR2DPTR(void *, ckobj), xckobj); \
|
|
Packit |
b3426c |
} while(0)
|
|
Packit |
b3426c |
t0_cv = get_cv("t::callck::t0", 0);
|
|
Packit |
b3426c |
t1_cv = get_cv("t::callck::t1", 0);
|
|
Packit |
b3426c |
check_cc(t0_cv, Perl_ck_entersub_args_proto_or_list, (SV*)t0_cv);
|
|
Packit |
b3426c |
check_cc(t1_cv, Perl_ck_entersub_args_proto_or_list, (SV*)t1_cv);
|
|
Packit |
b3426c |
cv_set_call_checker(t1_cv, Perl_ck_entersub_args_proto_or_list,
|
|
Packit |
b3426c |
&PL_sv_yes);
|
|
Packit |
b3426c |
check_cc(t0_cv, Perl_ck_entersub_args_proto_or_list, (SV*)t0_cv);
|
|
Packit |
b3426c |
check_cc(t1_cv, Perl_ck_entersub_args_proto_or_list, &PL_sv_yes);
|
|
Packit |
b3426c |
cv_set_call_checker(t0_cv, THX_ck_entersub_args_scalars, &PL_sv_no);
|
|
Packit |
b3426c |
check_cc(t0_cv, THX_ck_entersub_args_scalars, &PL_sv_no);
|
|
Packit |
b3426c |
check_cc(t1_cv, Perl_ck_entersub_args_proto_or_list, &PL_sv_yes);
|
|
Packit |
b3426c |
cv_set_call_checker(t1_cv, Perl_ck_entersub_args_proto_or_list,
|
|
Packit |
b3426c |
(SV*)t1_cv);
|
|
Packit |
b3426c |
check_cc(t0_cv, THX_ck_entersub_args_scalars, &PL_sv_no);
|
|
Packit |
b3426c |
check_cc(t1_cv, Perl_ck_entersub_args_proto_or_list, (SV*)t1_cv);
|
|
Packit |
b3426c |
cv_set_call_checker(t0_cv, Perl_ck_entersub_args_proto_or_list,
|
|
Packit |
b3426c |
(SV*)t0_cv);
|
|
Packit |
b3426c |
check_cc(t0_cv, Perl_ck_entersub_args_proto_or_list, (SV*)t0_cv);
|
|
Packit |
b3426c |
check_cc(t1_cv, Perl_ck_entersub_args_proto_or_list, (SV*)t1_cv);
|
|
Packit |
b3426c |
if (SvMAGICAL((SV*)t0_cv) || SvMAGIC((SV*)t0_cv)) croak_fail();
|
|
Packit |
b3426c |
if (SvMAGICAL((SV*)t1_cv) || SvMAGIC((SV*)t1_cv)) croak_fail();
|
|
Packit |
b3426c |
#undef check_cc
|
|
Packit |
b3426c |
#undef croak_fail_ne
|
|
Packit |
b3426c |
#undef croak_fail
|
|
Packit |
b3426c |
|
|
Packit |
b3426c |
void
|
|
Packit |
b3426c |
t0()
|
|
Packit |
b3426c |
PROTOTYPE:
|
|
Packit |
b3426c |
CODE:
|
|
Packit |
b3426c |
;
|
|
Packit |
b3426c |
|
|
Packit |
b3426c |
void
|
|
Packit |
b3426c |
t1()
|
|
Packit |
b3426c |
PROTOTYPE:
|
|
Packit |
b3426c |
CODE:
|
|
Packit |
b3426c |
;
|
|
Packit |
b3426c |
|
|
Packit |
b3426c |
void
|
|
Packit |
b3426c |
cv_set_call_checker_lists(CV *cv)
|
|
Packit |
b3426c |
PROTOTYPE: $
|
|
Packit |
b3426c |
CODE:
|
|
Packit |
b3426c |
cv_set_call_checker(cv, THX_ck_entersub_args_lists, &PL_sv_undef);
|
|
Packit |
b3426c |
|
|
Packit |
b3426c |
void
|
|
Packit |
b3426c |
cv_set_call_checker_scalars(CV *cv)
|
|
Packit |
b3426c |
PROTOTYPE: $
|
|
Packit |
b3426c |
CODE:
|
|
Packit |
b3426c |
cv_set_call_checker(cv, THX_ck_entersub_args_scalars, &PL_sv_undef);
|
|
Packit |
b3426c |
|
|
Packit |
b3426c |
void
|
|
Packit |
b3426c |
cv_set_call_checker_proto(CV *cv, SV *proto)
|
|
Packit |
b3426c |
PROTOTYPE: $$
|
|
Packit |
b3426c |
CODE:
|
|
Packit |
b3426c |
if (SvROK(proto))
|
|
Packit |
b3426c |
proto = SvRV(proto);
|
|
Packit |
b3426c |
cv_set_call_checker(cv, Perl_ck_entersub_args_proto, proto);
|
|
Packit |
b3426c |
|
|
Packit |
b3426c |
void
|
|
Packit |
b3426c |
cv_set_call_checker_proto_or_list(CV *cv, SV *proto)
|
|
Packit |
b3426c |
PROTOTYPE: $$
|
|
Packit |
b3426c |
CODE:
|
|
Packit |
b3426c |
if (SvROK(proto))
|
|
Packit |
b3426c |
proto = SvRV(proto);
|
|
Packit |
b3426c |
cv_set_call_checker(cv, Perl_ck_entersub_args_proto_or_list, proto);
|
|
Packit |
b3426c |
|
|
Packit |
b3426c |
void
|
|
Packit |
b3426c |
cv_set_call_checker_multi_sum(CV *cv)
|
|
Packit |
b3426c |
PROTOTYPE: $
|
|
Packit |
b3426c |
CODE:
|
|
Packit |
b3426c |
cv_set_call_checker(cv, THX_ck_entersub_multi_sum, &PL_sv_undef);
|