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 4 |
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
|
|
|
|
|
|
|
|
31
|
|
|
|
|
|
|
/* Back-compat flags we hope to remove in the next ABI version */ |
32
|
|
|
|
|
|
|
XS_PARSE_SUBLIKE_COMPAT_FLAG_DYNAMIC_ACTIONS = 1<<15, |
33
|
|
|
|
|
|
|
}; |
34
|
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
enum { |
36
|
|
|
|
|
|
|
XS_PARSE_SUBLIKE_PART_NAME = 1<<0, |
37
|
|
|
|
|
|
|
XS_PARSE_SUBLIKE_PART_ATTRS = 1<<1, |
38
|
|
|
|
|
|
|
XS_PARSE_SUBLIKE_PART_SIGNATURE = 1<<2, |
39
|
|
|
|
|
|
|
XS_PARSE_SUBLIKE_PART_BODY = 1<<3, |
40
|
|
|
|
|
|
|
}; |
41
|
|
|
|
|
|
|
|
42
|
|
|
|
|
|
|
enum { |
43
|
|
|
|
|
|
|
XS_PARSE_SUBLIKE_ACTION_CVf_ANON = (1<<0), /* should start_subparse() take CVf_ANON ? */ |
44
|
|
|
|
|
|
|
XS_PARSE_SUBLIKE_ACTION_SET_CVNAME = (1<<1), /* do we set a CvNAME? */ |
45
|
|
|
|
|
|
|
XS_PARSE_SUBLIKE_ACTION_INSTALL_SYMBOL = (1<<2), /* do we install the new CV into the symbol table? */ |
46
|
|
|
|
|
|
|
XS_PARSE_SUBLIKE_ACTION_REFGEN_ANONCODE = (1<<3), /* do we emit OP_REFGEN of OP_ANONCODE, or simply OP_NULL ? */ |
47
|
|
|
|
|
|
|
XS_PARSE_SUBLIKE_ACTION_RET_EXPR = (1<<4), /* do we return KEYWORD_PLUGIN_EXPR, or KEYWORD_PLUGIN_STMT ? */ |
48
|
|
|
|
|
|
|
}; |
49
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
struct XSParseSublikeHooks { |
51
|
|
|
|
|
|
|
U16 flags; |
52
|
|
|
|
|
|
|
U8 require_parts; |
53
|
|
|
|
|
|
|
U8 skip_parts; |
54
|
|
|
|
|
|
|
|
55
|
|
|
|
|
|
|
/* These two hooks are ANDed together; both must pass, if present */ |
56
|
|
|
|
|
|
|
const char *permit_hintkey; |
57
|
|
|
|
|
|
|
bool (*permit)(pTHX_ void *hookdata); |
58
|
|
|
|
|
|
|
|
59
|
|
|
|
|
|
|
void (*pre_subparse) (pTHX_ struct XSParseSublikeContext *ctx, void *hookdata); |
60
|
|
|
|
|
|
|
void (*post_blockstart)(pTHX_ struct XSParseSublikeContext *ctx, void *hookdata); |
61
|
|
|
|
|
|
|
void (*pre_blockend) (pTHX_ struct XSParseSublikeContext *ctx, void *hookdata); |
62
|
|
|
|
|
|
|
void (*post_newcv) (pTHX_ struct XSParseSublikeContext *ctx, void *hookdata); |
63
|
|
|
|
|
|
|
|
64
|
|
|
|
|
|
|
/* if flags & XS_PARSE_SUBLIKE_FLAG_FILTERATTRS */ |
65
|
|
|
|
|
|
|
bool (*filter_attr) (pTHX_ struct XSParseSublikeContext *ctx, SV *attr, SV *val, void *hookdata); |
66
|
|
|
|
|
|
|
}; |
67
|
|
|
|
|
|
|
|
68
|
|
|
|
|
|
|
static int (*parse_xs_parse_sublike_func)(pTHX_ const struct XSParseSublikeHooks *hooks, void *hookdata, OP **op_ptr); |
69
|
|
|
|
|
|
|
#define xs_parse_sublike(hooks, hookdata, op_ptr) S_xs_parse_sublike(aTHX_ hooks, hookdata, op_ptr) |
70
|
|
|
|
|
|
|
static int S_xs_parse_sublike(pTHX_ const struct XSParseSublikeHooks *hooks, void *hookdata, OP **op_ptr) |
71
|
|
|
|
|
|
|
{ |
72
|
|
|
|
|
|
|
if(!parse_xs_parse_sublike_func) |
73
|
|
|
|
|
|
|
croak("Must call boot_xs_parse_sublike() first"); |
74
|
|
|
|
|
|
|
|
75
|
|
|
|
|
|
|
return (*parse_xs_parse_sublike_func)(aTHX_ hooks, hookdata, op_ptr); |
76
|
|
|
|
|
|
|
} |
77
|
|
|
|
|
|
|
|
78
|
|
|
|
|
|
|
static void (*register_xs_parse_sublike_func)(pTHX_ const char *kw, const struct XSParseSublikeHooks *hooks, void *hookdata); |
79
|
|
|
|
|
|
|
#define register_xs_parse_sublike(kw, hooks, hookdata) S_register_xs_parse_sublike(aTHX_ kw, hooks, hookdata) |
80
|
|
|
|
|
|
|
static void S_register_xs_parse_sublike(pTHX_ const char *kw, const struct XSParseSublikeHooks *hooks, void *hookdata) |
81
|
|
|
|
|
|
|
{ |
82
|
2
|
50
|
|
|
|
|
if(!register_xs_parse_sublike_func) |
83
|
0
|
|
|
|
|
|
croak("Must call boot_xs_parse_sublike() first"); |
84
|
|
|
|
|
|
|
|
85
|
2
|
|
|
|
|
|
return (*register_xs_parse_sublike_func)(aTHX_ kw, hooks, hookdata); |
86
|
|
|
|
|
|
|
} |
87
|
|
|
|
|
|
|
|
88
|
|
|
|
|
|
|
static int (*parseany_xs_parse_sublike_func)(pTHX_ const struct XSParseSublikeHooks *hooks, void *hookdata, OP **op_ptr); |
89
|
|
|
|
|
|
|
#define xs_parse_sublike_any(hooks, hookdata, op_ptr) S_xs_parse_sublike_any(aTHX_ hooks, hookdata, op_ptr) |
90
|
|
|
|
|
|
|
static int S_xs_parse_sublike_any(pTHX_ const struct XSParseSublikeHooks *hooks, void *hookdata, OP **op_ptr) |
91
|
|
|
|
|
|
|
{ |
92
|
|
|
|
|
|
|
if(!parseany_xs_parse_sublike_func) |
93
|
|
|
|
|
|
|
croak("Must call boot_xs_parse_sublike() first"); |
94
|
|
|
|
|
|
|
|
95
|
|
|
|
|
|
|
return (*parseany_xs_parse_sublike_func)(aTHX_ hooks, hookdata, op_ptr); |
96
|
|
|
|
|
|
|
} |
97
|
|
|
|
|
|
|
|
98
|
|
|
|
|
|
|
#define boot_xs_parse_sublike(ver) S_boot_xs_parse_sublike(aTHX_ ver) |
99
|
2
|
|
|
|
|
|
static void S_boot_xs_parse_sublike(pTHX_ double ver) { |
100
|
|
|
|
|
|
|
SV **svp; |
101
|
2
|
50
|
|
|
|
|
SV *versv = ver ? newSVnv(ver) : NULL; |
102
|
|
|
|
|
|
|
|
103
|
2
|
|
|
|
|
|
load_module(PERL_LOADMOD_NOIMPORT, newSVpvs("XS::Parse::Sublike"), versv, NULL); |
104
|
|
|
|
|
|
|
|
105
|
2
|
|
|
|
|
|
svp = hv_fetchs(PL_modglobal, "XS::Parse::Sublike/ABIVERSION_MIN", 0); |
106
|
2
|
50
|
|
|
|
|
if(!svp) |
107
|
0
|
|
|
|
|
|
croak("XS::Parse::Sublike ABI minimum version missing"); |
108
|
2
|
50
|
|
|
|
|
int abi_ver = SvIV(*svp); |
109
|
2
|
50
|
|
|
|
|
if(abi_ver > XSPARSESUBLIKE_ABI_VERSION) |
110
|
0
|
|
|
|
|
|
croak("XS::Parse::Sublike ABI version mismatch - library supports >= %d, compiled for %d", |
111
|
|
|
|
|
|
|
abi_ver, XSPARSESUBLIKE_ABI_VERSION); |
112
|
|
|
|
|
|
|
|
113
|
2
|
|
|
|
|
|
svp = hv_fetchs(PL_modglobal, "XS::Parse::Sublike/ABIVERSION_MAX", 0); |
114
|
2
|
50
|
|
|
|
|
abi_ver = SvIV(*svp); |
115
|
2
|
50
|
|
|
|
|
if(abi_ver < XSPARSESUBLIKE_ABI_VERSION) |
116
|
0
|
|
|
|
|
|
croak("XS::Parse::Sublike ABI version mismatch - library supports <= %d, compiled for %d", |
117
|
|
|
|
|
|
|
abi_ver, XSPARSESUBLIKE_ABI_VERSION); |
118
|
|
|
|
|
|
|
|
119
|
2
|
50
|
|
|
|
|
parse_xs_parse_sublike_func = INT2PTR(int (*)(pTHX_ const struct XSParseSublikeHooks *, void *, OP**), |
120
|
|
|
|
|
|
|
SvUV(*hv_fetchs(PL_modglobal, "XS::Parse::Sublike/parse()@4", 0))); |
121
|
|
|
|
|
|
|
|
122
|
2
|
50
|
|
|
|
|
register_xs_parse_sublike_func = INT2PTR(void (*)(pTHX_ const char *, const struct XSParseSublikeHooks *, void *), |
123
|
|
|
|
|
|
|
SvUV(*hv_fetchs(PL_modglobal, "XS::Parse::Sublike/register()@4", 0))); |
124
|
|
|
|
|
|
|
|
125
|
2
|
50
|
|
|
|
|
parseany_xs_parse_sublike_func = INT2PTR(int (*)(pTHX_ const struct XSParseSublikeHooks *, void *, OP**), |
126
|
|
|
|
|
|
|
SvUV(*hv_fetchs(PL_modglobal, "XS::Parse::Sublike/parseany()@4", 0))); |
127
|
2
|
|
|
|
|
|
} |
128
|
|
|
|
|
|
|
|
129
|
|
|
|
|
|
|
#endif |