File Coverage

lib/Devel/CallChecker.xs
Criterion Covered Total %
statement 1 1 100.0
branch n/a
condition n/a
subroutine n/a
pod n/a
total 1 1 100.0


line stmt bran cond sub pod time code
1             #define PERL_NO_GET_CONTEXT 1
2             #include "EXTERN.h"
3             #include "perl.h"
4             #include "XSUB.h"
5              
6             #define Q_PERL_VERSION_DECIMAL(r,v,s) ((r)*1000000 + (v)*1000 + (s))
7             #define Q_PERL_DECIMAL_VERSION \
8             Q_PERL_VERSION_DECIMAL(PERL_REVISION,PERL_VERSION,PERL_SUBVERSION)
9             #define Q_PERL_VERSION_GE(r,v,s) \
10             (Q_PERL_DECIMAL_VERSION >= Q_PERL_VERSION_DECIMAL(r,v,s))
11             #define Q_PERL_VERSION_LT(r,v,s) \
12             (Q_PERL_DECIMAL_VERSION < Q_PERL_VERSION_DECIMAL(r,v,s))
13              
14             #if (Q_PERL_VERSION_GE(5,17,6) && Q_PERL_VERSION_LT(5,17,11)) || \
15             (Q_PERL_VERSION_GE(5,19,3) && Q_PERL_VERSION_LT(5,21,1))
16             PERL_STATIC_INLINE void suppress_unused_warning(void)
17             {
18             (void) S_croak_memory_wrap;
19             }
20             #endif /* (>=5.17.6 && <5.17.11) || (>=5.19.3 && <5.21.1) */
21              
22             #if Q_PERL_VERSION_LT(5,7,2)
23             # undef dNOOP
24             # define dNOOP extern int Perl___notused_func(void)
25             #endif /* <5.7.2 */
26              
27             #ifndef cBOOL
28             # define cBOOL(x) ((bool)!!(x))
29             #endif /* !cBOOL */
30              
31             #ifndef newSVpvs
32             # define newSVpvs(s) newSVpvn("" s "", (sizeof("" s "")-1))
33             #endif /* !newSVpvs */
34              
35             #ifndef OpMORESIB_set
36             # define OpMORESIB_set(o, sib) ((o)->op_sibling = (sib))
37             # define OpLASTSIB_set(o, parent) ((o)->op_sibling = NULL)
38             # define OpMAYBESIB_set(o, sib, parent) ((o)->op_sibling = (sib))
39             #endif /* !OpMORESIB_set */
40             #ifndef OpSIBLING
41             # define OpHAS_SIBLING(o) (cBOOL((o)->op_sibling))
42             # define OpSIBLING(o) (0 + (o)->op_sibling)
43             #endif /* !OpSIBLING */
44              
45             #if Q_PERL_VERSION_GE(5,7,3)
46             # define PERL_UNUSED_THX() NOOP
47             #else /* <5.7.3 */
48             # define PERL_UNUSED_THX() ((void)(aTHX+0))
49             #endif /* <5.7.3 */
50              
51             #define Q_PFX xAd8NP3gxZglovQRL5Hn_
52             #define Q_PFXS STRINGIFY(Q_PFX)
53             #define Q_CONCAT0(a,b) a##b
54             #define Q_CONCAT1(a,b) Q_CONCAT0(a,b)
55             #define Q_PFXD(name) Q_CONCAT1(Q_PFX, name)
56              
57             #if defined(WIN32) && Q_PERL_VERSION_GE(5,13,6)
58             # define Q_BASE_CALLCONV EXTERN_C
59             # define Q_BASE_CALLCONV_S "EXTERN_C"
60             #else /* !(WIN32 && >= 5.13.6) */
61             # define Q_BASE_CALLCONV PERL_CALLCONV
62             # define Q_BASE_CALLCONV_S "PERL_CALLCONV"
63             #endif /* !(WIN32 && >= 5.13.6) */
64              
65             #define Q_EXPORT_CALLCONV Q_BASE_CALLCONV
66              
67             #if defined(WIN32) || defined(__CYGWIN__)
68             # define Q_IMPORT_CALLCONV_S Q_BASE_CALLCONV_S " __declspec(dllimport)"
69             #else
70             # define Q_IMPORT_CALLCONV_S Q_BASE_CALLCONV_S
71             #endif
72              
73             #ifndef rv2cv_op_cv
74              
75             # define Q_RV2CV_CONST_REF_RESOLVES Q_PERL_VERSION_GE(5,11,2)
76              
77             # define RV2CVOPCV_MARK_EARLY 0x00000001
78             # define RV2CVOPCV_RETURN_NAME_GV 0x00000002
79              
80             # define Perl_rv2cv_op_cv Q_PFXD(roc0)
81             # define rv2cv_op_cv(cvop, flags) Perl_rv2cv_op_cv(aTHX_ cvop, flags)
82             Q_EXPORT_CALLCONV CV *Q_PFXD(roc0)(pTHX_ OP *cvop, U32 flags)
83             {
84             OP *rvop;
85             CV *cv;
86             GV *gv;
87             if(!(cvop->op_type == OP_RV2CV &&
88             !(cvop->op_private & OPpENTERSUB_AMPER) &&
89             (cvop->op_flags & OPf_KIDS)))
90             return NULL;
91             rvop = cUNOPx(cvop)->op_first;
92             switch(rvop->op_type) {
93             case OP_GV: {
94             gv = cGVOPx_gv(rvop);
95             cv = GvCVu(gv);
96             if(!cv) {
97             if(flags & RV2CVOPCV_MARK_EARLY)
98             rvop->op_private |= OPpEARLY_CV;
99             return NULL;
100             }
101             } break;
102             # if Q_RV2CV_CONST_REF_RESOLVES
103             case OP_CONST: {
104             SV *rv = cSVOPx_sv(rvop);
105             if(!SvROK(rv)) return NULL;
106             cv = (CV*)SvRV(rv);
107             gv = NULL;
108             } break;
109             # endif /* Q_RV2CV_CONST_REF_RESOLVES */
110             default: {
111             return NULL;
112             } break;
113             }
114             if(SvTYPE((SV*)cv) != SVt_PVCV) return NULL;
115             if(flags & RV2CVOPCV_RETURN_NAME_GV) {
116             if(!CvANON(cv) || !gv) gv = CvGV(cv);
117             return (CV*)gv;
118             } else {
119             return cv;
120             }
121             }
122              
123             # define Q_PROVIDE_RV2CV_OP_CV 1
124              
125             #endif /* !rv2cv_op_cv */
126              
127             #ifndef ck_entersub_args_proto_or_list
128              
129             # ifndef newSV_type
130             # define newSV_type(type) THX_newSV_type(aTHX_ type)
131             static SV *THX_newSV_type(pTHX_ svtype type)
132             {
133             SV *sv = newSV(0);
134             (void) SvUPGRADE(sv, type);
135             return sv;
136             }
137             # endif /* !newSV_type */
138              
139             # ifndef GvCV_set
140             # define GvCV_set(gv, cv) (GvCV(gv) = (cv))
141             # endif /* !GvCV_set */
142              
143             # ifndef CvGV_set
144             # define CvGV_set(cv, gv) (CvGV(cv) = (gv))
145             # endif /* !CvGV_set */
146              
147             # define entersub_extract_args(eo) THX_entersub_extract_args(aTHX_ eo)
148             static OP *THX_entersub_extract_args(pTHX_ OP *entersubop)
149             {
150             OP *pushop, *aop, *bop, *cop;
151             PERL_UNUSED_THX();
152             if(!(entersubop->op_flags & OPf_KIDS)) return NULL;
153             pushop = cUNOPx(entersubop)->op_first;
154             if(!OpHAS_SIBLING(pushop)) {
155             if(!(pushop->op_flags & OPf_KIDS)) return NULL;
156             pushop = cUNOPx(pushop)->op_first;
157             if(!OpHAS_SIBLING(pushop)) return NULL;
158             }
159             for(bop = pushop; (cop = OpSIBLING(bop), OpHAS_SIBLING(cop));
160             bop = cop) ;
161             if(bop == pushop) return NULL;
162             aop = OpSIBLING(pushop);
163             OpMORESIB_set(pushop, cop);
164             OpLASTSIB_set(bop, NULL);
165             return aop;
166             }
167              
168             # define entersub_inject_args(eo, ao) THX_entersub_inject_args(aTHX_ eo, ao)
169             static void THX_entersub_inject_args(pTHX_ OP *entersubop, OP *aop)
170             {
171             OP *pushop, *bop, *cop;
172             if(!aop) return;
173             if(!(entersubop->op_flags & OPf_KIDS)) {
174             abort:
175             while(aop) {
176             bop = OpSIBLING(aop);
177             op_free(aop);
178             aop = bop;
179             }
180             return;
181             }
182             pushop = cUNOPx(entersubop)->op_first;
183             if(!OpHAS_SIBLING(pushop)) {
184             if(!(pushop->op_flags & OPf_KIDS)) goto abort;
185             pushop = cUNOPx(pushop)->op_first;
186             if(!OpHAS_SIBLING(pushop)) goto abort;
187             }
188             for(bop = aop; (cop = OpSIBLING(bop)); bop = cop) ;
189             OpMORESIB_set(bop, OpSIBLING(pushop));
190             OpMORESIB_set(pushop, aop);
191             }
192              
193             # define ck_entersub_args_stalk(eo, so) THX_ck_entersub_args_stalk(aTHX_ eo, so)
194             static OP *THX_ck_entersub_args_stalk(pTHX_ OP *entersubop, OP *stalkcvop)
195             {
196             OP *stalkenterop = newLISTOP(OP_LIST, 0, newCVREF(0, stalkcvop), NULL);
197             entersub_inject_args(stalkenterop, entersub_extract_args(entersubop));
198             stalkenterop = newUNOP(OP_ENTERSUB, OPf_STACKED, stalkenterop);
199             entersub_inject_args(entersubop, entersub_extract_args(stalkenterop));
200             op_free(stalkenterop);
201             return entersubop;
202             }
203              
204             # define Perl_ck_entersub_args_list Q_PFXD(eal0)
205             # define ck_entersub_args_list(o) Perl_ck_entersub_args_list(aTHX_ o)
206             Q_EXPORT_CALLCONV OP *Q_PFXD(eal0)(pTHX_ OP *entersubop)
207             {
208             return ck_entersub_args_stalk(entersubop, newOP(OP_PADANY, 0));
209             }
210              
211             # define Perl_ck_entersub_args_proto Q_PFXD(eap0)
212             # define ck_entersub_args_proto(o, gv, sv) \
213             Perl_ck_entersub_args_proto(aTHX_ o, gv, sv)
214             Q_EXPORT_CALLCONV OP *Q_PFXD(eap0)(pTHX_ OP *entersubop, GV *namegv,
215             SV *protosv)
216             {
217             const char *proto;
218             STRLEN proto_len;
219             CV *stalkcv;
220             GV *stalkgv;
221             if(SvTYPE(protosv) == SVt_PVCV ? !SvPOK(protosv) : !SvOK(protosv))
222             croak("panic: ck_entersub_args_proto CV with no proto");
223             proto = SvPV(protosv, proto_len);
224             stalkcv = (CV*)newSV_type(SVt_PVCV);
225             sv_setpvn((SV*)stalkcv, proto, proto_len);
226             stalkgv = (GV*)sv_2mortal(newSV(0));
227             gv_init(stalkgv, GvSTASH(namegv), GvNAME(namegv), GvNAMELEN(namegv), 0);
228             GvCV_set(stalkgv, stalkcv);
229             CvGV_set(stalkcv, stalkgv);
230             return ck_entersub_args_stalk(entersubop, newGVOP(OP_GV, 0, stalkgv));
231             }
232              
233             # define Perl_ck_entersub_args_proto_or_list Q_PFXD(ean0)
234             # define ck_entersub_args_proto_or_list(o, gv, sv) \
235             Perl_ck_entersub_args_proto_or_list(aTHX_ o, gv, sv)
236             Q_EXPORT_CALLCONV OP *Q_PFXD(ean0)(pTHX_ OP *entersubop, GV *namegv,
237             SV *protosv)
238             {
239             if(SvTYPE(protosv) == SVt_PVCV ? SvPOK(protosv) : SvOK(protosv))
240             return ck_entersub_args_proto(entersubop, namegv, protosv);
241             else
242             return ck_entersub_args_list(entersubop);
243             }
244              
245             # define Q_PROVIDE_CK_ENTERSUB_ARGS_PROTO_OR_LIST 1
246              
247             #endif /* !ck_entersub_args_proto_or_list */
248              
249             #ifndef cv_set_call_checker
250              
251             # ifndef Newxz
252             # define Newxz(v,n,t) Newz(0,v,n,t)
253             # endif /* !Newxz */
254              
255             # ifndef SvMAGIC_set
256             # define SvMAGIC_set(sv, mg) (SvMAGIC(sv) = (mg))
257             # endif /* !SvMAGIC_set */
258              
259             # ifndef DPTR2FPTR
260             # define DPTR2FPTR(t,x) ((t)(UV)(x))
261             # endif /* !DPTR2FPTR */
262              
263             # ifndef FPTR2DPTR
264             # define FPTR2DPTR(t,x) ((t)(UV)(x))
265             # endif /* !FPTR2DPTR */
266              
267             # ifndef op_null
268             # define op_null(o) THX_op_null(aTHX_ o)
269             static void THX_op_null(pTHX_ OP *o)
270             {
271             PERL_UNUSED_THX();
272             if(o->op_type == OP_NULL) return;
273             /* must not be used on any op requiring non-trivial clearing */
274             o->op_targ = o->op_type;
275             o->op_type = OP_NULL;
276             o->op_ppaddr = PL_ppaddr[OP_NULL];
277             }
278             # endif /* !op_null */
279              
280             # ifndef mg_findext
281             # define mg_findext(sv, type, vtbl) THX_mg_findext(aTHX_ sv, type, vtbl)
282             static MAGIC *THX_mg_findext(pTHX_ SV *sv, int type, MGVTBL const *vtbl)
283             {
284             MAGIC *mg;
285             PERL_UNUSED_THX();
286             if(sv)
287             for(mg = SvMAGIC(sv); mg; mg = mg->mg_moremagic)
288             if(mg->mg_type == type && mg->mg_virtual == vtbl)
289             return mg;
290             return NULL;
291             }
292             # endif /* !mg_findext */
293              
294             # ifndef sv_unmagicext
295             # define sv_unmagicext(sv, type, vtbl) THX_sv_unmagicext(aTHX_ sv, type, vtbl)
296             static int THX_sv_unmagicext(pTHX_ SV *sv, int type, MGVTBL const *vtbl)
297             {
298             MAGIC *mg, **mgp;
299             if((vtbl && vtbl->svt_free)
300             # ifdef PERL_MAGIC_regex_global
301             || type == PERL_MAGIC_regex_global
302             # endif /* PERL_MAGIC_regex_global */
303             )
304             /* exceeded intended usage of this reserve implementation */
305             return 0;
306             if(SvTYPE(sv) < SVt_PVMG || !SvMAGIC(sv)) return 0;
307             mgp = NULL;
308             for(mg = mgp ? *mgp : SvMAGIC(sv); mg; mg = mgp ? *mgp : SvMAGIC(sv)) {
309             if(mg->mg_type == type && mg->mg_virtual == vtbl) {
310             if(mgp)
311             *mgp = mg->mg_moremagic;
312             else
313             SvMAGIC_set(sv, mg->mg_moremagic);
314             if(mg->mg_flags & MGf_REFCOUNTED)
315             SvREFCNT_dec(mg->mg_obj);
316             Safefree(mg);
317             } else {
318             mgp = &mg->mg_moremagic;
319             }
320             }
321             SvMAGICAL_off(sv);
322             mg_magical(sv);
323             return 0;
324             }
325             # endif /* !sv_unmagicext */
326              
327             # ifndef sv_magicext
328             # define sv_magicext(sv, obj, type, vtbl, name, namlen) \
329             THX_sv_magicext(aTHX_ sv, obj, type, vtbl, name, namlen)
330             static MAGIC *THX_sv_magicext(pTHX_ SV *sv, SV *obj, int type,
331             MGVTBL const *vtbl, char const *name, I32 namlen)
332             {
333             MAGIC *mg;
334             if(!(obj == &PL_sv_undef && !name && !namlen))
335             /* exceeded intended usage of this reserve implementation */
336             return NULL;
337             Newxz(mg, 1, MAGIC);
338             mg->mg_virtual = (MGVTBL*)vtbl;
339             mg->mg_type = type;
340             mg->mg_obj = &PL_sv_undef;
341             (void) SvUPGRADE(sv, SVt_PVMG);
342             mg->mg_moremagic = SvMAGIC(sv);
343             SvMAGIC_set(sv, mg);
344             SvMAGICAL_off(sv);
345             mg_magical(sv);
346             return mg;
347             }
348             # endif /* !sv_magicext */
349              
350             # ifndef PERL_MAGIC_ext
351             # define PERL_MAGIC_ext '~'
352             # endif /* !PERL_MAGIC_ext */
353              
354             # if Q_PERL_VERSION_LT(5,9,3)
355             typedef OP *(*Perl_check_t)(pTHX_ OP *);
356             # endif /* <5.9.3 */
357              
358             # if Q_PERL_VERSION_LT(5,10,1)
359             typedef unsigned Optype;
360             # endif /* <5.10.1 */
361              
362             # ifndef wrap_op_checker
363             # define wrap_op_checker(c,n,o) THX_wrap_op_checker(aTHX_ c,n,o)
364             static void THX_wrap_op_checker(pTHX_ Optype opcode,
365             Perl_check_t new_checker, Perl_check_t *old_checker_p)
366             {
367             PERL_UNUSED_THX();
368             if(*old_checker_p) return;
369             OP_REFCNT_LOCK;
370             if(!*old_checker_p) {
371             *old_checker_p = PL_check[opcode];
372             PL_check[opcode] = new_checker;
373             }
374             OP_REFCNT_UNLOCK;
375             }
376             # endif /* !wrap_op_checker */
377              
378             static MGVTBL const mgvtbl_checkcall;
379              
380             typedef OP *(*Perl_call_checker)(pTHX_ OP *, GV *, SV *);
381              
382             # define Perl_cv_get_call_checker Q_PFXD(gcc0)
383             # define cv_get_call_checker(cv, THX_ckfun_p, ckobj_p) \
384             Perl_cv_get_call_checker(aTHX_ cv, THX_ckfun_p, ckobj_p)
385             Q_EXPORT_CALLCONV void Q_PFXD(gcc0)(pTHX_ CV *cv,
386             Perl_call_checker *THX_ckfun_p, SV **ckobj_p)
387             {
388             MAGIC *callmg = SvMAGICAL((SV*)cv) ?
389             mg_findext((SV*)cv, PERL_MAGIC_ext, (MGVTBL*)&mgvtbl_checkcall)
390             : NULL;
391             if(callmg) {
392             *THX_ckfun_p = DPTR2FPTR(Perl_call_checker, callmg->mg_ptr);
393             *ckobj_p = callmg->mg_obj;
394             } else {
395             *THX_ckfun_p = Perl_ck_entersub_args_proto_or_list;
396             *ckobj_p = (SV*)cv;
397             }
398             }
399              
400             # define Perl_cv_set_call_checker Q_PFXD(scc0)
401             # define cv_set_call_checker(cv, THX_ckfun, ckobj) \
402             Perl_cv_set_call_checker(aTHX_ cv, THX_ckfun, ckobj)
403             Q_EXPORT_CALLCONV void Q_PFXD(scc0)(pTHX_ CV *cv,
404             Perl_call_checker THX_ckfun, SV *ckobj)
405             {
406             if(THX_ckfun == Perl_ck_entersub_args_proto_or_list &&
407             ckobj == (SV*)cv) {
408             if(SvMAGICAL((SV*)cv))
409             sv_unmagicext((SV*)cv, PERL_MAGIC_ext,
410             (MGVTBL*)&mgvtbl_checkcall);
411             } else {
412             MAGIC *callmg = mg_findext((SV*)cv, PERL_MAGIC_ext,
413             (MGVTBL*)&mgvtbl_checkcall);
414             if(!callmg)
415             callmg = sv_magicext((SV*)cv, &PL_sv_undef,
416             PERL_MAGIC_ext,
417             (MGVTBL*)&mgvtbl_checkcall, NULL, 0);
418             if(callmg->mg_flags & MGf_REFCOUNTED) {
419             SvREFCNT_dec(callmg->mg_obj);
420             callmg->mg_flags &= ~MGf_REFCOUNTED;
421             }
422             callmg->mg_ptr = FPTR2DPTR(char *, THX_ckfun);
423             callmg->mg_obj = ckobj;
424             if(ckobj != (SV*)cv) {
425             SvREFCNT_inc(ckobj);
426             callmg->mg_flags |= MGf_REFCOUNTED;
427             }
428             }
429             }
430              
431             static OP *(*THX_nxck_entersub)(pTHX_ OP *);
432              
433             static OP *THX_myck_entersub(pTHX_ OP *entersubop)
434             {
435             OP *aop, *cvop;
436             CV *cv;
437             GV *namegv;
438             Perl_call_checker THX_ckfun;
439             SV *ckobj;
440             aop = cUNOPx(entersubop)->op_first;
441             if(!OpHAS_SIBLING(aop)) aop = cUNOPx(aop)->op_first;
442             aop = OpSIBLING(aop);
443             for(cvop = aop; OpHAS_SIBLING(cvop); cvop = OpSIBLING(cvop)) ;
444             if(!(cv = rv2cv_op_cv(cvop, 0)))
445             return THX_nxck_entersub(aTHX_ entersubop);
446             cv_get_call_checker(cv, &THX_ckfun, &ckobj);
447             if(THX_ckfun == Perl_ck_entersub_args_proto_or_list && ckobj == (SV*)cv)
448             return THX_nxck_entersub(aTHX_ entersubop);
449             namegv = (GV*)rv2cv_op_cv(cvop,
450             RV2CVOPCV_MARK_EARLY|RV2CVOPCV_RETURN_NAME_GV);
451             entersubop->op_private |= OPpENTERSUB_HASTARG;
452             entersubop->op_private |= (PL_hints & HINT_STRICT_REFS);
453             if(PERLDB_SUB && PL_curstash != PL_debstash)
454             entersubop->op_private |= OPpENTERSUB_DB;
455             op_null(cvop);
456             return THX_ckfun(aTHX_ entersubop, namegv, ckobj);
457             }
458              
459             # define Q_PROVIDE_CV_SET_CALL_CHECKER 1
460              
461             #endif /* !cv_set_call_checker */
462              
463             MODULE = Devel::CallChecker PACKAGE = Devel::CallChecker
464              
465             PROTOTYPES: DISABLE
466              
467             BOOT:
468             #if Q_PROVIDE_CV_SET_CALL_CHECKER
469             wrap_op_checker(OP_ENTERSUB, THX_myck_entersub, &THX_nxck_entersub);
470             #endif /* Q_PROVIDE_CV_SET_CALL_CHECKER */
471              
472             SV *
473             callchecker0_h()
474             CODE:
475             #if PERL_VERSION & 1
476             # define Q_CODE_PERL_SUBVERSION_CRITERION \
477             " && PERL_SUBVERSION == " STRINGIFY(PERL_SUBVERSION)
478             # define Q_TEXT_PERL_SUBVERSION_CRITERION "." STRINGIFY(PERL_SUBVERSION)
479             #else /* !(PERL_VERSION & 1) */
480             # define Q_CODE_PERL_SUBVERSION_CRITERION ""
481             # define Q_TEXT_PERL_SUBVERSION_CRITERION ""
482             #endif /* !(PERL_VERSION & 1) */
483             #define Q_DEFFN(RETTYPE, PUBNAME, PRIVNAME, ARGTYPES, ARGNAMES) \
484             Q_IMPORT_CALLCONV_S " " RETTYPE " " \
485             Q_PFXS PRIVNAME "(pTHX_ " ARGTYPES ");\n" \
486             "#define Perl_" PUBNAME " " Q_PFXS PRIVNAME "\n" \
487             "#define " PUBNAME "(" ARGNAMES ") " \
488             "Perl_" PUBNAME "(aTHX_ " ARGNAMES ")\n"
489             #if Q_PROVIDE_RV2CV_OP_CV
490             # define Q_CODE_PROVIDE_RV2CV_OP_CV \
491             "#define RV2CVOPCV_MARK_EARLY 0x00000001\n" \
492             "#define RV2CVOPCV_RETURN_NAME_GV 0x00000002\n" \
493             Q_DEFFN("CV *", "rv2cv_op_cv", "roc0", "OP *, U32", "cvop, flags")
494             #else /* !Q_PROVIDE_RV2CV_OP_CV */
495             # define Q_CODE_PROVIDE_RV2CV_OP_CV ""
496             #endif /* !Q_PROVIDE_RV2CV_OP_CV */
497             #if Q_PROVIDE_CK_ENTERSUB_ARGS_PROTO_OR_LIST
498             # define Q_CODE_PROVIDE_CK_ENTERSUB_ARGS_PROTO_OR_LIST \
499             Q_DEFFN("OP *", "ck_entersub_args_list", "eal0", "OP *", "o") \
500             Q_DEFFN("OP *", "ck_entersub_args_proto", "eap0", \
501             "OP *, GV *, SV *", "o, gv, sv") \
502             Q_DEFFN("OP *", "ck_entersub_args_proto_or_list", "ean0", \
503             "OP *, GV *, SV *", "o, gv, sv")
504             #else /* !Q_PROVIDE_CK_ENTERSUB_ARGS_PROTO_OR_LIST */
505             # define Q_CODE_PROVIDE_CK_ENTERSUB_ARGS_PROTO_OR_LIST ""
506             #endif /* !Q_PROVIDE_CK_ENTERSUB_ARGS_PROTO_OR_LIST */
507             #if Q_PROVIDE_CV_SET_CALL_CHECKER
508             # define Q_CODE_PROVIDE_CV_SET_CALL_CHECKER \
509             "typedef OP *(*Perl_call_checker)(pTHX_ OP *, GV *, SV *);\n" \
510             Q_DEFFN("void", "cv_get_call_checker", "gcc0", \
511             "CV *, Perl_call_checker *, SV **", "cv, fp, op") \
512             Q_DEFFN("void", "cv_set_call_checker", "scc0", \
513             "CV *, Perl_call_checker, SV *", "cv, f, o")
514             #else /* !Q_PROVIDE_CV_SET_CALL_CHECKER */
515             # define Q_CODE_PROVIDE_CV_SET_CALL_CHECKER ""
516             #endif /* !Q_PROVIDE_CV_SET_CALL_CHECKER */
517 2           RETVAL = newSVpvs(
518             "/* DO NOT EDIT -- generated "
519             "by Devel::CallChecker version " XS_VERSION " */\n"
520             "#ifndef " Q_PFXS "INCLUDED\n"
521             "#define " Q_PFXS "INCLUDED 1\n"
522             "#ifndef PERL_VERSION\n"
523             " #error you must include perl.h before callchecker0.h\n"
524             "#elif !(PERL_REVISION == " STRINGIFY(PERL_REVISION)
525             " && PERL_VERSION == " STRINGIFY(PERL_VERSION)
526             Q_CODE_PERL_SUBVERSION_CRITERION ")\n"
527             " #error this callchecker0.h is for Perl "
528             STRINGIFY(PERL_REVISION) "." STRINGIFY(PERL_VERSION)
529             Q_TEXT_PERL_SUBVERSION_CRITERION " only\n"
530             "#endif /* Perl version mismatch */\n"
531             Q_CODE_PROVIDE_RV2CV_OP_CV
532             Q_CODE_PROVIDE_CK_ENTERSUB_ARGS_PROTO_OR_LIST
533             Q_CODE_PROVIDE_CV_SET_CALL_CHECKER
534             "#endif /* !" Q_PFXS "INCLUDED */\n"
535             );
536             OUTPUT:
537             RETVAL