line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
/* This file is part of the indirect Perl module. |
2
|
|
|
|
|
|
|
* See http://search.cpan.org/dist/indirect/ */ |
3
|
|
|
|
|
|
|
|
4
|
|
|
|
|
|
|
#define PERL_NO_GET_CONTEXT |
5
|
|
|
|
|
|
|
#include "EXTERN.h" |
6
|
|
|
|
|
|
|
#include "perl.h" |
7
|
|
|
|
|
|
|
#include "XSUB.h" |
8
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
/* --- XS helpers ---------------------------------------------------------- */ |
10
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
#define XSH_PACKAGE "indirect" |
12
|
|
|
|
|
|
|
|
13
|
|
|
|
|
|
|
#include "xsh/caps.h" |
14
|
|
|
|
|
|
|
#include "xsh/util.h" |
15
|
|
|
|
|
|
|
#include "xsh/mem.h" |
16
|
|
|
|
|
|
|
#include "xsh/ops.h" |
17
|
|
|
|
|
|
|
|
18
|
|
|
|
|
|
|
/* ... op => source position map ........................................... */ |
19
|
|
|
|
|
|
|
|
20
|
|
|
|
|
|
|
typedef struct { |
21
|
|
|
|
|
|
|
char *buf; |
22
|
|
|
|
|
|
|
STRLEN pos; |
23
|
|
|
|
|
|
|
STRLEN size; |
24
|
|
|
|
|
|
|
STRLEN len; |
25
|
|
|
|
|
|
|
line_t line; |
26
|
|
|
|
|
|
|
} indirect_op_info_t; |
27
|
|
|
|
|
|
|
|
28
|
|
|
|
|
|
|
#define PTABLE_NAME ptable |
29
|
|
|
|
|
|
|
#define PTABLE_VAL_FREE(V) if (V) { indirect_op_info_t *oi = (V); XSH_LOCAL_FREE(oi->buf, oi->size, char); XSH_LOCAL_FREE(oi, 1, indirect_op_info_t); } |
30
|
|
|
|
|
|
|
#define PTABLE_NEED_DELETE 1 |
31
|
|
|
|
|
|
|
#define PTABLE_NEED_WALK 0 |
32
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
#include "xsh/ptable.h" |
34
|
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
/* XSH_LOCAL_FREE() always need aTHX */ |
36
|
|
|
|
|
|
|
#define ptable_store(T, K, V) ptable_store(aTHX_ (T), (K), (V)) |
37
|
|
|
|
|
|
|
#define ptable_delete(T, K) ptable_delete(aTHX_ (T), (K)) |
38
|
|
|
|
|
|
|
#define ptable_clear(T) ptable_clear(aTHX_ (T)) |
39
|
|
|
|
|
|
|
#define ptable_free(T) ptable_free(aTHX_ (T)) |
40
|
|
|
|
|
|
|
|
41
|
|
|
|
|
|
|
/* ... Lexical hints ....................................................... */ |
42
|
|
|
|
|
|
|
|
43
|
|
|
|
|
|
|
#define XSH_HINTS_TYPE_SV 1 |
44
|
|
|
|
|
|
|
|
45
|
|
|
|
|
|
|
#include "xsh/hints.h" |
46
|
|
|
|
|
|
|
|
47
|
|
|
|
|
|
|
/* ... Thread-local storage ................................................ */ |
48
|
|
|
|
|
|
|
|
49
|
|
|
|
|
|
|
typedef struct { |
50
|
|
|
|
|
|
|
ptable *map; |
51
|
|
|
|
|
|
|
SV *global_code; |
52
|
|
|
|
|
|
|
} xsh_user_cxt_t; |
53
|
|
|
|
|
|
|
|
54
|
|
|
|
|
|
|
#define XSH_THREADS_USER_CONTEXT 1 |
55
|
|
|
|
|
|
|
#define XSH_THREADS_USER_CLONE_NEEDS_DUP 1 |
56
|
|
|
|
|
|
|
#define XSH_THREADS_COMPILE_TIME_PROTECTION 1 |
57
|
|
|
|
|
|
|
|
58
|
|
|
|
|
|
|
#if XSH_THREADSAFE |
59
|
|
|
|
|
|
|
|
60
|
|
|
|
|
|
|
static void xsh_user_clone(pTHX_ const xsh_user_cxt_t *old_cxt, xsh_user_cxt_t *new_cxt, CLONE_PARAMS *params) { |
61
|
|
|
|
|
|
|
new_cxt->map = ptable_new(32); |
62
|
|
|
|
|
|
|
new_cxt->global_code = xsh_dup_inc(old_cxt->global_code, params); |
63
|
|
|
|
|
|
|
|
64
|
|
|
|
|
|
|
return; |
65
|
|
|
|
|
|
|
} |
66
|
|
|
|
|
|
|
|
67
|
|
|
|
|
|
|
#endif /* XSH_THREADSAFE */ |
68
|
|
|
|
|
|
|
|
69
|
|
|
|
|
|
|
#include "xsh/threads.h" |
70
|
|
|
|
|
|
|
|
71
|
|
|
|
|
|
|
/* ... Lexical hints, continued ............................................ */ |
72
|
|
|
|
|
|
|
|
73
|
100535
|
|
|
|
|
|
static SV *indirect_hint(pTHX) { |
74
|
|
|
|
|
|
|
#define indirect_hint() indirect_hint(aTHX) |
75
|
|
|
|
|
|
|
SV *hint; |
76
|
|
|
|
|
|
|
|
77
|
|
|
|
|
|
|
#if XSH_HAS_PERL(5, 10, 0) || defined(PL_parser) |
78
|
100535
|
100
|
|
|
|
|
if (!PL_parser) |
79
|
4
|
|
|
|
|
|
return NULL; |
80
|
|
|
|
|
|
|
#endif |
81
|
|
|
|
|
|
|
|
82
|
100531
|
|
|
|
|
|
hint = xsh_hints_fetch(); |
83
|
100531
|
100
|
|
|
|
|
if (hint && SvOK(hint)) { |
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
84
|
45570
|
|
|
|
|
|
return xsh_hints_detag(hint); |
85
|
|
|
|
|
|
|
} else { |
86
|
|
|
|
|
|
|
dXSH_CXT; |
87
|
54961
|
50
|
|
|
|
|
if (xsh_is_loaded(&XSH_CXT)) |
88
|
54961
|
|
|
|
|
|
return XSH_CXT.global_code; |
89
|
|
|
|
|
|
|
else |
90
|
0
|
|
|
|
|
|
return NULL; |
91
|
|
|
|
|
|
|
} |
92
|
|
|
|
|
|
|
} |
93
|
|
|
|
|
|
|
|
94
|
|
|
|
|
|
|
/* --- Compatibility wrappers ---------------------------------------------- */ |
95
|
|
|
|
|
|
|
|
96
|
|
|
|
|
|
|
#ifndef SvPV_const |
97
|
|
|
|
|
|
|
# define SvPV_const SvPV |
98
|
|
|
|
|
|
|
#endif |
99
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
#ifndef SvPV_nolen_const |
101
|
|
|
|
|
|
|
# define SvPV_nolen_const SvPV_nolen |
102
|
|
|
|
|
|
|
#endif |
103
|
|
|
|
|
|
|
|
104
|
|
|
|
|
|
|
#ifndef SvPVX_const |
105
|
|
|
|
|
|
|
# define SvPVX_const SvPVX |
106
|
|
|
|
|
|
|
#endif |
107
|
|
|
|
|
|
|
|
108
|
|
|
|
|
|
|
#ifndef SvREFCNT_inc_simple_void_NN |
109
|
|
|
|
|
|
|
# ifdef SvREFCNT_inc_simple_NN |
110
|
|
|
|
|
|
|
# define SvREFCNT_inc_simple_void_NN SvREFCNT_inc_simple_NN |
111
|
|
|
|
|
|
|
# else |
112
|
|
|
|
|
|
|
# define SvREFCNT_inc_simple_void_NN SvREFCNT_inc |
113
|
|
|
|
|
|
|
# endif |
114
|
|
|
|
|
|
|
#endif |
115
|
|
|
|
|
|
|
|
116
|
|
|
|
|
|
|
#ifndef sv_catpvn_nomg |
117
|
|
|
|
|
|
|
# define sv_catpvn_nomg sv_catpvn |
118
|
|
|
|
|
|
|
#endif |
119
|
|
|
|
|
|
|
|
120
|
|
|
|
|
|
|
#ifndef mPUSHp |
121
|
|
|
|
|
|
|
# define mPUSHp(P, L) PUSHs(sv_2mortal(newSVpvn((P), (L)))) |
122
|
|
|
|
|
|
|
#endif |
123
|
|
|
|
|
|
|
|
124
|
|
|
|
|
|
|
#ifndef mPUSHu |
125
|
|
|
|
|
|
|
# define mPUSHu(U) PUSHs(sv_2mortal(newSVuv(U))) |
126
|
|
|
|
|
|
|
#endif |
127
|
|
|
|
|
|
|
|
128
|
|
|
|
|
|
|
#ifndef HvNAME_get |
129
|
|
|
|
|
|
|
# define HvNAME_get(H) HvNAME(H) |
130
|
|
|
|
|
|
|
#endif |
131
|
|
|
|
|
|
|
|
132
|
|
|
|
|
|
|
#ifndef HvNAMELEN_get |
133
|
|
|
|
|
|
|
# define HvNAMELEN_get(H) strlen(HvNAME_get(H)) |
134
|
|
|
|
|
|
|
#endif |
135
|
|
|
|
|
|
|
|
136
|
|
|
|
|
|
|
#if XSH_HAS_PERL(5, 10, 0) || defined(PL_parser) |
137
|
|
|
|
|
|
|
# ifndef PL_linestr |
138
|
|
|
|
|
|
|
# define PL_linestr PL_parser->linestr |
139
|
|
|
|
|
|
|
# endif |
140
|
|
|
|
|
|
|
# ifndef PL_bufptr |
141
|
|
|
|
|
|
|
# define PL_bufptr PL_parser->bufptr |
142
|
|
|
|
|
|
|
# endif |
143
|
|
|
|
|
|
|
# ifndef PL_oldbufptr |
144
|
|
|
|
|
|
|
# define PL_oldbufptr PL_parser->oldbufptr |
145
|
|
|
|
|
|
|
# endif |
146
|
|
|
|
|
|
|
# ifndef PL_lex_inwhat |
147
|
|
|
|
|
|
|
# define PL_lex_inwhat PL_parser->lex_inwhat |
148
|
|
|
|
|
|
|
# endif |
149
|
|
|
|
|
|
|
# ifndef PL_multi_close |
150
|
|
|
|
|
|
|
# define PL_multi_close PL_parser->multi_close |
151
|
|
|
|
|
|
|
# endif |
152
|
|
|
|
|
|
|
#else |
153
|
|
|
|
|
|
|
# ifndef PL_linestr |
154
|
|
|
|
|
|
|
# define PL_linestr PL_Ilinestr |
155
|
|
|
|
|
|
|
# endif |
156
|
|
|
|
|
|
|
# ifndef PL_bufptr |
157
|
|
|
|
|
|
|
# define PL_bufptr PL_Ibufptr |
158
|
|
|
|
|
|
|
# endif |
159
|
|
|
|
|
|
|
# ifndef PL_oldbufptr |
160
|
|
|
|
|
|
|
# define PL_oldbufptr PL_Ioldbufptr |
161
|
|
|
|
|
|
|
# endif |
162
|
|
|
|
|
|
|
# ifndef PL_lex_inwhat |
163
|
|
|
|
|
|
|
# define PL_lex_inwhat PL_Ilex_inwhat |
164
|
|
|
|
|
|
|
# endif |
165
|
|
|
|
|
|
|
# ifndef PL_multi_close |
166
|
|
|
|
|
|
|
# define PL_multi_close PL_Imulti_close |
167
|
|
|
|
|
|
|
# endif |
168
|
|
|
|
|
|
|
#endif |
169
|
|
|
|
|
|
|
|
170
|
|
|
|
|
|
|
/* ... Safe version of call_sv() ........................................... */ |
171
|
|
|
|
|
|
|
|
172
|
1355
|
|
|
|
|
|
static I32 indirect_call_sv(pTHX_ SV *sv, I32 flags) { |
173
|
|
|
|
|
|
|
#define indirect_call_sv(S, F) indirect_call_sv(aTHX_ (S), (F)) |
174
|
|
|
|
|
|
|
I32 ret, cxix; |
175
|
|
|
|
|
|
|
PERL_CONTEXT saved_cx; |
176
|
1355
|
|
|
|
|
|
SV *saved_errsv = NULL; |
177
|
|
|
|
|
|
|
|
178
|
1355
|
50
|
|
|
|
|
if (SvTRUE(ERRSV)) { |
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
179
|
2
|
50
|
|
|
|
|
if (IN_PERL_COMPILETIME && PL_errors) |
|
|
50
|
|
|
|
|
|
180
|
2
|
50
|
|
|
|
|
sv_catsv(PL_errors, ERRSV); |
181
|
|
|
|
|
|
|
else |
182
|
0
|
0
|
|
|
|
|
saved_errsv = newSVsv(ERRSV); |
183
|
2
|
50
|
|
|
|
|
SvCUR_set(ERRSV, 0); |
184
|
|
|
|
|
|
|
} |
185
|
|
|
|
|
|
|
|
186
|
1355
|
50
|
|
|
|
|
cxix = (cxstack_ix < cxstack_max) ? (cxstack_ix + 1) : Perl_cxinc(aTHX); |
187
|
|
|
|
|
|
|
/* The last popped context will be reused by call_sv(), but our callers may |
188
|
|
|
|
|
|
|
* still need its previous value. Back it up so that it isn't clobbered. */ |
189
|
1355
|
|
|
|
|
|
saved_cx = cxstack[cxix]; |
190
|
|
|
|
|
|
|
|
191
|
1355
|
|
|
|
|
|
ret = call_sv(sv, flags | G_EVAL); |
192
|
|
|
|
|
|
|
|
193
|
1353
|
|
|
|
|
|
cxstack[cxix] = saved_cx; |
194
|
|
|
|
|
|
|
|
195
|
1353
|
50
|
|
|
|
|
if (SvTRUE(ERRSV)) { |
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
196
|
|
|
|
|
|
|
/* Discard the old ERRSV, and reuse the variable to temporarily store the |
197
|
|
|
|
|
|
|
* new one. */ |
198
|
9
|
50
|
|
|
|
|
if (saved_errsv) |
199
|
0
|
0
|
|
|
|
|
sv_setsv(saved_errsv, ERRSV); |
200
|
|
|
|
|
|
|
else |
201
|
9
|
50
|
|
|
|
|
saved_errsv = newSVsv(ERRSV); |
202
|
9
|
50
|
|
|
|
|
SvCUR_set(ERRSV, 0); |
203
|
|
|
|
|
|
|
/* Immediately flush all errors. */ |
204
|
9
|
50
|
|
|
|
|
if (IN_PERL_COMPILETIME) { |
205
|
|
|
|
|
|
|
#if XSH_HAS_PERL(5, 10, 0) || defined(PL_parser) |
206
|
9
|
50
|
|
|
|
|
if (PL_parser) |
207
|
9
|
|
|
|
|
|
++PL_parser->error_count; |
208
|
|
|
|
|
|
|
#elif defined(PL_error_count) |
209
|
|
|
|
|
|
|
++PL_error_count; |
210
|
|
|
|
|
|
|
#else |
211
|
|
|
|
|
|
|
++PL_Ierror_count; |
212
|
|
|
|
|
|
|
#endif |
213
|
9
|
50
|
|
|
|
|
if (PL_errors) { |
214
|
9
|
50
|
|
|
|
|
sv_setsv(ERRSV, PL_errors); |
215
|
9
|
|
|
|
|
|
SvCUR_set(PL_errors, 0); |
216
|
|
|
|
|
|
|
} |
217
|
|
|
|
|
|
|
} |
218
|
9
|
50
|
|
|
|
|
sv_catsv(ERRSV, saved_errsv); |
219
|
9
|
|
|
|
|
|
SvREFCNT_dec(saved_errsv); |
220
|
9
|
|
|
|
|
|
croak(NULL); |
221
|
1344
|
50
|
|
|
|
|
} else if (saved_errsv) { |
222
|
|
|
|
|
|
|
/* If IN_PERL_COMPILETIME && PL_errors, then the old ERRSV has already been |
223
|
|
|
|
|
|
|
* added to PL_errors. Otherwise, just restore it to ERRSV, as if no eval |
224
|
|
|
|
|
|
|
* block has ever been executed. */ |
225
|
0
|
0
|
|
|
|
|
sv_setsv(ERRSV, saved_errsv); |
226
|
0
|
|
|
|
|
|
SvREFCNT_dec(saved_errsv); |
227
|
|
|
|
|
|
|
} |
228
|
|
|
|
|
|
|
|
229
|
1344
|
|
|
|
|
|
return ret; |
230
|
|
|
|
|
|
|
} |
231
|
|
|
|
|
|
|
|
232
|
|
|
|
|
|
|
/* --- Check functions ----------------------------------------------------- */ |
233
|
|
|
|
|
|
|
|
234
|
|
|
|
|
|
|
/* ... op => source position map, continued ................................ */ |
235
|
|
|
|
|
|
|
|
236
|
26703
|
|
|
|
|
|
static void indirect_map_store(pTHX_ const OP *o, STRLEN pos, SV *sv, line_t line) { |
237
|
|
|
|
|
|
|
#define indirect_map_store(O, P, N, L) indirect_map_store(aTHX_ (O), (P), (N), (L)) |
238
|
|
|
|
|
|
|
indirect_op_info_t *oi; |
239
|
|
|
|
|
|
|
const char *s; |
240
|
|
|
|
|
|
|
STRLEN len; |
241
|
|
|
|
|
|
|
dXSH_CXT; |
242
|
|
|
|
|
|
|
|
243
|
|
|
|
|
|
|
/* No need to check for XSH_CXT.map != NULL because this code path is always |
244
|
|
|
|
|
|
|
* guarded by indirect_hint(). */ |
245
|
|
|
|
|
|
|
|
246
|
26703
|
100
|
|
|
|
|
if (!(oi = ptable_fetch(XSH_CXT.map, o))) { |
247
|
23386
|
|
|
|
|
|
XSH_LOCAL_ALLOC(oi, 1, indirect_op_info_t); |
248
|
23386
|
|
|
|
|
|
ptable_store(XSH_CXT.map, o, oi); |
249
|
23386
|
|
|
|
|
|
oi->buf = NULL; |
250
|
23386
|
|
|
|
|
|
oi->size = 0; |
251
|
|
|
|
|
|
|
} |
252
|
|
|
|
|
|
|
|
253
|
26703
|
100
|
|
|
|
|
if (sv) { |
254
|
14106
|
50
|
|
|
|
|
s = SvPV_const(sv, len); |
255
|
|
|
|
|
|
|
} else { |
256
|
12597
|
|
|
|
|
|
s = "{"; |
257
|
12597
|
|
|
|
|
|
len = 1; |
258
|
|
|
|
|
|
|
} |
259
|
|
|
|
|
|
|
|
260
|
26703
|
100
|
|
|
|
|
if (len > oi->size) { |
261
|
26461
|
|
|
|
|
|
XSH_LOCAL_REALLOC(oi->buf, oi->size, len, char); |
262
|
26461
|
|
|
|
|
|
oi->size = len; |
263
|
|
|
|
|
|
|
} |
264
|
26703
|
|
|
|
|
|
Copy(s, oi->buf, len, char); |
265
|
|
|
|
|
|
|
|
266
|
26703
|
|
|
|
|
|
oi->len = len; |
267
|
26703
|
|
|
|
|
|
oi->pos = pos; |
268
|
26703
|
|
|
|
|
|
oi->line = line; |
269
|
26703
|
|
|
|
|
|
} |
270
|
|
|
|
|
|
|
|
271
|
7672
|
|
|
|
|
|
static const indirect_op_info_t *indirect_map_fetch(pTHX_ const OP *o) { |
272
|
|
|
|
|
|
|
#define indirect_map_fetch(O) indirect_map_fetch(aTHX_ (O)) |
273
|
|
|
|
|
|
|
dXSH_CXT; |
274
|
|
|
|
|
|
|
|
275
|
|
|
|
|
|
|
/* No need to check for XSH_CXT.map != NULL because this code path is always |
276
|
|
|
|
|
|
|
* guarded by indirect_hint(). */ |
277
|
|
|
|
|
|
|
|
278
|
7672
|
|
|
|
|
|
return ptable_fetch(XSH_CXT.map, o); |
279
|
|
|
|
|
|
|
} |
280
|
|
|
|
|
|
|
|
281
|
65652
|
|
|
|
|
|
static void indirect_map_delete(pTHX_ const OP *o) { |
282
|
|
|
|
|
|
|
#define indirect_map_delete(O) indirect_map_delete(aTHX_ (O)) |
283
|
|
|
|
|
|
|
dXSH_CXT; |
284
|
|
|
|
|
|
|
|
285
|
65652
|
50
|
|
|
|
|
if (xsh_is_loaded(&XSH_CXT) && XSH_CXT.map) |
|
|
50
|
|
|
|
|
|
286
|
65652
|
|
|
|
|
|
ptable_delete(XSH_CXT.map, o); |
287
|
65652
|
|
|
|
|
|
} |
288
|
|
|
|
|
|
|
|
289
|
|
|
|
|
|
|
/* ... Heuristics for finding a string in the source buffer ................ */ |
290
|
|
|
|
|
|
|
|
291
|
19059
|
|
|
|
|
|
static int indirect_find(pTHX_ SV *name_sv, const char *line_bufptr, STRLEN *name_pos) { |
292
|
|
|
|
|
|
|
#define indirect_find(NSV, LBP, NP) indirect_find(aTHX_ (NSV), (LBP), (NP)) |
293
|
|
|
|
|
|
|
STRLEN name_len, line_len; |
294
|
|
|
|
|
|
|
const char *name, *name_end; |
295
|
|
|
|
|
|
|
const char *line, *line_end; |
296
|
|
|
|
|
|
|
const char *p; |
297
|
|
|
|
|
|
|
|
298
|
19059
|
50
|
|
|
|
|
line = SvPV_const(PL_linestr, line_len); |
299
|
19059
|
|
|
|
|
|
line_end = line + line_len; |
300
|
|
|
|
|
|
|
|
301
|
19059
|
50
|
|
|
|
|
name = SvPV_const(name_sv, name_len); |
302
|
19059
|
50
|
|
|
|
|
if (name_len >= 1 && *name == '$') { |
|
|
100
|
|
|
|
|
|
303
|
385
|
|
|
|
|
|
++name; |
304
|
385
|
|
|
|
|
|
--name_len; |
305
|
942
|
100
|
|
|
|
|
while (line_bufptr < line_end && *line_bufptr != '$') |
|
|
100
|
|
|
|
|
|
306
|
557
|
|
|
|
|
|
++line_bufptr; |
307
|
385
|
100
|
|
|
|
|
if (line_bufptr >= line_end) |
308
|
6
|
|
|
|
|
|
return 0; |
309
|
|
|
|
|
|
|
} |
310
|
19053
|
|
|
|
|
|
name_end = name + name_len; |
311
|
|
|
|
|
|
|
|
312
|
19053
|
|
|
|
|
|
p = line_bufptr; |
313
|
|
|
|
|
|
|
while (1) { |
314
|
19071
|
|
|
|
|
|
p = ninstr(p, line_end, name, name_end); |
315
|
19071
|
100
|
|
|
|
|
if (!p) |
316
|
8004
|
|
|
|
|
|
return 0; |
317
|
11067
|
100
|
|
|
|
|
if (!isALNUM(p[name_len])) |
318
|
11049
|
|
|
|
|
|
break; |
319
|
|
|
|
|
|
|
/* p points to a word that has name as prefix, skip the rest of the word */ |
320
|
18
|
|
|
|
|
|
p += name_len + 1; |
321
|
48
|
100
|
|
|
|
|
while (isALNUM(*p)) |
322
|
30
|
|
|
|
|
|
++p; |
323
|
18
|
|
|
|
|
|
} |
324
|
|
|
|
|
|
|
|
325
|
11049
|
|
|
|
|
|
*name_pos = p - line; |
326
|
|
|
|
|
|
|
|
327
|
19059
|
|
|
|
|
|
return 1; |
328
|
|
|
|
|
|
|
} |
329
|
|
|
|
|
|
|
|
330
|
|
|
|
|
|
|
/* ... ck_const ............................................................ */ |
331
|
|
|
|
|
|
|
|
332
|
|
|
|
|
|
|
static OP *(*indirect_old_ck_const)(pTHX_ OP *) = 0; |
333
|
|
|
|
|
|
|
|
334
|
38825
|
|
|
|
|
|
static OP *indirect_ck_const(pTHX_ OP *o) { |
335
|
38825
|
|
|
|
|
|
o = indirect_old_ck_const(aTHX_ o); |
336
|
|
|
|
|
|
|
|
337
|
38825
|
100
|
|
|
|
|
if (indirect_hint()) { |
338
|
14333
|
|
|
|
|
|
SV *sv = cSVOPo_sv; |
339
|
|
|
|
|
|
|
|
340
|
14333
|
100
|
|
|
|
|
if (SvPOK(sv) && (SvTYPE(sv) >= SVt_PV)) { |
|
|
50
|
|
|
|
|
|
341
|
|
|
|
|
|
|
STRLEN pos; |
342
|
|
|
|
|
|
|
const char *bufptr; |
343
|
|
|
|
|
|
|
|
344
|
14118
|
100
|
|
|
|
|
bufptr = PL_multi_close == '<' ? PL_bufptr : PL_oldbufptr; |
345
|
|
|
|
|
|
|
|
346
|
14118
|
100
|
|
|
|
|
if (indirect_find(sv, bufptr, &pos)) { |
347
|
|
|
|
|
|
|
STRLEN len; |
348
|
|
|
|
|
|
|
|
349
|
|
|
|
|
|
|
/* If the constant is equal to the current package name, try to look for |
350
|
|
|
|
|
|
|
* a "__PACKAGE__" coming before what we got. We only need to check this |
351
|
|
|
|
|
|
|
* when we already had a match because __PACKAGE__ can only appear in |
352
|
|
|
|
|
|
|
* direct method calls ("new __PACKAGE__" is a syntax error). */ |
353
|
10791
|
|
|
|
|
|
len = SvCUR(sv); |
354
|
10791
|
50
|
|
|
|
|
if (PL_curstash |
355
|
10791
|
50
|
|
|
|
|
&& len == (STRLEN) HvNAMELEN_get(PL_curstash) |
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
356
|
52
|
50
|
|
|
|
|
&& memcmp(SvPVX(sv), HvNAME_get(PL_curstash), len) == 0) { |
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
357
|
|
|
|
|
|
|
STRLEN pos_pkg; |
358
|
30
|
|
|
|
|
|
SV *pkg = sv_newmortal(); |
359
|
30
|
|
|
|
|
|
sv_setpvn(pkg, "__PACKAGE__", sizeof("__PACKAGE__")-1); |
360
|
|
|
|
|
|
|
|
361
|
30
|
100
|
|
|
|
|
if (indirect_find(pkg, PL_oldbufptr, &pos_pkg) && pos_pkg < pos) { |
|
|
100
|
|
|
|
|
|
362
|
11
|
|
|
|
|
|
sv = pkg; |
363
|
30
|
|
|
|
|
|
pos = pos_pkg; |
364
|
|
|
|
|
|
|
} |
365
|
|
|
|
|
|
|
} |
366
|
|
|
|
|
|
|
|
367
|
10791
|
|
|
|
|
|
indirect_map_store(o, pos, sv, CopLINE(&PL_compiling)); |
368
|
14118
|
|
|
|
|
|
return o; |
369
|
|
|
|
|
|
|
} |
370
|
|
|
|
|
|
|
} |
371
|
|
|
|
|
|
|
} |
372
|
|
|
|
|
|
|
|
373
|
28034
|
|
|
|
|
|
indirect_map_delete(o); |
374
|
28034
|
|
|
|
|
|
return o; |
375
|
|
|
|
|
|
|
} |
376
|
|
|
|
|
|
|
|
377
|
|
|
|
|
|
|
/* ... ck_rv2sv ............................................................ */ |
378
|
|
|
|
|
|
|
|
379
|
|
|
|
|
|
|
static OP *(*indirect_old_ck_rv2sv)(pTHX_ OP *) = 0; |
380
|
|
|
|
|
|
|
|
381
|
1543
|
|
|
|
|
|
static OP *indirect_ck_rv2sv(pTHX_ OP *o) { |
382
|
1543
|
100
|
|
|
|
|
if (indirect_hint()) { |
383
|
267
|
|
|
|
|
|
OP *op = cUNOPo->op_first; |
384
|
|
|
|
|
|
|
SV *sv; |
385
|
267
|
|
|
|
|
|
const char *name = NULL; |
386
|
|
|
|
|
|
|
STRLEN pos, len; |
387
|
267
|
|
|
|
|
|
OPCODE type = (OPCODE) op->op_type; |
388
|
|
|
|
|
|
|
|
389
|
267
|
100
|
|
|
|
|
switch (type) { |
390
|
|
|
|
|
|
|
case OP_GV: |
391
|
|
|
|
|
|
|
case OP_GVSV: { |
392
|
2
|
|
|
|
|
|
GV *gv = cGVOPx_gv(op); |
393
|
2
|
|
|
|
|
|
name = GvNAME(gv); |
394
|
2
|
|
|
|
|
|
len = GvNAMELEN(gv); |
395
|
2
|
|
|
|
|
|
break; |
396
|
|
|
|
|
|
|
} |
397
|
|
|
|
|
|
|
default: |
398
|
265
|
100
|
|
|
|
|
if ((PL_opargs[type] & OA_CLASS_MASK) == OA_SVOP) { |
399
|
238
|
|
|
|
|
|
SV *nsv = cSVOPx_sv(op); |
400
|
238
|
50
|
|
|
|
|
if (SvPOK(nsv) && (SvTYPE(nsv) >= SVt_PV)) |
|
|
50
|
|
|
|
|
|
401
|
238
|
50
|
|
|
|
|
name = SvPV_const(nsv, len); |
402
|
|
|
|
|
|
|
} |
403
|
|
|
|
|
|
|
} |
404
|
267
|
100
|
|
|
|
|
if (!name) |
405
|
64
|
|
|
|
|
|
goto done; |
406
|
|
|
|
|
|
|
|
407
|
240
|
|
|
|
|
|
sv = sv_2mortal(newSVpvn("$", 1)); |
408
|
240
|
|
|
|
|
|
sv_catpvn_nomg(sv, name, len); |
409
|
240
|
100
|
|
|
|
|
if (!indirect_find(sv, PL_oldbufptr, &pos)) { |
410
|
|
|
|
|
|
|
/* If it failed, retry without the current stash */ |
411
|
176
|
50
|
|
|
|
|
const char *stash = HvNAME_get(PL_curstash); |
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
412
|
176
|
50
|
|
|
|
|
STRLEN stashlen = HvNAMELEN_get(PL_curstash); |
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
413
|
|
|
|
|
|
|
|
414
|
176
|
100
|
|
|
|
|
if ((len < stashlen + 2) || strnNE(name, stash, stashlen) |
|
|
100
|
|
|
|
|
|
415
|
136
|
100
|
|
|
|
|
|| name[stashlen] != ':' || name[stashlen+1] != ':') { |
|
|
50
|
|
|
|
|
|
416
|
|
|
|
|
|
|
/* Failed again ? Try to remove main */ |
417
|
43
|
|
|
|
|
|
stash = "main"; |
418
|
43
|
|
|
|
|
|
stashlen = 4; |
419
|
43
|
100
|
|
|
|
|
if ((len < stashlen + 2) || strnNE(name, stash, stashlen) |
|
|
50
|
|
|
|
|
|
420
|
6
|
50
|
|
|
|
|
|| name[stashlen] != ':' || name[stashlen+1] != ':') |
|
|
50
|
|
|
|
|
|
421
|
|
|
|
|
|
|
goto done; |
422
|
|
|
|
|
|
|
} |
423
|
|
|
|
|
|
|
|
424
|
139
|
|
|
|
|
|
sv_setpvn(sv, "$", 1); |
425
|
139
|
|
|
|
|
|
stashlen += 2; |
426
|
139
|
|
|
|
|
|
sv_catpvn_nomg(sv, name + stashlen, len - stashlen); |
427
|
139
|
50
|
|
|
|
|
if (!indirect_find(sv, PL_oldbufptr, &pos)) |
428
|
0
|
|
|
|
|
|
goto done; |
429
|
|
|
|
|
|
|
} |
430
|
|
|
|
|
|
|
|
431
|
203
|
|
|
|
|
|
o = indirect_old_ck_rv2sv(aTHX_ o); |
432
|
|
|
|
|
|
|
|
433
|
203
|
|
|
|
|
|
indirect_map_store(o, pos, sv, CopLINE(&PL_compiling)); |
434
|
203
|
|
|
|
|
|
return o; |
435
|
|
|
|
|
|
|
} |
436
|
|
|
|
|
|
|
|
437
|
|
|
|
|
|
|
done: |
438
|
1340
|
|
|
|
|
|
o = indirect_old_ck_rv2sv(aTHX_ o); |
439
|
|
|
|
|
|
|
|
440
|
1340
|
|
|
|
|
|
indirect_map_delete(o); |
441
|
1340
|
|
|
|
|
|
return o; |
442
|
|
|
|
|
|
|
} |
443
|
|
|
|
|
|
|
|
444
|
|
|
|
|
|
|
/* ... ck_padany ........................................................... */ |
445
|
|
|
|
|
|
|
|
446
|
|
|
|
|
|
|
static OP *(*indirect_old_ck_padany)(pTHX_ OP *) = 0; |
447
|
|
|
|
|
|
|
|
448
|
12329
|
|
|
|
|
|
static OP *indirect_ck_padany(pTHX_ OP *o) { |
449
|
12329
|
|
|
|
|
|
o = indirect_old_ck_padany(aTHX_ o); |
450
|
|
|
|
|
|
|
|
451
|
12329
|
100
|
|
|
|
|
if (indirect_hint()) { |
452
|
|
|
|
|
|
|
SV *sv; |
453
|
1650
|
|
|
|
|
|
const char *s = PL_oldbufptr, *t = PL_bufptr - 1; |
454
|
|
|
|
|
|
|
|
455
|
2036
|
50
|
|
|
|
|
while (s < t && isSPACE(*s)) ++s; |
|
|
100
|
|
|
|
|
|
456
|
1650
|
100
|
|
|
|
|
if (*s == '$' && ++s <= t) { |
|
|
50
|
|
|
|
|
|
457
|
1836
|
100
|
|
|
|
|
while (s < t && isSPACE(*s)) ++s; |
|
|
100
|
|
|
|
|
|
458
|
3019
|
100
|
|
|
|
|
while (s < t && isSPACE(*t)) --t; |
|
|
100
|
|
|
|
|
|
459
|
1580
|
|
|
|
|
|
sv = sv_2mortal(newSVpvn("$", 1)); |
460
|
1580
|
|
|
|
|
|
sv_catpvn_nomg(sv, s, t - s + 1); |
461
|
1580
|
|
|
|
|
|
indirect_map_store(o, s - SvPVX_const(PL_linestr), |
462
|
|
|
|
|
|
|
sv, CopLINE(&PL_compiling)); |
463
|
1580
|
|
|
|
|
|
return o; |
464
|
|
|
|
|
|
|
} |
465
|
|
|
|
|
|
|
} |
466
|
|
|
|
|
|
|
|
467
|
10749
|
|
|
|
|
|
indirect_map_delete(o); |
468
|
10749
|
|
|
|
|
|
return o; |
469
|
|
|
|
|
|
|
} |
470
|
|
|
|
|
|
|
|
471
|
|
|
|
|
|
|
/* ... ck_scope ............................................................ */ |
472
|
|
|
|
|
|
|
|
473
|
|
|
|
|
|
|
static OP *(*indirect_old_ck_scope) (pTHX_ OP *) = 0; |
474
|
|
|
|
|
|
|
static OP *(*indirect_old_ck_lineseq)(pTHX_ OP *) = 0; |
475
|
|
|
|
|
|
|
|
476
|
30115
|
|
|
|
|
|
static OP *indirect_ck_scope(pTHX_ OP *o) { |
477
|
30115
|
|
|
|
|
|
OP *(*old_ck)(pTHX_ OP *) = 0; |
478
|
|
|
|
|
|
|
|
479
|
30115
|
|
|
|
|
|
switch (o->op_type) { |
480
|
0
|
|
|
|
|
|
case OP_SCOPE: old_ck = indirect_old_ck_scope; break; |
481
|
30115
|
|
|
|
|
|
case OP_LINESEQ: old_ck = indirect_old_ck_lineseq; break; |
482
|
|
|
|
|
|
|
} |
483
|
30115
|
|
|
|
|
|
o = old_ck(aTHX_ o); |
484
|
|
|
|
|
|
|
|
485
|
30115
|
100
|
|
|
|
|
if (indirect_hint()) { |
486
|
12597
|
|
|
|
|
|
indirect_map_store(o, PL_oldbufptr - SvPVX_const(PL_linestr), |
487
|
|
|
|
|
|
|
NULL, CopLINE(&PL_compiling)); |
488
|
12597
|
|
|
|
|
|
return o; |
489
|
|
|
|
|
|
|
} |
490
|
|
|
|
|
|
|
|
491
|
17518
|
|
|
|
|
|
indirect_map_delete(o); |
492
|
17518
|
|
|
|
|
|
return o; |
493
|
|
|
|
|
|
|
} |
494
|
|
|
|
|
|
|
|
495
|
|
|
|
|
|
|
/* We don't need to clean the map entries for leave ops because they can only |
496
|
|
|
|
|
|
|
* be created by mutating from a lineseq. */ |
497
|
|
|
|
|
|
|
|
498
|
|
|
|
|
|
|
/* ... ck_method ........................................................... */ |
499
|
|
|
|
|
|
|
|
500
|
|
|
|
|
|
|
static OP *(*indirect_old_ck_method)(pTHX_ OP *) = 0; |
501
|
|
|
|
|
|
|
|
502
|
2235
|
|
|
|
|
|
static OP *indirect_ck_method(pTHX_ OP *o) { |
503
|
2235
|
100
|
|
|
|
|
if (indirect_hint()) { |
504
|
1583
|
|
|
|
|
|
OP *op = cUNOPo->op_first; |
505
|
|
|
|
|
|
|
|
506
|
|
|
|
|
|
|
/* Indirect method call is only possible when the method is a bareword, so |
507
|
|
|
|
|
|
|
* don't trip up on $obj->$meth. */ |
508
|
1583
|
50
|
|
|
|
|
if (op && op->op_type == OP_CONST) { |
|
|
100
|
|
|
|
|
|
509
|
1499
|
|
|
|
|
|
const indirect_op_info_t *oi = indirect_map_fetch(op); |
510
|
|
|
|
|
|
|
STRLEN pos; |
511
|
|
|
|
|
|
|
line_t line; |
512
|
|
|
|
|
|
|
SV *sv; |
513
|
|
|
|
|
|
|
|
514
|
1499
|
50
|
|
|
|
|
if (!oi) |
515
|
0
|
|
|
|
|
|
goto done; |
516
|
|
|
|
|
|
|
|
517
|
1499
|
|
|
|
|
|
sv = sv_2mortal(newSVpvn(oi->buf, oi->len)); |
518
|
1499
|
|
|
|
|
|
pos = oi->pos; |
519
|
|
|
|
|
|
|
/* Keep the old line so that we really point to the first line of the |
520
|
|
|
|
|
|
|
* expression. */ |
521
|
1499
|
|
|
|
|
|
line = oi->line; |
522
|
|
|
|
|
|
|
|
523
|
1499
|
|
|
|
|
|
o = indirect_old_ck_method(aTHX_ o); |
524
|
|
|
|
|
|
|
/* o may now be a method_named */ |
525
|
|
|
|
|
|
|
|
526
|
1499
|
|
|
|
|
|
indirect_map_store(o, pos, sv, line); |
527
|
1499
|
|
|
|
|
|
return o; |
528
|
|
|
|
|
|
|
} |
529
|
|
|
|
|
|
|
} |
530
|
|
|
|
|
|
|
|
531
|
|
|
|
|
|
|
done: |
532
|
736
|
|
|
|
|
|
o = indirect_old_ck_method(aTHX_ o); |
533
|
|
|
|
|
|
|
|
534
|
736
|
|
|
|
|
|
indirect_map_delete(o); |
535
|
736
|
|
|
|
|
|
return o; |
536
|
|
|
|
|
|
|
} |
537
|
|
|
|
|
|
|
|
538
|
|
|
|
|
|
|
/* ... ck_method_named ..................................................... */ |
539
|
|
|
|
|
|
|
|
540
|
|
|
|
|
|
|
/* "use foo/no foo" compiles its call to import/unimport directly to a |
541
|
|
|
|
|
|
|
* method_named op. */ |
542
|
|
|
|
|
|
|
|
543
|
|
|
|
|
|
|
static OP *(*indirect_old_ck_method_named)(pTHX_ OP *) = 0; |
544
|
|
|
|
|
|
|
|
545
|
7308
|
|
|
|
|
|
static OP *indirect_ck_method_named(pTHX_ OP *o) { |
546
|
7308
|
100
|
|
|
|
|
if (indirect_hint()) { |
547
|
|
|
|
|
|
|
STRLEN pos; |
548
|
|
|
|
|
|
|
line_t line; |
549
|
|
|
|
|
|
|
SV *sv; |
550
|
|
|
|
|
|
|
|
551
|
4532
|
|
|
|
|
|
sv = cSVOPo_sv; |
552
|
4532
|
50
|
|
|
|
|
if (!SvPOK(sv) || (SvTYPE(sv) < SVt_PV)) |
|
|
50
|
|
|
|
|
|
553
|
|
|
|
|
|
|
goto done; |
554
|
4532
|
|
|
|
|
|
sv = sv_mortalcopy(sv); |
555
|
|
|
|
|
|
|
|
556
|
4532
|
100
|
|
|
|
|
if (!indirect_find(sv, PL_oldbufptr, &pos)) |
557
|
4499
|
|
|
|
|
|
goto done; |
558
|
33
|
|
|
|
|
|
line = CopLINE(&PL_compiling); |
559
|
|
|
|
|
|
|
|
560
|
33
|
|
|
|
|
|
o = indirect_old_ck_method_named(aTHX_ o); |
561
|
|
|
|
|
|
|
|
562
|
33
|
|
|
|
|
|
indirect_map_store(o, pos, sv, line); |
563
|
4532
|
|
|
|
|
|
return o; |
564
|
|
|
|
|
|
|
} |
565
|
|
|
|
|
|
|
|
566
|
|
|
|
|
|
|
done: |
567
|
7275
|
|
|
|
|
|
o = indirect_old_ck_method_named(aTHX_ o); |
568
|
|
|
|
|
|
|
|
569
|
7275
|
|
|
|
|
|
indirect_map_delete(o); |
570
|
7275
|
|
|
|
|
|
return o; |
571
|
|
|
|
|
|
|
} |
572
|
|
|
|
|
|
|
|
573
|
|
|
|
|
|
|
/* ... ck_entersub ......................................................... */ |
574
|
|
|
|
|
|
|
|
575
|
|
|
|
|
|
|
static OP *(*indirect_old_ck_entersub)(pTHX_ OP *) = 0; |
576
|
|
|
|
|
|
|
|
577
|
8180
|
|
|
|
|
|
static OP *indirect_ck_entersub(pTHX_ OP *o) { |
578
|
8180
|
|
|
|
|
|
SV *code = indirect_hint(); |
579
|
|
|
|
|
|
|
|
580
|
8180
|
|
|
|
|
|
o = indirect_old_ck_entersub(aTHX_ o); |
581
|
|
|
|
|
|
|
|
582
|
8180
|
100
|
|
|
|
|
if (code) { |
583
|
|
|
|
|
|
|
const indirect_op_info_t *moi, *ooi; |
584
|
|
|
|
|
|
|
OP *mop, *oop; |
585
|
|
|
|
|
|
|
LISTOP *lop; |
586
|
|
|
|
|
|
|
|
587
|
4657
|
|
|
|
|
|
oop = o; |
588
|
|
|
|
|
|
|
do { |
589
|
4698
|
|
|
|
|
|
lop = (LISTOP *) oop; |
590
|
4698
|
50
|
|
|
|
|
if (!(lop->op_flags & OPf_KIDS)) |
591
|
0
|
|
|
|
|
|
goto done; |
592
|
4698
|
|
|
|
|
|
oop = lop->op_first; |
593
|
4698
|
100
|
|
|
|
|
} while (oop->op_type != OP_PUSHMARK); |
594
|
4657
|
50
|
|
|
|
|
oop = OpSIBLING(oop); |
595
|
4657
|
|
|
|
|
|
mop = lop->op_last; |
596
|
|
|
|
|
|
|
|
597
|
4657
|
50
|
|
|
|
|
if (!oop) |
598
|
0
|
|
|
|
|
|
goto done; |
599
|
|
|
|
|
|
|
|
600
|
4657
|
100
|
|
|
|
|
switch (oop->op_type) { |
601
|
|
|
|
|
|
|
case OP_CONST: |
602
|
|
|
|
|
|
|
case OP_RV2SV: |
603
|
|
|
|
|
|
|
case OP_PADSV: |
604
|
|
|
|
|
|
|
case OP_SCOPE: |
605
|
|
|
|
|
|
|
case OP_LEAVE: |
606
|
4622
|
|
|
|
|
|
break; |
607
|
|
|
|
|
|
|
default: |
608
|
35
|
|
|
|
|
|
goto done; |
609
|
|
|
|
|
|
|
} |
610
|
|
|
|
|
|
|
|
611
|
4622
|
100
|
|
|
|
|
if (mop->op_type == OP_METHOD) |
612
|
84
|
|
|
|
|
|
mop = cUNOPx(mop)->op_first; |
613
|
4538
|
100
|
|
|
|
|
else if (mop->op_type != OP_METHOD_NAMED) |
614
|
19
|
|
|
|
|
|
goto done; |
615
|
|
|
|
|
|
|
|
616
|
4603
|
|
|
|
|
|
moi = indirect_map_fetch(mop); |
617
|
4603
|
100
|
|
|
|
|
if (!moi) |
618
|
3033
|
|
|
|
|
|
goto done; |
619
|
|
|
|
|
|
|
|
620
|
1570
|
|
|
|
|
|
ooi = indirect_map_fetch(oop); |
621
|
1570
|
100
|
|
|
|
|
if (!ooi) |
622
|
5
|
|
|
|
|
|
goto done; |
623
|
|
|
|
|
|
|
|
624
|
|
|
|
|
|
|
/* When positions are identical, the method and the object must have the |
625
|
|
|
|
|
|
|
* same name. But it also means that it is an indirect call, as "foo->foo" |
626
|
|
|
|
|
|
|
* results in different positions. */ |
627
|
1565
|
100
|
|
|
|
|
if ( moi->line < ooi->line |
628
|
1481
|
100
|
|
|
|
|
|| (moi->line == ooi->line && moi->pos <= ooi->pos)) { |
|
|
100
|
|
|
|
|
|
629
|
|
|
|
|
|
|
SV *file; |
630
|
1355
|
|
|
|
|
|
dSP; |
631
|
|
|
|
|
|
|
|
632
|
1355
|
|
|
|
|
|
ENTER; |
633
|
1355
|
|
|
|
|
|
SAVETMPS; |
634
|
|
|
|
|
|
|
|
635
|
|
|
|
|
|
|
#ifdef USE_ITHREADS |
636
|
|
|
|
|
|
|
file = sv_2mortal(newSVpv(CopFILE(&PL_compiling), 0)); |
637
|
|
|
|
|
|
|
#else |
638
|
1355
|
50
|
|
|
|
|
file = sv_mortalcopy(CopFILESV(&PL_compiling)); |
639
|
|
|
|
|
|
|
#endif |
640
|
|
|
|
|
|
|
|
641
|
1355
|
50
|
|
|
|
|
PUSHMARK(SP); |
642
|
1355
|
50
|
|
|
|
|
EXTEND(SP, 4); |
643
|
1355
|
|
|
|
|
|
mPUSHp(ooi->buf, ooi->len); |
644
|
1355
|
|
|
|
|
|
mPUSHp(moi->buf, moi->len); |
645
|
1355
|
|
|
|
|
|
PUSHs(file); |
646
|
1355
|
|
|
|
|
|
mPUSHu(moi->line); |
647
|
1355
|
|
|
|
|
|
PUTBACK; |
648
|
|
|
|
|
|
|
|
649
|
1355
|
|
|
|
|
|
indirect_call_sv(code, G_VOID); |
650
|
|
|
|
|
|
|
|
651
|
1344
|
|
|
|
|
|
PUTBACK; |
652
|
|
|
|
|
|
|
|
653
|
1344
|
50
|
|
|
|
|
FREETMPS; |
654
|
1344
|
|
|
|
|
|
LEAVE; |
655
|
|
|
|
|
|
|
} |
656
|
|
|
|
|
|
|
} |
657
|
|
|
|
|
|
|
|
658
|
|
|
|
|
|
|
done: |
659
|
8169
|
|
|
|
|
|
return o; |
660
|
|
|
|
|
|
|
} |
661
|
|
|
|
|
|
|
|
662
|
|
|
|
|
|
|
/* --- Module setup/teardown ----------------------------------------------- */ |
663
|
|
|
|
|
|
|
|
664
|
34
|
|
|
|
|
|
static void xsh_user_global_setup(pTHX) { |
665
|
34
|
|
|
|
|
|
xsh_ck_replace(OP_CONST, indirect_ck_const, &indirect_old_ck_const); |
666
|
34
|
|
|
|
|
|
xsh_ck_replace(OP_RV2SV, indirect_ck_rv2sv, &indirect_old_ck_rv2sv); |
667
|
34
|
|
|
|
|
|
xsh_ck_replace(OP_PADANY, indirect_ck_padany, &indirect_old_ck_padany); |
668
|
34
|
|
|
|
|
|
xsh_ck_replace(OP_SCOPE, indirect_ck_scope, &indirect_old_ck_scope); |
669
|
34
|
|
|
|
|
|
xsh_ck_replace(OP_LINESEQ, indirect_ck_scope, &indirect_old_ck_lineseq); |
670
|
|
|
|
|
|
|
|
671
|
34
|
|
|
|
|
|
xsh_ck_replace(OP_METHOD, indirect_ck_method, |
672
|
|
|
|
|
|
|
&indirect_old_ck_method); |
673
|
34
|
|
|
|
|
|
xsh_ck_replace(OP_METHOD_NAMED, indirect_ck_method_named, |
674
|
|
|
|
|
|
|
&indirect_old_ck_method_named); |
675
|
34
|
|
|
|
|
|
xsh_ck_replace(OP_ENTERSUB, indirect_ck_entersub, |
676
|
|
|
|
|
|
|
&indirect_old_ck_entersub); |
677
|
|
|
|
|
|
|
|
678
|
34
|
|
|
|
|
|
return; |
679
|
|
|
|
|
|
|
} |
680
|
|
|
|
|
|
|
|
681
|
34
|
|
|
|
|
|
static void xsh_user_local_setup(pTHX_ xsh_user_cxt_t *cxt) { |
682
|
|
|
|
|
|
|
HV *stash; |
683
|
|
|
|
|
|
|
|
684
|
34
|
|
|
|
|
|
stash = gv_stashpvn(XSH_PACKAGE, XSH_PACKAGE_LEN, 1); |
685
|
34
|
|
|
|
|
|
newCONSTSUB(stash, "I_THREADSAFE", newSVuv(XSH_THREADSAFE)); |
686
|
34
|
|
|
|
|
|
newCONSTSUB(stash, "I_FORKSAFE", newSVuv(XSH_FORKSAFE)); |
687
|
|
|
|
|
|
|
|
688
|
34
|
|
|
|
|
|
cxt->map = ptable_new(32); |
689
|
34
|
|
|
|
|
|
cxt->global_code = NULL; |
690
|
|
|
|
|
|
|
|
691
|
34
|
|
|
|
|
|
return; |
692
|
|
|
|
|
|
|
} |
693
|
|
|
|
|
|
|
|
694
|
34
|
|
|
|
|
|
static void xsh_user_local_teardown(pTHX_ xsh_user_cxt_t *cxt) { |
695
|
34
|
|
|
|
|
|
SvREFCNT_dec(cxt->global_code); |
696
|
34
|
|
|
|
|
|
cxt->global_code = NULL; |
697
|
|
|
|
|
|
|
|
698
|
34
|
|
|
|
|
|
ptable_free(cxt->map); |
699
|
34
|
|
|
|
|
|
cxt->map = NULL; |
700
|
|
|
|
|
|
|
|
701
|
34
|
|
|
|
|
|
return; |
702
|
|
|
|
|
|
|
} |
703
|
|
|
|
|
|
|
|
704
|
34
|
|
|
|
|
|
static void xsh_user_global_teardown(pTHX) { |
705
|
34
|
|
|
|
|
|
xsh_ck_restore(OP_CONST, &indirect_old_ck_const); |
706
|
34
|
|
|
|
|
|
xsh_ck_restore(OP_RV2SV, &indirect_old_ck_rv2sv); |
707
|
34
|
|
|
|
|
|
xsh_ck_restore(OP_PADANY, &indirect_old_ck_padany); |
708
|
34
|
|
|
|
|
|
xsh_ck_restore(OP_SCOPE, &indirect_old_ck_scope); |
709
|
34
|
|
|
|
|
|
xsh_ck_restore(OP_LINESEQ, &indirect_old_ck_lineseq); |
710
|
|
|
|
|
|
|
|
711
|
34
|
|
|
|
|
|
xsh_ck_restore(OP_METHOD, &indirect_old_ck_method); |
712
|
34
|
|
|
|
|
|
xsh_ck_restore(OP_METHOD_NAMED, &indirect_old_ck_method_named); |
713
|
34
|
|
|
|
|
|
xsh_ck_restore(OP_ENTERSUB, &indirect_old_ck_entersub); |
714
|
|
|
|
|
|
|
|
715
|
34
|
|
|
|
|
|
return; |
716
|
|
|
|
|
|
|
} |
717
|
|
|
|
|
|
|
|
718
|
|
|
|
|
|
|
/* --- XS ------------------------------------------------------------------ */ |
719
|
|
|
|
|
|
|
|
720
|
|
|
|
|
|
|
MODULE = indirect PACKAGE = indirect |
721
|
|
|
|
|
|
|
|
722
|
|
|
|
|
|
|
PROTOTYPES: ENABLE |
723
|
|
|
|
|
|
|
|
724
|
|
|
|
|
|
|
BOOT: |
725
|
|
|
|
|
|
|
{ |
726
|
34
|
|
|
|
|
|
xsh_setup(); |
727
|
|
|
|
|
|
|
} |
728
|
|
|
|
|
|
|
|
729
|
|
|
|
|
|
|
#if XSH_THREADSAFE |
730
|
|
|
|
|
|
|
|
731
|
|
|
|
|
|
|
void |
732
|
|
|
|
|
|
|
CLONE(...) |
733
|
|
|
|
|
|
|
PROTOTYPE: DISABLE |
734
|
|
|
|
|
|
|
PPCODE: |
735
|
|
|
|
|
|
|
xsh_clone(); |
736
|
|
|
|
|
|
|
XSRETURN(0); |
737
|
|
|
|
|
|
|
|
738
|
|
|
|
|
|
|
#endif /* XSH_THREADSAFE */ |
739
|
|
|
|
|
|
|
|
740
|
|
|
|
|
|
|
SV * |
741
|
|
|
|
|
|
|
_tag(SV *code) |
742
|
|
|
|
|
|
|
PROTOTYPE: $ |
743
|
|
|
|
|
|
|
CODE: |
744
|
5101
|
100
|
|
|
|
|
if (!SvOK(code)) |
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
745
|
2023
|
|
|
|
|
|
code = NULL; |
746
|
3078
|
50
|
|
|
|
|
else if (SvROK(code)) |
747
|
3078
|
|
|
|
|
|
code = SvRV(code); |
748
|
5101
|
|
|
|
|
|
RETVAL = xsh_hints_tag(code); |
749
|
|
|
|
|
|
|
OUTPUT: |
750
|
|
|
|
|
|
|
RETVAL |
751
|
|
|
|
|
|
|
|
752
|
|
|
|
|
|
|
void |
753
|
|
|
|
|
|
|
_global(SV *code) |
754
|
|
|
|
|
|
|
PROTOTYPE: $ |
755
|
|
|
|
|
|
|
PPCODE: |
756
|
5
|
50
|
|
|
|
|
if (!SvOK(code)) |
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
757
|
0
|
|
|
|
|
|
code = NULL; |
758
|
5
|
50
|
|
|
|
|
else if (SvROK(code)) |
759
|
5
|
|
|
|
|
|
code = SvRV(code); |
760
|
|
|
|
|
|
|
{ |
761
|
|
|
|
|
|
|
dXSH_CXT; |
762
|
5
|
|
|
|
|
|
SvREFCNT_dec(XSH_CXT.global_code); |
763
|
5
|
|
|
|
|
|
XSH_CXT.global_code = SvREFCNT_inc(code); |
764
|
|
|
|
|
|
|
} |
765
|
5
|
|
|
|
|
|
XSRETURN(0); |