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 "callchecker0.h" |
5
|
|
|
|
|
|
|
#include "XSUB.h" |
6
|
|
|
|
|
|
|
|
7
|
|
|
|
|
|
|
#define PERL_VERSION_DECIMAL(r,v,s) (r*1000000 + v*1000 + s) |
8
|
|
|
|
|
|
|
#define PERL_DECIMAL_VERSION \ |
9
|
|
|
|
|
|
|
PERL_VERSION_DECIMAL(PERL_REVISION,PERL_VERSION,PERL_SUBVERSION) |
10
|
|
|
|
|
|
|
#define PERL_VERSION_GE(r,v,s) \ |
11
|
|
|
|
|
|
|
(PERL_DECIMAL_VERSION >= PERL_VERSION_DECIMAL(r,v,s)) |
12
|
|
|
|
|
|
|
|
13
|
|
|
|
|
|
|
#ifndef op_append_elem |
14
|
|
|
|
|
|
|
# define op_append_elem(t, f, l) THX_op_append_elem(aTHX_ t, f, l) |
15
|
|
|
|
|
|
|
static OP *THX_op_append_elem(pTHX_ I32 type, OP *first, OP *last) |
16
|
|
|
|
|
|
|
{ |
17
|
|
|
|
|
|
|
if(!first) return last; |
18
|
|
|
|
|
|
|
if(!last) return first; |
19
|
|
|
|
|
|
|
if(first->op_type != (unsigned)type || |
20
|
|
|
|
|
|
|
(type == OP_LIST && (first->op_flags & OPf_PARENS))) |
21
|
|
|
|
|
|
|
return newLISTOP(type, 0, first, last); |
22
|
|
|
|
|
|
|
if(first->op_flags & OPf_KIDS) { |
23
|
|
|
|
|
|
|
cLISTOPx(first)->op_last->op_sibling = last; |
24
|
|
|
|
|
|
|
} else { |
25
|
|
|
|
|
|
|
first->op_flags |= OPf_KIDS; |
26
|
|
|
|
|
|
|
cLISTOPx(first)->op_first = last; |
27
|
|
|
|
|
|
|
} |
28
|
|
|
|
|
|
|
cLISTOPx(first)->op_last = last; |
29
|
|
|
|
|
|
|
return first; |
30
|
|
|
|
|
|
|
} |
31
|
|
|
|
|
|
|
#endif /* !op_append_elem */ |
32
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
#ifndef qerror |
34
|
|
|
|
|
|
|
# define qerror(m) Perl_qerror(aTHX_ m) |
35
|
|
|
|
|
|
|
#endif /* !qerror */ |
36
|
|
|
|
|
|
|
|
37
|
|
|
|
|
|
|
#define QPFX C8K61oRQKxigiqmUlVdk_ |
38
|
|
|
|
|
|
|
#define QPFXS STRINGIFY(QPFX) |
39
|
|
|
|
|
|
|
#define QCONCAT0(a,b) a##b |
40
|
|
|
|
|
|
|
#define QCONCAT1(a,b) QCONCAT0(a,b) |
41
|
|
|
|
|
|
|
#define QPFXD(name) QCONCAT1(QPFX, name) |
42
|
|
|
|
|
|
|
|
43
|
|
|
|
|
|
|
#if defined(WIN32) && PERL_VERSION_GE(5,13,6) |
44
|
|
|
|
|
|
|
# define MY_BASE_CALLCONV EXTERN_C |
45
|
|
|
|
|
|
|
# define MY_BASE_CALLCONV_S "EXTERN_C" |
46
|
|
|
|
|
|
|
#else /* !(WIN32 && >= 5.13.6) */ |
47
|
|
|
|
|
|
|
# define MY_BASE_CALLCONV PERL_CALLCONV |
48
|
|
|
|
|
|
|
# define MY_BASE_CALLCONV_S "PERL_CALLCONV" |
49
|
|
|
|
|
|
|
#endif /* !(WIN32 && >= 5.13.6) */ |
50
|
|
|
|
|
|
|
|
51
|
|
|
|
|
|
|
#define MY_EXPORT_CALLCONV MY_BASE_CALLCONV |
52
|
|
|
|
|
|
|
|
53
|
|
|
|
|
|
|
#if defined(WIN32) || defined(__CYGWIN__) |
54
|
|
|
|
|
|
|
# define MY_IMPORT_CALLCONV_S MY_BASE_CALLCONV_S" __declspec(dllimport)" |
55
|
|
|
|
|
|
|
#else |
56
|
|
|
|
|
|
|
# define MY_IMPORT_CALLCONV_S MY_BASE_CALLCONV_S |
57
|
|
|
|
|
|
|
#endif |
58
|
|
|
|
|
|
|
|
59
|
|
|
|
|
|
|
static MGVTBL mgvtbl_parsecall; |
60
|
|
|
|
|
|
|
|
61
|
|
|
|
|
|
|
typedef OP *(*Perl_call_parser)(pTHX_ GV *, SV *, U32 *); |
62
|
|
|
|
|
|
|
|
63
|
|
|
|
|
|
|
#define CALLPARSER_PARENS 0x00000001 |
64
|
|
|
|
|
|
|
#define CALLPARSER_STATEMENT 0x00000002 |
65
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
#ifdef parse_fullexpr |
67
|
|
|
|
|
|
|
# define Q_PARSER_AVAILABLE 1 |
68
|
|
|
|
|
|
|
#endif /* parse_fullexpr */ |
69
|
|
|
|
|
|
|
|
70
|
|
|
|
|
|
|
#if Q_PARSER_AVAILABLE |
71
|
|
|
|
|
|
|
|
72
|
|
|
|
|
|
|
# define Perl_parse_args_parenthesised QPFXD(pac0) |
73
|
|
|
|
|
|
|
# define parse_args_parenthesised(fp) Perl_parse_args_parenthesised(aTHX_ fp) |
74
|
179
|
|
|
|
|
|
MY_EXPORT_CALLCONV OP *QPFXD(pac0)(pTHX_ U32 *flags_p) |
75
|
|
|
|
|
|
|
{ |
76
|
|
|
|
|
|
|
OP *argsop; |
77
|
179
|
|
|
|
|
|
lex_read_space(0); |
78
|
179
|
100
|
|
|
|
|
if(lex_peek_unichar(0) != '('/*)*/) { |
79
|
29
|
|
|
|
|
|
qerror(mess("syntax error")); |
80
|
29
|
|
|
|
|
|
return NULL; |
81
|
|
|
|
|
|
|
} |
82
|
150
|
|
|
|
|
|
lex_read_unichar(0); |
83
|
150
|
|
|
|
|
|
argsop = parse_fullexpr(PARSE_OPTIONAL); |
84
|
150
|
|
|
|
|
|
lex_read_space(0); |
85
|
150
|
50
|
|
|
|
|
if(lex_peek_unichar(0) != /*(*/')') { |
86
|
0
|
|
|
|
|
|
qerror(mess("syntax error")); |
87
|
0
|
|
|
|
|
|
return argsop; |
88
|
|
|
|
|
|
|
} |
89
|
150
|
|
|
|
|
|
lex_read_unichar(0); |
90
|
150
|
|
|
|
|
|
*flags_p |= CALLPARSER_PARENS; |
91
|
150
|
|
|
|
|
|
return argsop; |
92
|
|
|
|
|
|
|
} |
93
|
|
|
|
|
|
|
|
94
|
|
|
|
|
|
|
# define Perl_parse_args_nullary QPFXD(paz0) |
95
|
|
|
|
|
|
|
# define parse_args_nullary(fp) Perl_parse_args_nullary(aTHX_ fp) |
96
|
63
|
|
|
|
|
|
MY_EXPORT_CALLCONV OP *QPFXD(paz0)(pTHX_ U32 *flags_p) |
97
|
|
|
|
|
|
|
{ |
98
|
63
|
|
|
|
|
|
lex_read_space(0); |
99
|
63
|
100
|
|
|
|
|
if(lex_peek_unichar(0) == '('/*)*/) |
100
|
28
|
|
|
|
|
|
return parse_args_parenthesised(flags_p); |
101
|
|
|
|
|
|
|
return NULL; |
102
|
|
|
|
|
|
|
} |
103
|
|
|
|
|
|
|
|
104
|
|
|
|
|
|
|
# define Perl_parse_args_unary QPFXD(pau0) |
105
|
|
|
|
|
|
|
# define parse_args_unary(fp) Perl_parse_args_unary(aTHX_ fp) |
106
|
95
|
|
|
|
|
|
MY_EXPORT_CALLCONV OP *QPFXD(pau0)(pTHX_ U32 *flags_p) |
107
|
|
|
|
|
|
|
{ |
108
|
95
|
|
|
|
|
|
lex_read_space(0); |
109
|
95
|
100
|
|
|
|
|
if(lex_peek_unichar(0) == '('/*)*/) |
110
|
36
|
|
|
|
|
|
return parse_args_parenthesised(flags_p); |
111
|
59
|
|
|
|
|
|
return parse_arithexpr(PARSE_OPTIONAL); |
112
|
|
|
|
|
|
|
} |
113
|
|
|
|
|
|
|
|
114
|
|
|
|
|
|
|
# define Perl_parse_args_list QPFXD(pal0) |
115
|
|
|
|
|
|
|
# define parse_args_list(fp) Perl_parse_args_list(aTHX_ fp) |
116
|
79
|
|
|
|
|
|
MY_EXPORT_CALLCONV OP *QPFXD(pal0)(pTHX_ U32 *flags_p) |
117
|
|
|
|
|
|
|
{ |
118
|
79
|
|
|
|
|
|
lex_read_space(0); |
119
|
79
|
100
|
|
|
|
|
if(lex_peek_unichar(0) == '('/*)*/) |
120
|
32
|
|
|
|
|
|
return parse_args_parenthesised(flags_p); |
121
|
47
|
|
|
|
|
|
return parse_listexpr(PARSE_OPTIONAL); |
122
|
|
|
|
|
|
|
} |
123
|
|
|
|
|
|
|
|
124
|
|
|
|
|
|
|
# define Perl_parse_args_block_list QPFXD(pab0) |
125
|
|
|
|
|
|
|
# define parse_args_block_list(fp) Perl_parse_args_block_list(aTHX_ fp) |
126
|
63
|
|
|
|
|
|
MY_EXPORT_CALLCONV OP *QPFXD(pab0)(pTHX_ U32 *flags_p) |
127
|
|
|
|
|
|
|
{ |
128
|
|
|
|
|
|
|
OP *blkop, *argsop; |
129
|
|
|
|
|
|
|
I32 c; |
130
|
63
|
|
|
|
|
|
lex_read_space(0); |
131
|
63
|
|
|
|
|
|
c = lex_peek_unichar(0); |
132
|
63
|
100
|
|
|
|
|
if(c == '('/*)*/) return parse_args_parenthesised(flags_p); |
133
|
35
|
100
|
|
|
|
|
if(c == '{'/*}*/) { |
134
|
8
|
|
|
|
|
|
I32 floor = start_subparse(0, CVf_ANON); |
135
|
8
|
|
|
|
|
|
SAVEFREESV(PL_compcv); |
136
|
8
|
|
|
|
|
|
blkop = parse_block(0); |
137
|
8
|
50
|
|
|
|
|
SvREFCNT_inc_simple_void((SV*)PL_compcv); |
138
|
8
|
|
|
|
|
|
blkop = newANONATTRSUB(floor, NULL, NULL, blkop); |
139
|
|
|
|
|
|
|
} else { |
140
|
|
|
|
|
|
|
blkop = NULL; |
141
|
|
|
|
|
|
|
} |
142
|
35
|
|
|
|
|
|
argsop = parse_listexpr(PARSE_OPTIONAL); |
143
|
35
|
|
|
|
|
|
return op_prepend_elem(OP_LIST, blkop, argsop); |
144
|
|
|
|
|
|
|
} |
145
|
|
|
|
|
|
|
|
146
|
|
|
|
|
|
|
# define Perl_parse_args_proto QPFXD(pap0) |
147
|
|
|
|
|
|
|
# define parse_args_proto(gv, sv, fp) Perl_parse_args_proto(aTHX_ gv, sv, fp) |
148
|
80
|
|
|
|
|
|
MY_EXPORT_CALLCONV OP *QPFXD(pap0)(pTHX_ GV *namegv, SV *protosv, U32 *flags_p) |
149
|
|
|
|
|
|
|
{ |
150
|
|
|
|
|
|
|
STRLEN proto_len; |
151
|
|
|
|
|
|
|
char const *proto; |
152
|
|
|
|
|
|
|
PERL_UNUSED_ARG(namegv); |
153
|
80
|
100
|
|
|
|
|
if (SvTYPE(protosv) == SVt_PVCV ? !SvPOK(protosv) : !SvOK(protosv)) |
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
154
|
16
|
|
|
|
|
|
croak("panic: parse_args_proto with no proto"); |
155
|
|
|
|
|
|
|
/* |
156
|
|
|
|
|
|
|
* There are variations between Perl versions in the syntactic |
157
|
|
|
|
|
|
|
* interpretation of prototypes, which this code in principle |
158
|
|
|
|
|
|
|
* needs to track. However, from the introduction of the parser |
159
|
|
|
|
|
|
|
* API functions required by this code (5.13.8) to the date |
160
|
|
|
|
|
|
|
* of this note (5.14.0-RC0) there have been no such changes. |
161
|
|
|
|
|
|
|
* With luck there may be no more before this function migrates |
162
|
|
|
|
|
|
|
* into the core. |
163
|
|
|
|
|
|
|
*/ |
164
|
64
|
50
|
|
|
|
|
proto = SvPV(protosv, proto_len); |
165
|
64
|
100
|
|
|
|
|
if(!proto_len) return parse_args_nullary(flags_p); |
166
|
72
|
100
|
|
|
|
|
while(*proto == ';') proto++; |
167
|
56
|
100
|
|
|
|
|
if(proto[0] == '&') return parse_args_block_list(flags_p); |
168
|
48
|
100
|
|
|
|
|
if(((proto[0] == '$' || proto[0] == '_' || |
|
|
50
|
|
|
|
|
|
169
|
48
|
50
|
|
|
|
|
proto[0] == '*' || proto[0] == '+') && |
|
|
50
|
|
|
|
|
|
170
|
8
|
50
|
|
|
|
|
!proto[1]) || |
171
|
0
|
0
|
|
|
|
|
(proto[0] == '\\' && proto[1] && !proto[2])) |
|
|
0
|
|
|
|
|
|
172
|
40
|
|
|
|
|
|
return parse_args_unary(flags_p); |
173
|
8
|
50
|
|
|
|
|
if(proto[0] == '\\' && proto[1] == '['/*]*/) { |
|
|
0
|
|
|
|
|
|
174
|
0
|
|
|
|
|
|
proto += 2; |
175
|
0
|
0
|
|
|
|
|
while(*proto && *proto != /*[*/']') proto++; |
176
|
0
|
0
|
|
|
|
|
if(proto[0] == /*[*/']' && !proto[1]) |
|
|
0
|
|
|
|
|
|
177
|
0
|
|
|
|
|
|
return parse_args_unary(flags_p); |
178
|
|
|
|
|
|
|
} |
179
|
8
|
|
|
|
|
|
return parse_args_list(flags_p); |
180
|
|
|
|
|
|
|
} |
181
|
|
|
|
|
|
|
|
182
|
|
|
|
|
|
|
# define Perl_parse_args_proto_or_list QPFXD(pan0) |
183
|
|
|
|
|
|
|
# define parse_args_proto_or_list(gv, sv, fp) \ |
184
|
|
|
|
|
|
|
Perl_parse_args_proto_or_list(aTHX_ gv, sv, fp) |
185
|
32
|
|
|
|
|
|
MY_EXPORT_CALLCONV OP *QPFXD(pan0)(pTHX_ GV *namegv, SV *protosv, U32 *flags_p) |
186
|
|
|
|
|
|
|
{ |
187
|
32
|
100
|
|
|
|
|
if(SvTYPE(protosv) == SVt_PVCV ? SvPOK(protosv) : SvOK(protosv)) |
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
188
|
16
|
|
|
|
|
|
return parse_args_proto(namegv, protosv, flags_p); |
189
|
|
|
|
|
|
|
else |
190
|
16
|
|
|
|
|
|
return parse_args_list(flags_p); |
191
|
|
|
|
|
|
|
} |
192
|
|
|
|
|
|
|
|
193
|
|
|
|
|
|
|
#endif /* Q_PARSER_AVAILABLE */ |
194
|
|
|
|
|
|
|
|
195
|
|
|
|
|
|
|
#ifndef mg_findext |
196
|
|
|
|
|
|
|
# define mg_findext(sv, type, vtbl) THX_mg_findext(aTHX_ sv, type, vtbl) |
197
|
|
|
|
|
|
|
static MAGIC *THX_mg_findext(pTHX_ SV *sv, int type, MGVTBL const *vtbl) |
198
|
|
|
|
|
|
|
{ |
199
|
|
|
|
|
|
|
MAGIC *mg; |
200
|
|
|
|
|
|
|
if(sv) |
201
|
|
|
|
|
|
|
for(mg = SvMAGIC(sv); mg; mg = mg->mg_moremagic) |
202
|
|
|
|
|
|
|
if(mg->mg_type == type && mg->mg_virtual == vtbl) |
203
|
|
|
|
|
|
|
return mg; |
204
|
|
|
|
|
|
|
return NULL; |
205
|
|
|
|
|
|
|
} |
206
|
|
|
|
|
|
|
#endif /* !mg_findext */ |
207
|
|
|
|
|
|
|
|
208
|
|
|
|
|
|
|
#ifndef sv_unmagicext |
209
|
|
|
|
|
|
|
# define sv_unmagicext(sv, type, vtbl) THX_sv_unmagicext(aTHX_ sv, type, vtbl) |
210
|
|
|
|
|
|
|
static int THX_sv_unmagicext(pTHX_ SV *sv, int type, MGVTBL const *vtbl) |
211
|
|
|
|
|
|
|
{ |
212
|
|
|
|
|
|
|
MAGIC *mg, **mgp; |
213
|
|
|
|
|
|
|
if((vtbl && vtbl->svt_free) || type == PERL_MAGIC_regex_global) |
214
|
|
|
|
|
|
|
/* exceeded intended usage of this reserve implementation */ |
215
|
|
|
|
|
|
|
return 0; |
216
|
|
|
|
|
|
|
if(SvTYPE(sv) < SVt_PVMG || !SvMAGIC(sv)) return 0; |
217
|
|
|
|
|
|
|
mgp = NULL; |
218
|
|
|
|
|
|
|
for(mg = mgp ? *mgp : SvMAGIC(sv); mg; mg = mgp ? *mgp : SvMAGIC(sv)) { |
219
|
|
|
|
|
|
|
if(mg->mg_type == type && mg->mg_virtual == vtbl) { |
220
|
|
|
|
|
|
|
if(mgp) |
221
|
|
|
|
|
|
|
*mgp = mg->mg_moremagic; |
222
|
|
|
|
|
|
|
else |
223
|
|
|
|
|
|
|
SvMAGIC_set(sv, mg->mg_moremagic); |
224
|
|
|
|
|
|
|
if(mg->mg_flags & MGf_REFCOUNTED) |
225
|
|
|
|
|
|
|
SvREFCNT_dec(mg->mg_obj); |
226
|
|
|
|
|
|
|
Safefree(mg); |
227
|
|
|
|
|
|
|
} else { |
228
|
|
|
|
|
|
|
mgp = &mg->mg_moremagic; |
229
|
|
|
|
|
|
|
} |
230
|
|
|
|
|
|
|
} |
231
|
|
|
|
|
|
|
SvMAGICAL_off(sv); |
232
|
|
|
|
|
|
|
mg_magical(sv); |
233
|
|
|
|
|
|
|
return 0; |
234
|
|
|
|
|
|
|
} |
235
|
|
|
|
|
|
|
#endif /* !sv_unmagicext */ |
236
|
|
|
|
|
|
|
|
237
|
622
|
|
|
|
|
|
MY_EXPORT_CALLCONV void QPFXD(gcp0)(pTHX_ CV *cv, |
238
|
|
|
|
|
|
|
Perl_call_parser *psfun_p, SV **psobj_p) |
239
|
|
|
|
|
|
|
{ |
240
|
622
|
|
|
|
|
|
MAGIC *callmg = SvMAGICAL((SV*)cv) ? |
241
|
622
|
100
|
|
|
|
|
mg_findext((SV*)cv, PERL_MAGIC_ext, &mgvtbl_parsecall) : NULL; |
242
|
622
|
100
|
|
|
|
|
if(callmg) { |
243
|
397
|
|
|
|
|
|
*psfun_p = DPTR2FPTR(Perl_call_parser, callmg->mg_ptr); |
244
|
397
|
|
|
|
|
|
*psobj_p = callmg->mg_obj; |
245
|
|
|
|
|
|
|
} else { |
246
|
225
|
|
|
|
|
|
*psfun_p = DPTR2FPTR(Perl_call_parser, NULL); |
247
|
225
|
|
|
|
|
|
*psobj_p = NULL; |
248
|
|
|
|
|
|
|
} |
249
|
622
|
|
|
|
|
|
} |
250
|
|
|
|
|
|
|
|
251
|
48
|
|
|
|
|
|
MY_EXPORT_CALLCONV void QPFXD(scp0)(pTHX_ CV *cv, |
252
|
|
|
|
|
|
|
Perl_call_parser psfun, SV *psobj) |
253
|
|
|
|
|
|
|
{ |
254
|
48
|
100
|
|
|
|
|
if( |
255
|
48
|
|
|
|
|
|
(!psfun && !psobj) |
256
|
|
|
|
|
|
|
#if Q_PARSER_AVAILABLE |
257
|
46
|
100
|
|
|
|
|
|| (psfun == Perl_parse_args_proto_or_list && psobj == (SV*)cv) |
|
|
100
|
|
|
|
|
|
258
|
|
|
|
|
|
|
#endif /* Q_PARSER_AVAILABLE */ |
259
|
|
|
|
|
|
|
) { |
260
|
4
|
50
|
|
|
|
|
if(SvMAGICAL((SV*)cv)) |
261
|
4
|
|
|
|
|
|
sv_unmagicext((SV*)cv, PERL_MAGIC_ext, |
262
|
|
|
|
|
|
|
&mgvtbl_parsecall); |
263
|
|
|
|
|
|
|
} else { |
264
|
44
|
|
|
|
|
|
MAGIC *callmg = |
265
|
|
|
|
|
|
|
mg_findext((SV*)cv, PERL_MAGIC_ext, &mgvtbl_parsecall); |
266
|
44
|
100
|
|
|
|
|
if(!callmg) |
267
|
33
|
|
|
|
|
|
callmg = sv_magicext((SV*)cv, &PL_sv_undef, |
268
|
|
|
|
|
|
|
PERL_MAGIC_ext, &mgvtbl_parsecall, NULL, 0); |
269
|
44
|
50
|
|
|
|
|
if(callmg->mg_flags & MGf_REFCOUNTED) { |
270
|
44
|
|
|
|
|
|
SvREFCNT_dec(callmg->mg_obj); |
271
|
44
|
|
|
|
|
|
callmg->mg_flags &= ~MGf_REFCOUNTED; |
272
|
|
|
|
|
|
|
} |
273
|
44
|
|
|
|
|
|
callmg->mg_ptr = FPTR2DPTR(char *, psfun); |
274
|
44
|
|
|
|
|
|
callmg->mg_obj = psobj; |
275
|
44
|
50
|
|
|
|
|
if(psobj != (SV*)cv) { |
276
|
|
|
|
|
|
|
SvREFCNT_inc(psobj); |
277
|
44
|
|
|
|
|
|
callmg->mg_flags |= MGf_REFCOUNTED; |
278
|
|
|
|
|
|
|
} |
279
|
|
|
|
|
|
|
} |
280
|
48
|
|
|
|
|
|
} |
281
|
|
|
|
|
|
|
|
282
|
|
|
|
|
|
|
#if Q_PARSER_AVAILABLE |
283
|
|
|
|
|
|
|
|
284
|
10
|
|
|
|
|
|
MY_EXPORT_CALLCONV void QPFXD(gcp1)(pTHX_ CV *cv, |
285
|
|
|
|
|
|
|
Perl_call_parser *psfun_p, SV **psobj_p) |
286
|
|
|
|
|
|
|
{ |
287
|
10
|
|
|
|
|
|
QPFXD(gcp0)(aTHX_ cv, psfun_p, psobj_p); |
288
|
10
|
100
|
|
|
|
|
if(!*psfun_p && !*psobj_p) { |
|
|
50
|
|
|
|
|
|
289
|
6
|
|
|
|
|
|
*psfun_p = Perl_parse_args_proto_or_list; |
290
|
6
|
|
|
|
|
|
*psobj_p = (SV*)cv; |
291
|
|
|
|
|
|
|
} |
292
|
10
|
|
|
|
|
|
} |
293
|
|
|
|
|
|
|
|
294
|
41
|
|
|
|
|
|
MY_EXPORT_CALLCONV void QPFXD(scp1)(pTHX_ CV *cv, |
295
|
|
|
|
|
|
|
Perl_call_parser psfun, SV *psobj) |
296
|
|
|
|
|
|
|
{ |
297
|
41
|
50
|
|
|
|
|
if(!psobj) croak("null object for cv_set_call_parser"); |
298
|
41
|
|
|
|
|
|
QPFXD(scp0)(aTHX_ cv, psfun, psobj); |
299
|
41
|
|
|
|
|
|
} |
300
|
|
|
|
|
|
|
|
301
|
|
|
|
|
|
|
#endif /* Q_PARSER_AVAILABLE */ |
302
|
|
|
|
|
|
|
|
303
|
|
|
|
|
|
|
static int (*next_keyword_plugin)(pTHX_ char *, STRLEN, OP **); |
304
|
6801
|
|
|
|
|
|
static int my_keyword_plugin(pTHX_ |
305
|
|
|
|
|
|
|
char *keyword_ptr, STRLEN keyword_len, OP **op_ptr) |
306
|
|
|
|
|
|
|
{ |
307
|
|
|
|
|
|
|
OP *nmop, *cvop, *argsop; |
308
|
|
|
|
|
|
|
CV *cv; |
309
|
|
|
|
|
|
|
GV *namegv; |
310
|
|
|
|
|
|
|
Perl_call_parser psfun; |
311
|
|
|
|
|
|
|
SV *psobj; |
312
|
|
|
|
|
|
|
U32 parser_flags; |
313
|
|
|
|
|
|
|
/* |
314
|
|
|
|
|
|
|
* Creation of the rv2cv op below (or more precisely its gv op |
315
|
|
|
|
|
|
|
* child created during checking) uses a pad slot under threads. |
316
|
|
|
|
|
|
|
* Normally this is fine, but early versions of the padrange |
317
|
|
|
|
|
|
|
* mechanism make assumptions about pad slots being contiguous |
318
|
|
|
|
|
|
|
* that this breaks. On the affected perl versions, therefore, |
319
|
|
|
|
|
|
|
* we watch for the pad slot being consumed, and restore the |
320
|
|
|
|
|
|
|
* pad's fill pointer if we throw the op away (upon declining |
321
|
|
|
|
|
|
|
* to handle the keyword). |
322
|
|
|
|
|
|
|
* |
323
|
|
|
|
|
|
|
* The core bug was supposedly fixed in Perl 5.19.4, but actually |
324
|
|
|
|
|
|
|
* that version exhibits a different bug also apparently related |
325
|
|
|
|
|
|
|
* to padrange. Restoring the pad's fill pointer works around |
326
|
|
|
|
|
|
|
* this bug too. |
327
|
|
|
|
|
|
|
* |
328
|
|
|
|
|
|
|
* The other padrange bug was fixed in Perl 5.19.5 (commit aa033da), |
329
|
|
|
|
|
|
|
* so the workaround is no longer needed after that, but it remains |
330
|
|
|
|
|
|
|
* harmless until v5.21.4 (commit c9859fb) where it starts breaking |
331
|
|
|
|
|
|
|
* (see t/pad2.t.) */ |
332
|
|
|
|
|
|
|
#define MUST_RESTORE_PAD_FILL USE_THREADS && PERL_VERSION_GE(5,17,6) && ! PERL_VERSION_GE(5,19,5) |
333
|
|
|
|
|
|
|
#if MUST_RESTORE_PAD_FILL |
334
|
|
|
|
|
|
|
I32 padfill = av_len(PL_comppad); |
335
|
|
|
|
|
|
|
#endif /* MUST_RESTORE_PAD_FILL */ |
336
|
|
|
|
|
|
|
/* |
337
|
|
|
|
|
|
|
* If Devel::Declare happens to be loaded, it triggers magic |
338
|
|
|
|
|
|
|
* upon building of an rv2cv op, assuming that it's being built |
339
|
|
|
|
|
|
|
* by the lexer. Since we're about to build such an op here, |
340
|
|
|
|
|
|
|
* replicating what the lexer will normally do shortly after, |
341
|
|
|
|
|
|
|
* there's a risk that Devel::Declare could fire here, ultimately |
342
|
|
|
|
|
|
|
* firing twice for a single appearance of a name it's interested |
343
|
|
|
|
|
|
|
* in. To suppress Devel::Declare, therefore, we temporarily |
344
|
|
|
|
|
|
|
* set PL_parser to null. The same goes for Data::Alias and |
345
|
|
|
|
|
|
|
* some other modules that use similar techniques. |
346
|
|
|
|
|
|
|
* |
347
|
|
|
|
|
|
|
* Unfortunately Devel::Declare prior to 0.006004 still does some |
348
|
|
|
|
|
|
|
* work at the wrong time if PL_parser is null, and Data::Alias |
349
|
|
|
|
|
|
|
* prior to 1.13 crashes if PL_parser is null. So this module |
350
|
|
|
|
|
|
|
* is not compatible with earlier versions of those modules, |
351
|
|
|
|
|
|
|
* and can't be made compatible. |
352
|
|
|
|
|
|
|
*/ |
353
|
6801
|
|
|
|
|
|
ENTER; |
354
|
6801
|
|
|
|
|
|
SAVEVPTR(PL_parser); |
355
|
6801
|
|
|
|
|
|
PL_parser = NULL; |
356
|
6801
|
|
|
|
|
|
nmop = newSVOP(OP_CONST, 0, newSVpvn(keyword_ptr, keyword_len)); |
357
|
6801
|
|
|
|
|
|
nmop->op_private = OPpCONST_BARE; |
358
|
6801
|
|
|
|
|
|
cvop = newCVREF(0, nmop); |
359
|
6801
|
|
|
|
|
|
LEAVE; |
360
|
6801
|
100
|
|
|
|
|
if(!(cv = rv2cv_op_cv(cvop, 0))) { |
361
|
|
|
|
|
|
|
decline: |
362
|
6412
|
|
|
|
|
|
op_free(cvop); |
363
|
|
|
|
|
|
|
#if MUST_RESTORE_PAD_FILL |
364
|
|
|
|
|
|
|
av_fill(PL_comppad, padfill); |
365
|
|
|
|
|
|
|
#endif /* MUST_RESTORE_PAD_FILL */ |
366
|
6412
|
|
|
|
|
|
return next_keyword_plugin(aTHX_ |
367
|
|
|
|
|
|
|
keyword_ptr, keyword_len, op_ptr); |
368
|
|
|
|
|
|
|
} |
369
|
602
|
|
|
|
|
|
QPFXD(gcp0)(aTHX_ cv, &psfun, &psobj); |
370
|
602
|
100
|
|
|
|
|
if(!psfun && !psobj) goto decline; |
|
|
50
|
|
|
|
|
|
371
|
389
|
|
|
|
|
|
namegv = (GV*)rv2cv_op_cv(cvop, |
372
|
|
|
|
|
|
|
RV2CVOPCV_MARK_EARLY|RV2CVOPCV_RETURN_NAME_GV); |
373
|
389
|
|
|
|
|
|
parser_flags = 0; |
374
|
389
|
|
|
|
|
|
argsop = psfun(aTHX_ namegv, psobj, &parser_flags); |
375
|
373
|
100
|
|
|
|
|
if(!(parser_flags & CALLPARSER_PARENS)) |
376
|
221
|
|
|
|
|
|
cvop->op_private |= OPpENTERSUB_NOPAREN; |
377
|
373
|
|
|
|
|
|
*op_ptr = newUNOP(OP_ENTERSUB, OPf_STACKED, |
378
|
|
|
|
|
|
|
op_append_elem(OP_LIST, argsop, cvop)); |
379
|
373
|
|
|
|
|
|
return (parser_flags & CALLPARSER_STATEMENT) ? |
380
|
373
|
100
|
|
|
|
|
KEYWORD_PLUGIN_STMT : KEYWORD_PLUGIN_EXPR; |
381
|
|
|
|
|
|
|
} |
382
|
|
|
|
|
|
|
|
383
|
|
|
|
|
|
|
#define fmt_header(n, content) THX_fmt_header(aTHX_ n, content) |
384
|
|
|
|
|
|
|
static SV *THX_fmt_header(pTHX_ char n, char const *content) |
385
|
|
|
|
|
|
|
{ |
386
|
6
|
|
|
|
|
|
return newSVpvf( |
387
|
|
|
|
|
|
|
"/* DO NOT EDIT -- generated " |
388
|
|
|
|
|
|
|
"by Devel::CallParser version "XS_VERSION" */\n" |
389
|
|
|
|
|
|
|
"#ifndef "QPFXS"INCLUDED_callparser%c\n" |
390
|
|
|
|
|
|
|
"#define "QPFXS"INCLUDED_callparser%c 1\n" |
391
|
|
|
|
|
|
|
"#ifndef PERL_VERSION\n" |
392
|
|
|
|
|
|
|
" #error you must include perl.h before callparser%c.h\n" |
393
|
|
|
|
|
|
|
"#elif !(PERL_REVISION == "STRINGIFY(PERL_REVISION) |
394
|
|
|
|
|
|
|
" && PERL_VERSION == "STRINGIFY(PERL_VERSION) |
395
|
|
|
|
|
|
|
#if PERL_VERSION & 1 |
396
|
|
|
|
|
|
|
" && PERL_SUBVERSION == "STRINGIFY(PERL_SUBVERSION) |
397
|
|
|
|
|
|
|
#endif /* PERL_VERSION & 1 */ |
398
|
|
|
|
|
|
|
")\n" |
399
|
|
|
|
|
|
|
" #error this callparser%c.h is for Perl " |
400
|
|
|
|
|
|
|
STRINGIFY(PERL_REVISION)"."STRINGIFY(PERL_VERSION) |
401
|
|
|
|
|
|
|
#if PERL_VERSION & 1 |
402
|
|
|
|
|
|
|
"."STRINGIFY(PERL_SUBVERSION) |
403
|
|
|
|
|
|
|
#endif /* PERL_VERSION & 1 */ |
404
|
|
|
|
|
|
|
" only\n" |
405
|
|
|
|
|
|
|
"#endif /* Perl version mismatch */\n" |
406
|
|
|
|
|
|
|
"%s" |
407
|
|
|
|
|
|
|
"#endif /* !"QPFXS"INCLUDED_callparser%c */\n", |
408
|
|
|
|
|
|
|
n, n, n, n, content, n); |
409
|
|
|
|
|
|
|
} |
410
|
|
|
|
|
|
|
|
411
|
|
|
|
|
|
|
#define DEFFN(RETTYPE, PUBNAME, PRIVNAME, ARGTYPES, ARGNAMES) \ |
412
|
|
|
|
|
|
|
MY_IMPORT_CALLCONV_S" "RETTYPE" "QPFXS PRIVNAME"(pTHX_ "ARGTYPES");\n" \ |
413
|
|
|
|
|
|
|
"#define Perl_"PUBNAME" "QPFXS PRIVNAME"\n" \ |
414
|
|
|
|
|
|
|
"#define "PUBNAME"("ARGNAMES") Perl_"PUBNAME"(aTHX_ "ARGNAMES")\n" |
415
|
|
|
|
|
|
|
|
416
|
|
|
|
|
|
|
#define DEFCALLBACK \ |
417
|
|
|
|
|
|
|
"typedef OP *(*Perl_call_parser)(pTHX_ GV *, SV *, U32 *);\n" \ |
418
|
|
|
|
|
|
|
"#define CALLPARSER_PARENS 0x00000001\n" \ |
419
|
|
|
|
|
|
|
"#define CALLPARSER_STATEMENT 0x00000002\n" |
420
|
|
|
|
|
|
|
|
421
|
|
|
|
|
|
|
MODULE = Devel::CallParser PACKAGE = Devel::CallParser |
422
|
|
|
|
|
|
|
|
423
|
|
|
|
|
|
|
PROTOTYPES: DISABLE |
424
|
|
|
|
|
|
|
|
425
|
|
|
|
|
|
|
BOOT: |
426
|
9
|
|
|
|
|
|
next_keyword_plugin = PL_keyword_plugin; |
427
|
9
|
|
|
|
|
|
PL_keyword_plugin = my_keyword_plugin; |
428
|
|
|
|
|
|
|
|
429
|
|
|
|
|
|
|
SV * |
430
|
|
|
|
|
|
|
callparser0_h() |
431
|
|
|
|
|
|
|
CODE: |
432
|
|
|
|
|
|
|
RETVAL = fmt_header('0', |
433
|
|
|
|
|
|
|
DEFCALLBACK |
434
|
|
|
|
|
|
|
DEFFN("void", "cv_get_call_parser", "gcp0", |
435
|
|
|
|
|
|
|
"CV *, Perl_call_parser *, SV **", "cv, fp, op") |
436
|
|
|
|
|
|
|
DEFFN("void", "cv_set_call_parser", "scp0", |
437
|
|
|
|
|
|
|
"CV *, Perl_call_parser, SV *", "cv, f, o") |
438
|
|
|
|
|
|
|
); |
439
|
|
|
|
|
|
|
OUTPUT: |
440
|
|
|
|
|
|
|
RETVAL |
441
|
|
|
|
|
|
|
|
442
|
|
|
|
|
|
|
SV * |
443
|
|
|
|
|
|
|
callparser1_h() |
444
|
|
|
|
|
|
|
CODE: |
445
|
|
|
|
|
|
|
#if Q_PARSER_AVAILABLE |
446
|
|
|
|
|
|
|
RETVAL = fmt_header('1', |
447
|
|
|
|
|
|
|
DEFFN("OP *", "parse_args_parenthesised", "pac0", "U32 *", "fp") |
448
|
|
|
|
|
|
|
DEFFN("OP *", "parse_args_nullary", "paz0", "U32 *", "fp") |
449
|
|
|
|
|
|
|
DEFFN("OP *", "parse_args_unary", "pau0", "U32 *", "fp") |
450
|
|
|
|
|
|
|
DEFFN("OP *", "parse_args_list", "pal0", "U32 *", "fp") |
451
|
|
|
|
|
|
|
DEFFN("OP *", "parse_args_block_list", "pab0", "U32 *", "fp") |
452
|
|
|
|
|
|
|
DEFFN("OP *", "parse_args_proto", "pap0", |
453
|
|
|
|
|
|
|
"GV *, SV *, U32 *", "gv, sv, fp") |
454
|
|
|
|
|
|
|
DEFFN("OP *", "parse_args_proto_or_list", "pan0", |
455
|
|
|
|
|
|
|
"GV *, SV *, U32 *", "gv, sv, fp") |
456
|
|
|
|
|
|
|
DEFCALLBACK |
457
|
|
|
|
|
|
|
DEFFN("void", "cv_get_call_parser", "gcp1", |
458
|
|
|
|
|
|
|
"CV *, Perl_call_parser *, SV **", "cv, fp, op") |
459
|
|
|
|
|
|
|
DEFFN("void", "cv_set_call_parser", "scp1", |
460
|
|
|
|
|
|
|
"CV *, Perl_call_parser, SV *", "cv, f, o") |
461
|
|
|
|
|
|
|
); |
462
|
|
|
|
|
|
|
#else /* !Q_PARSER_AVAILABLE */ |
463
|
|
|
|
|
|
|
croak("callparser1.h not available on this version of Perl"); |
464
|
|
|
|
|
|
|
#endif /* !Q_PARSER_AVAILABLE */ |
465
|
|
|
|
|
|
|
OUTPUT: |
466
|
|
|
|
|
|
|
RETVAL |