File Coverage

/usr/local/lib/perl5/site_perl/5.42.0/x86_64-linux/auto/share/module/XS-Parse-Sublike/include/XSParseSublike.h
Criterion Covered Total %
statement 20 24 83.3
branch 5 10 50.0
condition n/a
subroutine n/a
pod n/a
total 25 34 73.5


line stmt bran cond sub pod time code
1             #ifndef __XS_PARSE_SUBLIKE_H__
2             #define __XS_PARSE_SUBLIKE_H__
3              
4             #define XSPARSESUBLIKE_ABI_VERSION 8
5              
6             struct XSParseSublikeContext {
7             SV *name; /* may be NULL for anon subs */
8             /* STAGE pre_subparse */
9             OP *attrs; /* may be NULL */
10             /* STAGE post_blockstart */
11             OP *body;
12             /* STAGE pre_blockend */
13             CV *cv;
14             /* STAGE post_newcv */
15              
16             U32 actions;
17              
18             /* Unused by XS::Parse::Sublike itself but can be handy for modules to store
19             * data in between stages */
20             HV *moddata;
21             };
22              
23             enum {
24             XS_PARSE_SUBLIKE_FLAG_FILTERATTRS = 1<<0, /* API v4 flag, no longer used */
25             XS_PARSE_SUBLIKE_FLAG_BODY_OPTIONAL = 1<<1,
26             XS_PARSE_SUBLIKE_FLAG_PREFIX = 1<<2,
27              
28             XS_PARSE_SUBLIKE_FLAG_SIGNATURE_NAMED_PARAMS = 1<<3,
29             XS_PARSE_SUBLIKE_FLAG_SIGNATURE_PARAM_ATTRIBUTES = 1<<4,
30              
31             XS_PARSE_SUBLIKE_FLAG_ALLOW_PKGNAME = 1<<5,
32              
33             XS_PARSE_SUBLIKE_FLAG_SIGNATURE_REFALIAS = 1<<6,
34              
35             /* Back-compat flags we hope to remove in the next ABI version */
36             XS_PARSE_SUBLIKE_COMPAT_FLAG_DYNAMIC_ACTIONS = 1<<15,
37             };
38              
39             enum {
40             XS_PARSE_SUBLIKE_PART_NAME = 1<<0,
41             XS_PARSE_SUBLIKE_PART_ATTRS = 1<<1,
42             XS_PARSE_SUBLIKE_PART_SIGNATURE = 1<<2,
43             XS_PARSE_SUBLIKE_PART_BODY = 1<<3,
44             };
45              
46             enum {
47             XS_PARSE_SUBLIKE_ACTION_CVf_ANON = (1<<0), /* should start_subparse() take CVf_ANON ? */
48             XS_PARSE_SUBLIKE_ACTION_SET_CVNAME = (1<<1), /* do we set a CvNAME? */
49             XS_PARSE_SUBLIKE_ACTION_INSTALL_SYMBOL = (1<<2), /* do we install the new CV into the symbol table? */
50             XS_PARSE_SUBLIKE_ACTION_REFGEN_ANONCODE = (1<<3), /* do we emit OP_REFGEN of OP_ANONCODE, or simply OP_NULL ? */
51             XS_PARSE_SUBLIKE_ACTION_RET_EXPR = (1<<4), /* do we return KEYWORD_PLUGIN_EXPR, or KEYWORD_PLUGIN_STMT ? */
52             XS_PARSE_SUBLIKE_ACTION_INSTALL_LEXICAL = (1<<5), /* do we install the new CV into the current lexical pad? (Perl 5.18+) */
53             };
54              
55             struct XSParseSublikeHooks {
56             U32 ver; /* caller must initialise to XSPARSESUBLIKE_ABI_VERSION */
57             U16 flags;
58             U8 require_parts;
59             U8 skip_parts;
60              
61             /* These two hooks are ANDed together; both must pass, if present */
62             const char *permit_hintkey;
63             bool (*permit)(pTHX_ void *hookdata);
64              
65             void (*pre_subparse) (pTHX_ struct XSParseSublikeContext *ctx, void *hookdata);
66             bool (*filter_attr) (pTHX_ struct XSParseSublikeContext *ctx, SV *attr, SV *val, void *hookdata);
67             void (*post_blockstart)(pTHX_ struct XSParseSublikeContext *ctx, void *hookdata);
68             void (*pre_blockend) (pTHX_ struct XSParseSublikeContext *ctx, void *hookdata);
69             void (*post_newcv) (pTHX_ struct XSParseSublikeContext *ctx, void *hookdata);
70              
71             /* if ver >= 7: */
72             void (*start_signature) (pTHX_ struct XSParseSublikeContext *ctx, void *hookdata);
73             void (*finish_signature)(pTHX_ struct XSParseSublikeContext *ctx, void *hookdata);
74             };
75              
76             static int (*parse_xs_parse_sublike_func)(pTHX_ const struct XSParseSublikeHooks *hooks, void *hookdata, OP **op_ptr);
77             #define xs_parse_sublike(hooks, hookdata, op_ptr) S_xs_parse_sublike(aTHX_ hooks, hookdata, op_ptr)
78             static int S_xs_parse_sublike(pTHX_ const struct XSParseSublikeHooks *hooks, void *hookdata, OP **op_ptr)
79             {
80             if(!parse_xs_parse_sublike_func)
81             croak("Must call boot_xs_parse_sublike() first");
82              
83             return (*parse_xs_parse_sublike_func)(aTHX_ hooks, hookdata, op_ptr);
84             }
85              
86             static void (*register_xs_parse_sublike_func)(pTHX_ const char *kw, const struct XSParseSublikeHooks *hooks, void *hookdata);
87             #define register_xs_parse_sublike(kw, hooks, hookdata) S_register_xs_parse_sublike(aTHX_ kw, hooks, hookdata)
88 48           static void S_register_xs_parse_sublike(pTHX_ const char *kw, const struct XSParseSublikeHooks *hooks, void *hookdata)
89             {
90 48 50         if(!register_xs_parse_sublike_func)
91 0           croak("Must call boot_xs_parse_sublike() first");
92              
93 48           return (*register_xs_parse_sublike_func)(aTHX_ kw, hooks, hookdata);
94             }
95              
96             static int (*parseany_xs_parse_sublike_func)(pTHX_ const struct XSParseSublikeHooks *hooks, void *hookdata, OP **op_ptr);
97             #define xs_parse_sublike_any(hooks, hookdata, op_ptr) S_xs_parse_sublike_any(aTHX_ hooks, hookdata, op_ptr)
98             static int S_xs_parse_sublike_any(pTHX_ const struct XSParseSublikeHooks *hooks, void *hookdata, OP **op_ptr)
99             {
100             if(!parseany_xs_parse_sublike_func)
101             croak("Must call boot_xs_parse_sublike() first");
102              
103             return (*parseany_xs_parse_sublike_func)(aTHX_ hooks, hookdata, op_ptr);
104             }
105              
106             /* arguments to the signature_add_param function */
107             struct XPSSignatureParamDetails {
108             U32 ver; /* caller must initialise to XSPARSESUBLIKE_ABI_VERSION */
109              
110             /* TODO: Right now this is entirely ABI-unstable and prone to change between versions
111             * For now this can only add mandatory positional scalar, or final slurpy
112             * params whose pad variable has already been declared, and that have no
113             * attributes attached.
114             */
115             char sigil;
116             PADOFFSET padix;
117             };
118              
119             static void (*signature_add_param_func)(pTHX_ struct XSParseSublikeContext *ctx, struct XPSSignatureParamDetails *details);
120             #define xps_signature_add_param(ctx, details) S_xps_signature_add_param(aTHX_ ctx, details)
121             static void S_xps_signature_add_param(pTHX_ struct XSParseSublikeContext *ctx, struct XPSSignatureParamDetails *details)
122             {
123             if(!signature_add_param_func)
124             croak("Must call boot_xs_parse_sublike() first");
125              
126             (*signature_add_param_func)(aTHX_ ctx, details);
127             }
128              
129             /* Easier to define one query function that takes a `q` parameter, that
130             * indicates which question we are asking. This saves us having to export
131             * lots of functions. This is internal implementation detail, not exposed
132             * API.
133             */
134             static IV (*signature_query_func)(pTHX_ struct XSParseSublikeContext *ctx, int q);
135             #define xps_signature_query_params(ctx) S_xps_signature_query(aTHX_ ctx, 0)
136             #define xps_signature_query_optparams(ctx) S_xps_signature_query(aTHX_ ctx, 1)
137             #define xps_signature_query_slurpy(ctx) ((char)S_xps_signature_query(aTHX_ ctx, 2))
138             static IV S_xps_signature_query(pTHX_ struct XSParseSublikeContext *ctx, int q)
139             {
140             if(!signature_query_func)
141             croak("Must call boot_xs_parse_sublike() first");
142              
143             return (*signature_query_func)(aTHX_ ctx, q);
144             }
145              
146             /* Experimental support for subroutine parameter attributes.
147             * Only supported on Perl v5.26 or later
148             */
149              
150             struct XPSSignatureParamContext {
151             bool is_named;
152             PADOFFSET padix;
153             OP *varop;
154             /* apply phase runs here */
155             OP *defop;
156             OP *op;
157             /* post_defop phase runs here */
158              
159             /* TODO: in next ABI-breaking change, move this to the top */
160             char sigil;
161             const char *namepv;
162             STRLEN namelen;
163              
164             bool is_refalias;
165             };
166              
167             struct XPSSignatureAttributeFuncs {
168             U32 ver; /* caller must initialise to XSPARSESUBLIKE_ABI_VERSION */
169             U32 flags;
170             const char *permit_hintkey;
171              
172             void (*apply)(pTHX_ struct XPSSignatureParamContext *ctx, SV *attrvalue, void **attrdata_ptr, void *funcdata);
173             void (*post_defop)(pTHX_ struct XPSSignatureParamContext *ctx, void *attrdata, void *funcdata);
174              
175             void (*free)(pTHX_ void *attrdata, void *funcdata);
176             };
177              
178             static void (*register_xps_signature_attribute_func)(pTHX_ const char *name, const struct XPSSignatureAttributeFuncs *funcs, void *funcdata);
179             #define register_xps_signature_attribute(name, funcs, funcdata) S_register_xps_signature_attribute(aTHX_ name, funcs, funcdata)
180             static void S_register_xps_signature_attribute(pTHX_ const char *name, const struct XPSSignatureAttributeFuncs *funcs, void *funcdata)
181             {
182             if(!register_xps_signature_attribute_func)
183             croak("Must call boot_xs_parse_sublike() first");
184              
185             (*register_xps_signature_attribute_func)(aTHX_ name, funcs, funcdata);
186             }
187              
188              
189             #define boot_xs_parse_sublike(ver) S_boot_xs_parse_sublike(aTHX_ ver)
190 48           static void S_boot_xs_parse_sublike(pTHX_ double ver) {
191             SV **svp;
192 48 50         SV *versv = ver ? newSVnv(ver) : NULL;
193              
194 48           load_module(PERL_LOADMOD_NOIMPORT, newSVpvs("XS::Parse::Sublike"), versv, NULL);
195              
196 48           svp = hv_fetchs(PL_modglobal, "XS::Parse::Sublike/ABIVERSION_MIN", 0);
197 48 50         if(!svp)
198 0           croak("XS::Parse::Sublike ABI minimum version missing");
199 48           int abi_ver = SvIV(*svp);
200 48 50         if(abi_ver > XSPARSESUBLIKE_ABI_VERSION)
201 0           croak("XS::Parse::Sublike ABI version mismatch - library supports >= %d, compiled for %d",
202             abi_ver, XSPARSESUBLIKE_ABI_VERSION);
203              
204 48           svp = hv_fetchs(PL_modglobal, "XS::Parse::Sublike/ABIVERSION_MAX", 0);
205 48           abi_ver = SvIV(*svp);
206 48 50         if(abi_ver < XSPARSESUBLIKE_ABI_VERSION)
207 0           croak("XS::Parse::Sublike ABI version mismatch - library supports <= %d, compiled for %d",
208             abi_ver, XSPARSESUBLIKE_ABI_VERSION);
209              
210 48           parse_xs_parse_sublike_func = INT2PTR(int (*)(pTHX_ const struct XSParseSublikeHooks *, void *, OP**),
211             SvUV(*hv_fetchs(PL_modglobal, "XS::Parse::Sublike/parse()@6", 0)));
212              
213 48           register_xs_parse_sublike_func = INT2PTR(void (*)(pTHX_ const char *, const struct XSParseSublikeHooks *, void *),
214             SvUV(*hv_fetchs(PL_modglobal, "XS::Parse::Sublike/register()@6", 0)));
215              
216 48           parseany_xs_parse_sublike_func = INT2PTR(int (*)(pTHX_ const struct XSParseSublikeHooks *, void *, OP**),
217             SvUV(*hv_fetchs(PL_modglobal, "XS::Parse::Sublike/parseany()@6", 0)));
218              
219 48           register_xps_signature_attribute_func = INT2PTR(void (*)(pTHX_ const char *, const struct XPSSignatureAttributeFuncs *, void *),
220             SvUV(*hv_fetchs(PL_modglobal, "XS::Parse::Sublike/register_sigattr()@5", 0)));
221              
222 48           signature_add_param_func = INT2PTR(void (*)(pTHX_ struct XSParseSublikeContext *ctx, struct XPSSignatureParamDetails *details),
223             SvUV(*hv_fetchs(PL_modglobal, "XS::Parse::Sublike/signature_add_param()@7", 0)));
224              
225 48           signature_query_func = INT2PTR(IV (*)(pTHX_ struct XSParseSublikeContext *ctx, int q),
226             SvUV(*hv_fetchs(PL_modglobal, "XS::Parse::Sublike/signature_query()@8", 0)));
227 48           }
228              
229             #endif