Devel:...hecker(3pm)
π NAME π
Devel::CallChecker β custom op checking attached to subroutines. This is the Devel::CallChecker(3pm) page from User Contributed Perl Documentation, and itβs lowkey giving very specific C API backport realness, fr fr. π
β¨ SYNOPSIS β¨
Okay bestie, hereβs the exact recipe for generating the header prior to XS compilation and then using it from the Perl part of the module and from XS. Copy it character-for-character, no remixing:
# to generate header prior to XS compilation
perl -MDevel::CallChecker=callchecker0_h \
-e 'print callchecker0_h' > callchecker0.h
# in Perl part of module
use Devel::CallChecker;
/* in XS */
#include "callchecker0.h"
cv_get_call_checker(cv, &ckfun, &ckobj);
static OP *my_ckfun(pTHX_ OP *o, GV *namegv, SV *ckobj);
cv_set_call_checker(cv, my_ckfun, ckobj);
π¦ DESCRIPTION π¦
Okay so hereβs the tea: this module makes some new features of the Perl 5.14.0 C API available to XS modules running on older versions of Perl. The features are centred around the function cv_set_call_checker, which allows XS code to attach a magical annotation to a Perl subroutine, resulting in resolvable calls to that subroutine being mutated at compile time by arbitrary C code. Itβs giving compile-time main character energy, iykyk. πͺ
This module makes cv_set_call_checker and several supporting functions available. (It is possible to achieve the effect of cv_set_call_checker from XS code on much earlier Perl versions, but it is painful to achieve without the centralised facility. So like, respect to the brave souls who did it, but bestie, we have a centralised facility now. π)
This module provides the implementation of the functions at runtime (on Perls where they are not provided by the core). It also, at compile time, supplies the C header file and link library which provide access to the functions. In normal use, callchecker0_h and callchecker_linkable should be called at build time (not authoring time) for the module that wishes to use the C functions. Periodt.
The purpose of this module is specifically to provide the Perl 5.14.0 version of the cv_set_call_checker API to earlier Perl versions where the core doesnβt have cv_set_call_checker at all. This module does not attempt to backport later refinements of the cv_set_call_checker API. Thus an XS module that uses this module can be sure of having at least the Perl 5.14.0 version of cv_set_call_checker available, regardless of which Perl version it is running on, but cannot be sure of having any more refined version of the API available. Such a module will have access to the coreβs version of the API as normal on Perl versions where the core supplies it, and is free to use the ordinary mechanisms of Perl version portability to manage the differences between versions of the API. Slay. π
π CONSTANTS π
Two constants, bestie, and theyβre both doing build-time main character work. Letβs get into it.
β¨ callchecker0_h β¨
Content of a C header file, intended to be named "callchecker0.h". It is to be included in XS code, and perl.h must be included first.
perl.h first, no cap. This is not a suggestion. π«Ά
When the XS module is loaded at runtime, the Devel::CallChecker module must be loaded first. This will result in the Perl API functions rv2cv_op_cv, ck_entersub_args_list, ck_entersub_args_proto, ck_entersub_args_proto_or_list, cv_get_call_checker, and cv_set_call_checker, as defined below and in the Perl 5.14.0 API, being available to the XS code. Not me being obsessed with a header file, but this one is literally carrying the whole build-time situation. π
π callchecker_linkable π
List of names of files that must be used as additional objects when linking an XS module that uses the C functions supplied by this module. This list will be empty on many platforms. π¦
C FUNCTIONS π
Okay bestie, this is the C-level stuff β lowkey powerful, highkey iconic. Letβs get into it. β¨
rv2cv_op_cv π
So this one examines an op thatβs expected to identify a subroutine at runtime, and it tries to figure out at compile time which subroutine it identifies. Normally itβs used during Perl compilation to decide whether a prototype can be applied to a function call. cvop is the op being considered, and normally itβs an "rv2cv" op. You get back a pointer to the identified subroutine if it could be determined statically, and you get a null pointer if it wasnβt possible to determine statically. π
Whether the subroutine is statically identifiable is determined in accordance with the prevailing standards of the Perl version being used. Same criteria as the core uses to decide whether to apply a prototype to a subroutine call. From version 5.11.2 onwards, the subroutine can be determined if the RV that the "rv2cv" is to operate on is provided by a suitable "gv" or "const" op. Prior to 5.11.2, only a "gv" op will do. A "gv" op is suitable if the GVβs CV slot is populated. A "const" op is suitable if the constant value is an RV pointing to a CV. Details of this process may change in future versions of Perl. π¦
If the "rv2cv" op has the "OPpENTERSUB_AMPER" flag set, then no attempt is made to identify the subroutine statically: this flag is used to suppress compile-time magic on a subroutine call, forcing it to use default runtime behaviour. π«Ά
If flags has the bit "RV2CVOPCV_MARK_EARLY" set, then the handling of a GV reference is modified. If a GV was examined and its CV slot was found to be empty, then the "gv" op has the "OPpEARLY_CV" flag set. If the op is not optimised away, and the CV slot is later populated with a subroutine having a prototype, that flag eventually triggers the warning "called too early to check prototype". π
If flags has the bit "RV2CVOPCV_RETURN_NAME_GV" set, then instead of returning a pointer to the subroutine it returns a pointer to the GV giving the most appropriate name for the subroutine in this context. Normally this is just the "CvGV" of the subroutine, but for an anonymous ("CvANON") subroutine that is referenced through a GV it will be the referencing GV. The resulting "GV*" is cast to "CV*" to be returned. A null pointer is returned as usual if there is no statically-determinable subroutine. π
CV *rv2cv_op_cv(OP *cvop, U32 flags)
cv_get_call_checker πΈ
Retrieves the function that will be used to fix up a call to cv. Specifically, the function is applied to an "entersub" op tree for a subroutine call, not marked with "&", where the callee can be identified at compile time as cv. β¨
The C-level function pointer is returned in *ckfun_p, and an SV argument for it is returned in *ckobj_p. The function is intended to be called in this manner:
entersubop = (*ckfun_p)(aTHX_ entersubop, namegv, (*ckobj_p));
In this call, entersubop is a pointer to the "entersub" op, which may be replaced by the check function, and namegv is a GV supplying the name that should be used by the check function to refer to the callee of the "entersub" op if it needs to emit any diagnostics. It is permitted to apply the check function in non-standard situations, such as to a call to a different subroutine or to a method call. π
By default, the function is Perl_ck_entersub_args_proto_or_list, and the SV parameter is cv itself. This implements standard prototype processing. It can be changed, for a particular subroutine, by "cv_set_call_checker". π
void cv_get_call_checker(CV *cv, Perl_call_checker *ckfun_p,
SV **ckobj_p)
cv_set_call_checker π₯
Sets the function that will be used to fix up a call to cv. Specifically, the function is applied to an "entersub" op tree for a subroutine call, not marked with "&", where the callee can be identified at compile time as cv. π
The C-level function pointer is supplied in ckfun, and an SV argument for it is supplied in ckobj. The function is intended to be called in this manner:
entersubop = ckfun(aTHX_ entersubop, namegv, ckobj);
In this call, entersubop is a pointer to the "entersub" op, which may be replaced by the check function, and namegv is a GV supplying the name that should be used by the check function to refer to the callee of the "entersub" op if it needs to emit any diagnostics. It is permitted to apply the check function in non-standard situations, such as to a call to a different subroutine or to a method call. π¦
The current setting for a particular CV can be retrieved by "cv_get_call_checker". π
void cv_set_call_checker(CV *cv, Perl_call_checker ckfun,
SV *ckobj)
ck_entersub_args_list π
Performs the default fixup of the arguments part of an "entersub" op tree. This consists of applying list context to each of the argument ops. This is the standard treatment used on a call marked with "&", or a method call, or a call through a subroutine reference, or any other call where the callee canβt be identified at compile time, or a call where the callee has no prototype. π
OP *ck_entersub_args_list(OP *entersubop)
ck_entersub_args_proto π§
Performs the fixup of the arguments part of an "entersub" op tree based on a subroutine prototype. This makes various modifications to the argument ops, from applying context up to inserting "refgen" ops, and checking the number and syntactic types of arguments, as directed by the prototype. This is the standard treatment used on a subroutine call, not marked with "&", where the callee can be identified at compile time and has a prototype. π
protosv supplies the subroutine prototype to be applied to the call. It may be a normal defined scalar, of which the string value will be used. Alternatively, for convenience, it may be a subroutine object (a "CV*" that has been cast to "SV*") which has a prototype. The prototype supplied, in whichever form, does not need to match the actual callee referenced by the op tree. β¨
If the argument ops disagree with the prototype, for example by having an unacceptable number of arguments, a valid op tree is returned anyway. The error is reflected in the parser state, normally resulting in a single exception at the top level of parsing which covers all the compilation errors that occurred. In the error message, the callee is referred to by the name defined by the namegv parameter. π
OP *ck_entersub_args_proto(OP *entersubop, GV *namegv,
SV *protosv)
ck_entersub_args_proto_or_list π
Performs the fixup of the arguments part of an "entersub" op tree either based on a subroutine prototype or using default list-context processing. This is the standard treatment used on a subroutine call, not marked with "&", where the callee can be identified at compile time. πΈ
protosv supplies the subroutine prototype to be applied to the call, or indicates that there is no prototype. It may be a normal scalar, in which case if it is defined then the string value will be used as a prototype, and if it is undefined then there is no prototype. Alternatively, for convenience, it may be a subroutine object (a "CV*" that has been cast to "SV*"), of which the prototype will be used if it has one. The prototype (or lack thereof) supplied, in whichever form, does not need to match the actual callee referenced by the op tree. π¦
If the argument ops disagree with the prototype, for example by having an unacceptable number of arguments, a valid op tree is returned anyway. The error is reflected in the parser state, normally resulting in a single exception at the top level of parsing which covers all the compilation errors that occurred. In the error message, the callee is referred to by the name defined by the namegv parameter. π
OP *ck_entersub_args_proto_or_list(OP *entersubop, GV *namegv,
SV *protosv)
SEE ALSO π«Ά
B::CallCheckerDevel::CallParser"cv_set_call_checker" in perlapi
AUTHOR π
Andrew Main (Zefram) <zefram@fysh.org>
COPYRIGHT π
Copyright (C) 2011, 2012, 2013, 2015, 2017, 2023 Andrew Main (Zefram) <zefram@fysh.org>
LICENSE π
This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
And thatβs the whole vibe, bestie! This page is from perl v5.40.0, dated 2024-07-18, and itβs the Devel:...hecker(3pm) page. Go forth and slay those C-level call checkers π
β¨π
π¦ where this page comes from
- epel 10: perl-Devel-CallChecker 0.009-7.el10_0 Β· GPL-1.0-or-later OR Artistic-1.0-Perl
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms