File Coverage

XSParseSublike.h
Criterion Covered Total %
statement 17 21 80.9
branch 11 22 50.0
condition n/a
subroutine n/a
pod n/a
total 28 43 65.1


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 5
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,
25             XS_PARSE_SUBLIKE_FLAG_BODY_OPTIONAL = 1<<1,
26             XS_PARSE_SUBLIKE_FLAG_PREFIX = 1<<2,
27              
28             /* *Experimental* named parameter parsing support */
29             XS_PARSE_SUBLIKE_FLAG_SIGNATURE_NAMED_PARAMS = 1<<3,
30             /* *Experimental* parameter attribute parsing support */
31             XS_PARSE_SUBLIKE_FLAG_SIGNATURE_PARAM_ATTRIBUTES = 1<<4,
32              
33             /* Back-compat flags we hope to remove in the next ABI version */
34             XS_PARSE_SUBLIKE_COMPAT_FLAG_DYNAMIC_ACTIONS = 1<<15,
35             };
36              
37             enum {
38             XS_PARSE_SUBLIKE_PART_NAME = 1<<0,
39             XS_PARSE_SUBLIKE_PART_ATTRS = 1<<1,
40             XS_PARSE_SUBLIKE_PART_SIGNATURE = 1<<2,
41             XS_PARSE_SUBLIKE_PART_BODY = 1<<3,
42             };
43              
44             enum {
45             XS_PARSE_SUBLIKE_ACTION_CVf_ANON = (1<<0), /* should start_subparse() take CVf_ANON ? */
46             XS_PARSE_SUBLIKE_ACTION_SET_CVNAME = (1<<1), /* do we set a CvNAME? */
47             XS_PARSE_SUBLIKE_ACTION_INSTALL_SYMBOL = (1<<2), /* do we install the new CV into the symbol table? */
48             XS_PARSE_SUBLIKE_ACTION_REFGEN_ANONCODE = (1<<3), /* do we emit OP_REFGEN of OP_ANONCODE, or simply OP_NULL ? */
49             XS_PARSE_SUBLIKE_ACTION_RET_EXPR = (1<<4), /* do we return KEYWORD_PLUGIN_EXPR, or KEYWORD_PLUGIN_STMT ? */
50             };
51              
52             struct XSParseSublikeHooks {
53             U16 flags;
54             U8 require_parts;
55             U8 skip_parts;
56              
57             /* These two hooks are ANDed together; both must pass, if present */
58             const char *permit_hintkey;
59             bool (*permit)(pTHX_ void *hookdata);
60              
61             void (*pre_subparse) (pTHX_ struct XSParseSublikeContext *ctx, void *hookdata);
62             void (*post_blockstart)(pTHX_ struct XSParseSublikeContext *ctx, void *hookdata);
63             void (*pre_blockend) (pTHX_ struct XSParseSublikeContext *ctx, void *hookdata);
64             void (*post_newcv) (pTHX_ struct XSParseSublikeContext *ctx, void *hookdata);
65              
66             /* if flags & XS_PARSE_SUBLIKE_FLAG_FILTERATTRS */
67             bool (*filter_attr) (pTHX_ struct XSParseSublikeContext *ctx, SV *attr, SV *val, void *hookdata);
68             };
69              
70             static int (*parse_xs_parse_sublike_func)(pTHX_ const struct XSParseSublikeHooks *hooks, void *hookdata, OP **op_ptr);
71             #define xs_parse_sublike(hooks, hookdata, op_ptr) S_xs_parse_sublike(aTHX_ hooks, hookdata, op_ptr)
72             static int S_xs_parse_sublike(pTHX_ const struct XSParseSublikeHooks *hooks, void *hookdata, OP **op_ptr)
73             {
74             if(!parse_xs_parse_sublike_func)
75             croak("Must call boot_xs_parse_sublike() first");
76              
77             return (*parse_xs_parse_sublike_func)(aTHX_ hooks, hookdata, op_ptr);
78             }
79              
80             static void (*register_xs_parse_sublike_func)(pTHX_ const char *kw, const struct XSParseSublikeHooks *hooks, void *hookdata);
81             #define register_xs_parse_sublike(kw, hooks, hookdata) S_register_xs_parse_sublike(aTHX_ kw, hooks, hookdata)
82             static void S_register_xs_parse_sublike(pTHX_ const char *kw, const struct XSParseSublikeHooks *hooks, void *hookdata)
83             {
84 45 50         if(!register_xs_parse_sublike_func)
85 0           croak("Must call boot_xs_parse_sublike() first");
86              
87 45           return (*register_xs_parse_sublike_func)(aTHX_ kw, hooks, hookdata);
88             }
89              
90             static int (*parseany_xs_parse_sublike_func)(pTHX_ const struct XSParseSublikeHooks *hooks, void *hookdata, OP **op_ptr);
91             #define xs_parse_sublike_any(hooks, hookdata, op_ptr) S_xs_parse_sublike_any(aTHX_ hooks, hookdata, op_ptr)
92             static int S_xs_parse_sublike_any(pTHX_ const struct XSParseSublikeHooks *hooks, void *hookdata, OP **op_ptr)
93             {
94             if(!parseany_xs_parse_sublike_func)
95             croak("Must call boot_xs_parse_sublike() first");
96              
97             return (*parseany_xs_parse_sublike_func)(aTHX_ hooks, hookdata, op_ptr);
98             }
99              
100              
101             /* Experimental support for subroutine parameter attributes.
102             * Only supported on Perl v5.26 or later
103             */
104              
105             struct XPSSignatureParamContext {
106             bool is_named;
107             PADOFFSET padix;
108             OP *varop;
109             /* apply phase runs here */
110             OP *defop;
111             OP *op;
112             /* post_defop phase runs here */
113             };
114              
115             struct XPSSignatureAttributeFuncs {
116             U32 ver; /* caller must initialise to XSPARSESUBLIKE_ABI_VERSION */
117             U32 flags;
118             const char *permit_hintkey;
119              
120             void (*apply)(pTHX_ struct XPSSignatureParamContext *ctx, SV *attrvalue, void **attrdata_ptr, void *funcdata);
121             void (*post_defop)(pTHX_ struct XPSSignatureParamContext *ctx, void *attrdata, void *funcdata);
122              
123             void (*free)(pTHX_ void *attrdata, void *funcdata);
124             };
125              
126             static void (*register_xps_signature_attribute_func)(pTHX_ const char *name, const struct XPSSignatureAttributeFuncs *funcs, void *funcdata);
127             #define register_xps_signature_attribute(name, funcs, funcdata) S_register_xps_signature_attribute(aTHX_ name, funcs, funcdata)
128             static void S_register_xps_signature_attribute(pTHX_ const char *name, const struct XPSSignatureAttributeFuncs *funcs, void *funcdata)
129             {
130             if(!register_xps_signature_attribute_func)
131             croak("Must call boot_xs_parse_sublike() first");
132              
133             (*register_xps_signature_attribute_func)(aTHX_ name, funcs, funcdata);
134             }
135              
136              
137             #define boot_xs_parse_sublike(ver) S_boot_xs_parse_sublike(aTHX_ ver)
138 45           static void S_boot_xs_parse_sublike(pTHX_ double ver) {
139             SV **svp;
140 45 50         SV *versv = ver ? newSVnv(ver) : NULL;
141              
142 45           load_module(PERL_LOADMOD_NOIMPORT, newSVpvs("XS::Parse::Sublike"), versv, NULL);
143              
144 45           svp = hv_fetchs(PL_modglobal, "XS::Parse::Sublike/ABIVERSION_MIN", 0);
145 45 50         if(!svp)
146 0           croak("XS::Parse::Sublike ABI minimum version missing");
147 45 50         int abi_ver = SvIV(*svp);
148 45 50         if(abi_ver > XSPARSESUBLIKE_ABI_VERSION)
149 0           croak("XS::Parse::Sublike ABI version mismatch - library supports >= %d, compiled for %d",
150             abi_ver, XSPARSESUBLIKE_ABI_VERSION);
151              
152 45           svp = hv_fetchs(PL_modglobal, "XS::Parse::Sublike/ABIVERSION_MAX", 0);
153 45 50         abi_ver = SvIV(*svp);
154 45 50         if(abi_ver < XSPARSESUBLIKE_ABI_VERSION)
155 0           croak("XS::Parse::Sublike ABI version mismatch - library supports <= %d, compiled for %d",
156             abi_ver, XSPARSESUBLIKE_ABI_VERSION);
157              
158 45 50         parse_xs_parse_sublike_func = INT2PTR(int (*)(pTHX_ const struct XSParseSublikeHooks *, void *, OP**),
159             SvUV(*hv_fetchs(PL_modglobal, "XS::Parse::Sublike/parse()@4", 0)));
160              
161 45 50         register_xs_parse_sublike_func = INT2PTR(void (*)(pTHX_ const char *, const struct XSParseSublikeHooks *, void *),
162             SvUV(*hv_fetchs(PL_modglobal, "XS::Parse::Sublike/register()@4", 0)));
163              
164 45 50         parseany_xs_parse_sublike_func = INT2PTR(int (*)(pTHX_ const struct XSParseSublikeHooks *, void *, OP**),
165             SvUV(*hv_fetchs(PL_modglobal, "XS::Parse::Sublike/parseany()@4", 0)));
166              
167 45 50         register_xps_signature_attribute_func = INT2PTR(void (*)(pTHX_ const char *, const struct XPSSignatureAttributeFuncs *, void *),
168             SvUV(*hv_fetchs(PL_modglobal, "XS::Parse::Sublike/register_sigattr()@5", 0)));
169 45           }
170              
171             #endif