| 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); |