Blame t/callck.xs

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);