line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
/* This file is part of the Scope::Upper Perl module. |
2
|
|
|
|
|
|
|
* See http://search.cpan.org/dist/Scope-Upper/ */ |
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 "Scope::Upper" |
12
|
|
|
|
|
|
|
|
13
|
|
|
|
|
|
|
#include "xsh/caps.h" |
14
|
|
|
|
|
|
|
#include "xsh/util.h" |
15
|
|
|
|
|
|
|
#include "xsh/debug.h" |
16
|
|
|
|
|
|
|
|
17
|
|
|
|
|
|
|
/* --- Compatibility ------------------------------------------------------- */ |
18
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
/* perl 5.23.8 onwards has a revamped context system */ |
20
|
|
|
|
|
|
|
#define SU_HAS_NEW_CXT XSH_HAS_PERL(5, 23, 8) |
21
|
|
|
|
|
|
|
|
22
|
|
|
|
|
|
|
#ifndef dVAR |
23
|
|
|
|
|
|
|
# define dVAR dNOOP |
24
|
|
|
|
|
|
|
#endif |
25
|
|
|
|
|
|
|
|
26
|
|
|
|
|
|
|
#ifndef MUTABLE_SV |
27
|
|
|
|
|
|
|
# define MUTABLE_SV(S) ((SV *) (S)) |
28
|
|
|
|
|
|
|
#endif |
29
|
|
|
|
|
|
|
|
30
|
|
|
|
|
|
|
#ifndef MUTABLE_AV |
31
|
|
|
|
|
|
|
# define MUTABLE_AV(A) ((AV *) (A)) |
32
|
|
|
|
|
|
|
#endif |
33
|
|
|
|
|
|
|
|
34
|
|
|
|
|
|
|
#ifndef MUTABLE_CV |
35
|
|
|
|
|
|
|
# define MUTABLE_CV(C) ((CV *) (C)) |
36
|
|
|
|
|
|
|
#endif |
37
|
|
|
|
|
|
|
|
38
|
|
|
|
|
|
|
#ifndef PERL_UNUSED_VAR |
39
|
|
|
|
|
|
|
# define PERL_UNUSED_VAR(V) |
40
|
|
|
|
|
|
|
#endif |
41
|
|
|
|
|
|
|
|
42
|
|
|
|
|
|
|
#ifndef Newx |
43
|
|
|
|
|
|
|
# define Newx(v, n, c) New(0, v, n, c) |
44
|
|
|
|
|
|
|
#endif |
45
|
|
|
|
|
|
|
|
46
|
|
|
|
|
|
|
#ifdef DEBUGGING |
47
|
|
|
|
|
|
|
# ifdef PoisonNew |
48
|
|
|
|
|
|
|
# define SU_POISON(D, N, T) PoisonNew((D), (N), T) |
49
|
|
|
|
|
|
|
# elif defined(Poison) |
50
|
|
|
|
|
|
|
# define SU_POISON(D, N, T) Poison((D), (N), T) |
51
|
|
|
|
|
|
|
# endif |
52
|
|
|
|
|
|
|
#endif |
53
|
|
|
|
|
|
|
#ifndef SU_POISON |
54
|
|
|
|
|
|
|
# define SU_POISON(D, N, T) NOOP |
55
|
|
|
|
|
|
|
#endif |
56
|
|
|
|
|
|
|
|
57
|
|
|
|
|
|
|
#ifndef newSV_type |
58
|
|
|
|
|
|
|
static SV *su_newSV_type(pTHX_ svtype t) { |
59
|
|
|
|
|
|
|
SV *sv = newSV(0); |
60
|
|
|
|
|
|
|
SvUPGRADE(sv, t); |
61
|
|
|
|
|
|
|
return sv; |
62
|
|
|
|
|
|
|
} |
63
|
|
|
|
|
|
|
# define newSV_type(T) su_newSV_type(aTHX_ (T)) |
64
|
|
|
|
|
|
|
#endif |
65
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
#ifdef newSVpvn_flags |
67
|
|
|
|
|
|
|
# define su_newmortal_pvn(S, L) newSVpvn_flags((S), (L), SVs_TEMP) |
68
|
|
|
|
|
|
|
#else |
69
|
|
|
|
|
|
|
# define su_newmortal_pvn(S, L) sv_2mortal(newSVpvn((S), (L))) |
70
|
|
|
|
|
|
|
#endif |
71
|
|
|
|
|
|
|
#define su_newmortal_pvs(S) su_newmortal_pvn((S), sizeof(S)-1) |
72
|
|
|
|
|
|
|
|
73
|
|
|
|
|
|
|
#ifndef SvPV_const |
74
|
|
|
|
|
|
|
# define SvPV_const(S, L) SvPV(S, L) |
75
|
|
|
|
|
|
|
#endif |
76
|
|
|
|
|
|
|
|
77
|
|
|
|
|
|
|
#ifndef SvPVX_const |
78
|
|
|
|
|
|
|
# define SvPVX_const(S) SvPVX(S) |
79
|
|
|
|
|
|
|
#endif |
80
|
|
|
|
|
|
|
|
81
|
|
|
|
|
|
|
#ifndef SvPV_nolen_const |
82
|
|
|
|
|
|
|
# define SvPV_nolen_const(S) SvPV_nolen(S) |
83
|
|
|
|
|
|
|
#endif |
84
|
|
|
|
|
|
|
|
85
|
|
|
|
|
|
|
#ifndef SvREFCNT_inc_simple_void |
86
|
|
|
|
|
|
|
# define SvREFCNT_inc_simple_void(sv) ((void) SvREFCNT_inc(sv)) |
87
|
|
|
|
|
|
|
#endif |
88
|
|
|
|
|
|
|
|
89
|
|
|
|
|
|
|
#ifndef mPUSHi |
90
|
|
|
|
|
|
|
# define mPUSHi(I) PUSHs(sv_2mortal(newSViv(I))) |
91
|
|
|
|
|
|
|
#endif |
92
|
|
|
|
|
|
|
|
93
|
|
|
|
|
|
|
#ifndef GvCV_set |
94
|
|
|
|
|
|
|
# define GvCV_set(G, C) (GvCV(G) = (C)) |
95
|
|
|
|
|
|
|
#endif |
96
|
|
|
|
|
|
|
|
97
|
|
|
|
|
|
|
#ifndef CvGV_set |
98
|
|
|
|
|
|
|
# define CvGV_set(C, G) (CvGV(C) = (G)) |
99
|
|
|
|
|
|
|
#endif |
100
|
|
|
|
|
|
|
|
101
|
|
|
|
|
|
|
#ifndef CvSTASH_set |
102
|
|
|
|
|
|
|
# define CvSTASH_set(C, S) (CvSTASH(C) = (S)) |
103
|
|
|
|
|
|
|
#endif |
104
|
|
|
|
|
|
|
|
105
|
|
|
|
|
|
|
#ifndef CvISXSUB |
106
|
|
|
|
|
|
|
# define CvISXSUB(C) CvXSUB(C) |
107
|
|
|
|
|
|
|
#endif |
108
|
|
|
|
|
|
|
|
109
|
|
|
|
|
|
|
#ifndef PadlistARRAY |
110
|
|
|
|
|
|
|
# define PadlistARRAY(P) AvARRAY(P) |
111
|
|
|
|
|
|
|
# define PadARRAY(P) AvARRAY(P) |
112
|
|
|
|
|
|
|
#endif |
113
|
|
|
|
|
|
|
|
114
|
|
|
|
|
|
|
#ifndef CxHASARGS |
115
|
|
|
|
|
|
|
# define CxHASARGS(C) ((C)->blk_sub.hasargs) |
116
|
|
|
|
|
|
|
#endif |
117
|
|
|
|
|
|
|
|
118
|
|
|
|
|
|
|
#ifndef CxGIMME |
119
|
|
|
|
|
|
|
# ifdef G_WANT |
120
|
|
|
|
|
|
|
# define CxGIMME(C) ((C)->blk_gimme & G_WANT) |
121
|
|
|
|
|
|
|
# else |
122
|
|
|
|
|
|
|
# define CxGIMME(C) ((C)->blk_gimme) |
123
|
|
|
|
|
|
|
# endif |
124
|
|
|
|
|
|
|
#endif |
125
|
|
|
|
|
|
|
|
126
|
|
|
|
|
|
|
#ifndef CxOLD_OP_TYPE |
127
|
|
|
|
|
|
|
# define CxOLD_OP_TYPE(C) (C)->blk_eval.old_op_type |
128
|
|
|
|
|
|
|
#endif |
129
|
|
|
|
|
|
|
|
130
|
|
|
|
|
|
|
#ifndef OutCopFILE |
131
|
|
|
|
|
|
|
# define OutCopFILE(C) CopFILE(C) |
132
|
|
|
|
|
|
|
#endif |
133
|
|
|
|
|
|
|
|
134
|
|
|
|
|
|
|
#ifndef OutCopFILE_len |
135
|
|
|
|
|
|
|
# define OutCopFILE_len(C) strlen(OutCopFILE(C)) |
136
|
|
|
|
|
|
|
#endif |
137
|
|
|
|
|
|
|
|
138
|
|
|
|
|
|
|
#ifndef CopHINTS_get |
139
|
|
|
|
|
|
|
# define CopHINTS_get(C) ((I32) (C)->op_private & HINT_PRIVATE_MASK) |
140
|
|
|
|
|
|
|
#endif |
141
|
|
|
|
|
|
|
|
142
|
|
|
|
|
|
|
#ifndef CopHINTHASH_get |
143
|
|
|
|
|
|
|
# define CopHINTHASH_get(C) (C)->cop_hints_hash |
144
|
|
|
|
|
|
|
#endif |
145
|
|
|
|
|
|
|
|
146
|
|
|
|
|
|
|
#ifndef cophh_2hv |
147
|
|
|
|
|
|
|
# define COPHH struct refcounted_he |
148
|
|
|
|
|
|
|
# define cophh_2hv(H, F) Perl_refcounted_he_chain_2hv(aTHX_ (H)) |
149
|
|
|
|
|
|
|
#endif |
150
|
|
|
|
|
|
|
|
151
|
|
|
|
|
|
|
#ifndef HvNAME_get |
152
|
|
|
|
|
|
|
# define HvNAME_get(H) HvNAME(H) |
153
|
|
|
|
|
|
|
#endif |
154
|
|
|
|
|
|
|
|
155
|
|
|
|
|
|
|
#ifndef HvNAMELEN |
156
|
|
|
|
|
|
|
# define HvNAMELEN(H) strlen(HvNAME(H)) |
157
|
|
|
|
|
|
|
#endif |
158
|
|
|
|
|
|
|
|
159
|
|
|
|
|
|
|
#ifndef gv_fetchpvn_flags |
160
|
|
|
|
|
|
|
# define gv_fetchpvn_flags(A, B, C, D) gv_fetchpv((A), (C), (D)) |
161
|
|
|
|
|
|
|
#endif |
162
|
|
|
|
|
|
|
|
163
|
|
|
|
|
|
|
#ifndef hv_fetchs |
164
|
|
|
|
|
|
|
# define hv_fetchs(H, K, L) hv_fetch((H), (K), sizeof(K)-1, (L)) |
165
|
|
|
|
|
|
|
#endif |
166
|
|
|
|
|
|
|
|
167
|
|
|
|
|
|
|
#ifndef OP_GIMME_REVERSE |
168
|
|
|
|
|
|
|
static U8 su_op_gimme_reverse(U8 gimme) { |
169
|
|
|
|
|
|
|
switch (gimme) { |
170
|
|
|
|
|
|
|
case G_VOID: |
171
|
|
|
|
|
|
|
return OPf_WANT_VOID; |
172
|
|
|
|
|
|
|
case G_ARRAY: |
173
|
|
|
|
|
|
|
return OPf_WANT_LIST; |
174
|
|
|
|
|
|
|
default: |
175
|
|
|
|
|
|
|
break; |
176
|
|
|
|
|
|
|
} |
177
|
|
|
|
|
|
|
|
178
|
|
|
|
|
|
|
return OPf_WANT_SCALAR; |
179
|
|
|
|
|
|
|
} |
180
|
|
|
|
|
|
|
#define OP_GIMME_REVERSE(G) su_op_gimme_reverse(G) |
181
|
|
|
|
|
|
|
#endif |
182
|
|
|
|
|
|
|
|
183
|
|
|
|
|
|
|
#ifndef OpSIBLING |
184
|
|
|
|
|
|
|
# ifdef OP_SIBLING |
185
|
|
|
|
|
|
|
# define OpSIBLING(O) OP_SIBLING(O) |
186
|
|
|
|
|
|
|
# else |
187
|
|
|
|
|
|
|
# define OpSIBLING(O) ((O)->op_sibling) |
188
|
|
|
|
|
|
|
# endif |
189
|
|
|
|
|
|
|
#endif |
190
|
|
|
|
|
|
|
|
191
|
|
|
|
|
|
|
#ifndef PERL_MAGIC_tied |
192
|
|
|
|
|
|
|
# define PERL_MAGIC_tied 'P' |
193
|
|
|
|
|
|
|
#endif |
194
|
|
|
|
|
|
|
|
195
|
|
|
|
|
|
|
#ifndef PERL_MAGIC_env |
196
|
|
|
|
|
|
|
# define PERL_MAGIC_env 'E' |
197
|
|
|
|
|
|
|
#endif |
198
|
|
|
|
|
|
|
|
199
|
|
|
|
|
|
|
#ifndef NEGATIVE_INDICES_VAR |
200
|
|
|
|
|
|
|
# define NEGATIVE_INDICES_VAR "NEGATIVE_INDICES" |
201
|
|
|
|
|
|
|
#endif |
202
|
|
|
|
|
|
|
|
203
|
|
|
|
|
|
|
/* --- Error messages ------------------------------------------------------ */ |
204
|
|
|
|
|
|
|
|
205
|
|
|
|
|
|
|
static const char su_stack_smash[] = "Cannot target a scope outside of the current stack"; |
206
|
|
|
|
|
|
|
static const char su_no_such_target[] = "No targetable %s scope in the current stack"; |
207
|
|
|
|
|
|
|
|
208
|
|
|
|
|
|
|
/* --- Unique context ID global storage ------------------------------------ */ |
209
|
|
|
|
|
|
|
|
210
|
|
|
|
|
|
|
/* ... Sequence ID counter ................................................. */ |
211
|
|
|
|
|
|
|
|
212
|
|
|
|
|
|
|
typedef struct { |
213
|
|
|
|
|
|
|
UV *seqs; |
214
|
|
|
|
|
|
|
STRLEN size; |
215
|
|
|
|
|
|
|
} su_uv_array; |
216
|
|
|
|
|
|
|
|
217
|
|
|
|
|
|
|
static su_uv_array su_uid_seq_counter; |
218
|
|
|
|
|
|
|
|
219
|
|
|
|
|
|
|
#ifdef USE_ITHREADS |
220
|
|
|
|
|
|
|
|
221
|
|
|
|
|
|
|
static perl_mutex su_uid_seq_counter_mutex; |
222
|
|
|
|
|
|
|
|
223
|
|
|
|
|
|
|
#endif /* USE_ITHREADS */ |
224
|
|
|
|
|
|
|
|
225
|
823
|
|
|
|
|
|
static UV su_uid_seq_next(pTHX_ UV depth) { |
226
|
|
|
|
|
|
|
#define su_uid_seq_next(D) su_uid_seq_next(aTHX_ (D)) |
227
|
|
|
|
|
|
|
UV seq; |
228
|
|
|
|
|
|
|
UV *seqs; |
229
|
|
|
|
|
|
|
|
230
|
|
|
|
|
|
|
XSH_LOCK(&su_uid_seq_counter_mutex); |
231
|
|
|
|
|
|
|
|
232
|
823
|
|
|
|
|
|
seqs = su_uid_seq_counter.seqs; |
233
|
|
|
|
|
|
|
|
234
|
823
|
100
|
|
|
|
|
if (depth >= su_uid_seq_counter.size) { |
235
|
|
|
|
|
|
|
UV i; |
236
|
|
|
|
|
|
|
|
237
|
27
|
|
|
|
|
|
seqs = PerlMemShared_realloc(seqs, (depth + 1) * sizeof(UV)); |
238
|
90
|
100
|
|
|
|
|
for (i = su_uid_seq_counter.size; i <= depth; ++i) |
239
|
63
|
|
|
|
|
|
seqs[i] = 0; |
240
|
|
|
|
|
|
|
|
241
|
27
|
|
|
|
|
|
su_uid_seq_counter.seqs = seqs; |
242
|
27
|
|
|
|
|
|
su_uid_seq_counter.size = depth + 1; |
243
|
|
|
|
|
|
|
} |
244
|
|
|
|
|
|
|
|
245
|
823
|
|
|
|
|
|
seq = ++seqs[depth]; |
246
|
|
|
|
|
|
|
|
247
|
|
|
|
|
|
|
XSH_UNLOCK(&su_uid_seq_counter_mutex); |
248
|
|
|
|
|
|
|
|
249
|
823
|
|
|
|
|
|
return seq; |
250
|
|
|
|
|
|
|
} |
251
|
|
|
|
|
|
|
|
252
|
|
|
|
|
|
|
/* ... UID storage ......................................................... */ |
253
|
|
|
|
|
|
|
|
254
|
|
|
|
|
|
|
typedef struct { |
255
|
|
|
|
|
|
|
UV seq; |
256
|
|
|
|
|
|
|
U32 flags; |
257
|
|
|
|
|
|
|
} su_uid; |
258
|
|
|
|
|
|
|
|
259
|
|
|
|
|
|
|
#define SU_UID_ACTIVE 1 |
260
|
|
|
|
|
|
|
|
261
|
3588
|
|
|
|
|
|
static UV su_uid_depth(pTHX_ I32 cxix) { |
262
|
|
|
|
|
|
|
#define su_uid_depth(I) su_uid_depth(aTHX_ (I)) |
263
|
|
|
|
|
|
|
const PERL_SI *si; |
264
|
|
|
|
|
|
|
UV depth; |
265
|
|
|
|
|
|
|
|
266
|
3588
|
|
|
|
|
|
depth = cxix; |
267
|
3592
|
100
|
|
|
|
|
for (si = PL_curstackinfo->si_prev; si; si = si->si_prev) |
268
|
4
|
|
|
|
|
|
depth += si->si_cxix + 1; |
269
|
|
|
|
|
|
|
|
270
|
3588
|
|
|
|
|
|
return depth; |
271
|
|
|
|
|
|
|
} |
272
|
|
|
|
|
|
|
|
273
|
|
|
|
|
|
|
typedef struct { |
274
|
|
|
|
|
|
|
su_uid *map; |
275
|
|
|
|
|
|
|
STRLEN used; |
276
|
|
|
|
|
|
|
STRLEN alloc; |
277
|
|
|
|
|
|
|
} su_uid_storage; |
278
|
|
|
|
|
|
|
|
279
|
2749
|
|
|
|
|
|
static void su_uid_storage_dup(pTHX_ su_uid_storage *new_cxt, const su_uid_storage *old_cxt, UV max_depth) { |
280
|
|
|
|
|
|
|
#define su_uid_storage_dup(N, O, D) su_uid_storage_dup(aTHX_ (N), (O), (D)) |
281
|
2749
|
|
|
|
|
|
su_uid *old_map = old_cxt->map; |
282
|
|
|
|
|
|
|
|
283
|
2749
|
100
|
|
|
|
|
if (old_map) { |
284
|
503
|
|
|
|
|
|
su_uid *new_map = new_cxt->map; |
285
|
503
|
|
|
|
|
|
STRLEN old_used = old_cxt->used; |
286
|
|
|
|
|
|
|
STRLEN new_used, new_alloc; |
287
|
|
|
|
|
|
|
STRLEN i; |
288
|
|
|
|
|
|
|
|
289
|
503
|
|
|
|
|
|
new_used = max_depth < old_used ? max_depth : old_used; |
290
|
503
|
|
|
|
|
|
new_cxt->used = new_used; |
291
|
|
|
|
|
|
|
|
292
|
503
|
100
|
|
|
|
|
if (new_used <= new_cxt->alloc) { |
293
|
241
|
|
|
|
|
|
new_alloc = new_cxt->alloc; |
294
|
|
|
|
|
|
|
} else { |
295
|
262
|
|
|
|
|
|
new_alloc = new_used; |
296
|
262
|
50
|
|
|
|
|
Renew(new_map, new_alloc, su_uid); |
297
|
262
|
|
|
|
|
|
new_cxt->map = new_map; |
298
|
262
|
|
|
|
|
|
new_cxt->alloc = new_alloc; |
299
|
|
|
|
|
|
|
} |
300
|
|
|
|
|
|
|
|
301
|
13433
|
100
|
|
|
|
|
for (i = 0; i < new_alloc; ++i) { |
302
|
12930
|
|
|
|
|
|
su_uid *new_uid = new_map + i; |
303
|
|
|
|
|
|
|
|
304
|
12930
|
100
|
|
|
|
|
if (i < new_used) { /* => i < max_depth && i < old_used */ |
305
|
8604
|
|
|
|
|
|
su_uid *old_uid = old_map + i; |
306
|
|
|
|
|
|
|
|
307
|
8604
|
50
|
|
|
|
|
if (old_uid && (old_uid->flags & SU_UID_ACTIVE)) { |
|
|
100
|
|
|
|
|
|
308
|
1658
|
|
|
|
|
|
*new_uid = *old_uid; |
309
|
1658
|
|
|
|
|
|
continue; |
310
|
|
|
|
|
|
|
} |
311
|
|
|
|
|
|
|
} |
312
|
|
|
|
|
|
|
|
313
|
11272
|
|
|
|
|
|
new_uid->seq = 0; |
314
|
11272
|
|
|
|
|
|
new_uid->flags = 0; |
315
|
|
|
|
|
|
|
} |
316
|
|
|
|
|
|
|
} |
317
|
|
|
|
|
|
|
|
318
|
2749
|
|
|
|
|
|
return; |
319
|
|
|
|
|
|
|
} |
320
|
|
|
|
|
|
|
|
321
|
|
|
|
|
|
|
/* --- unwind() global storage --------------------------------------------- */ |
322
|
|
|
|
|
|
|
|
323
|
|
|
|
|
|
|
typedef struct { |
324
|
|
|
|
|
|
|
I32 cxix; |
325
|
|
|
|
|
|
|
I32 items; |
326
|
|
|
|
|
|
|
SV **savesp; |
327
|
|
|
|
|
|
|
LISTOP return_op; |
328
|
|
|
|
|
|
|
OP proxy_op; |
329
|
|
|
|
|
|
|
} su_unwind_storage; |
330
|
|
|
|
|
|
|
|
331
|
|
|
|
|
|
|
/* --- yield() global storage ---------------------------------------------- */ |
332
|
|
|
|
|
|
|
|
333
|
|
|
|
|
|
|
typedef struct { |
334
|
|
|
|
|
|
|
I32 cxix; |
335
|
|
|
|
|
|
|
I32 items; |
336
|
|
|
|
|
|
|
SV **savesp; |
337
|
|
|
|
|
|
|
UNOP leave_op; |
338
|
|
|
|
|
|
|
OP proxy_op; |
339
|
|
|
|
|
|
|
} su_yield_storage; |
340
|
|
|
|
|
|
|
|
341
|
|
|
|
|
|
|
/* --- uplevel() data tokens and global storage ---------------------------- */ |
342
|
|
|
|
|
|
|
|
343
|
|
|
|
|
|
|
#define SU_UPLEVEL_HIJACKS_RUNOPS XSH_HAS_PERL(5, 8, 0) |
344
|
|
|
|
|
|
|
|
345
|
|
|
|
|
|
|
typedef struct { |
346
|
|
|
|
|
|
|
void *next; |
347
|
|
|
|
|
|
|
|
348
|
|
|
|
|
|
|
su_uid_storage tmp_uid_storage; |
349
|
|
|
|
|
|
|
su_uid_storage old_uid_storage; |
350
|
|
|
|
|
|
|
|
351
|
|
|
|
|
|
|
I32 cxix; |
352
|
|
|
|
|
|
|
|
353
|
|
|
|
|
|
|
CV *callback; |
354
|
|
|
|
|
|
|
CV *renamed; |
355
|
|
|
|
|
|
|
|
356
|
|
|
|
|
|
|
#if SU_HAS_NEW_CXT |
357
|
|
|
|
|
|
|
U8 *cxtypes; /* array of saved context types */ |
358
|
|
|
|
|
|
|
I32 gap; /* how many contexts have temporarily CXt_NULLed out*/ |
359
|
|
|
|
|
|
|
AV* argarray; /* the PL_curpad[0] of the uplevel sub */ |
360
|
|
|
|
|
|
|
#else |
361
|
|
|
|
|
|
|
I32 target_depth; |
362
|
|
|
|
|
|
|
CV *target; |
363
|
|
|
|
|
|
|
PERL_SI *si; |
364
|
|
|
|
|
|
|
PERL_SI *old_curstackinfo; |
365
|
|
|
|
|
|
|
AV *old_mainstack; |
366
|
|
|
|
|
|
|
OP *old_op; |
367
|
|
|
|
|
|
|
bool old_catch; |
368
|
|
|
|
|
|
|
bool died; |
369
|
|
|
|
|
|
|
#endif |
370
|
|
|
|
|
|
|
|
371
|
|
|
|
|
|
|
COP *old_curcop; |
372
|
|
|
|
|
|
|
|
373
|
|
|
|
|
|
|
#if SU_UPLEVEL_HIJACKS_RUNOPS |
374
|
|
|
|
|
|
|
runops_proc_t old_runops; |
375
|
|
|
|
|
|
|
#endif |
376
|
|
|
|
|
|
|
} su_uplevel_ud; |
377
|
|
|
|
|
|
|
|
378
|
|
|
|
|
|
|
#if SU_HAS_NEW_CXT |
379
|
|
|
|
|
|
|
/* used to flag a context stack entry whose type has been temporarily |
380
|
|
|
|
|
|
|
* set to CXt_NULL. It relies on perl not using this value for real |
381
|
|
|
|
|
|
|
* CXt_NULL entries. |
382
|
|
|
|
|
|
|
*/ |
383
|
|
|
|
|
|
|
# define CXp_SU_UPLEVEL_NULLED 0x20 |
384
|
|
|
|
|
|
|
#endif |
385
|
|
|
|
|
|
|
|
386
|
242
|
|
|
|
|
|
static su_uplevel_ud *su_uplevel_ud_new(pTHX) { |
387
|
|
|
|
|
|
|
#define su_uplevel_ud_new() su_uplevel_ud_new(aTHX) |
388
|
|
|
|
|
|
|
su_uplevel_ud *sud; |
389
|
|
|
|
|
|
|
PERL_SI *si; |
390
|
|
|
|
|
|
|
|
391
|
242
|
|
|
|
|
|
Newx(sud, 1, su_uplevel_ud); |
392
|
242
|
|
|
|
|
|
sud->next = NULL; |
393
|
|
|
|
|
|
|
|
394
|
242
|
|
|
|
|
|
sud->tmp_uid_storage.map = NULL; |
395
|
242
|
|
|
|
|
|
sud->tmp_uid_storage.used = 0; |
396
|
242
|
|
|
|
|
|
sud->tmp_uid_storage.alloc = 0; |
397
|
|
|
|
|
|
|
|
398
|
|
|
|
|
|
|
#if !SU_HAS_NEW_CXT |
399
|
|
|
|
|
|
|
Newx(si, 1, PERL_SI); |
400
|
|
|
|
|
|
|
si->si_stack = newAV(); |
401
|
|
|
|
|
|
|
AvREAL_off(si->si_stack); |
402
|
|
|
|
|
|
|
si->si_cxstack = NULL; |
403
|
|
|
|
|
|
|
si->si_cxmax = -1; |
404
|
|
|
|
|
|
|
|
405
|
|
|
|
|
|
|
sud->si = si; |
406
|
|
|
|
|
|
|
#endif |
407
|
|
|
|
|
|
|
|
408
|
242
|
|
|
|
|
|
return sud; |
409
|
|
|
|
|
|
|
} |
410
|
|
|
|
|
|
|
|
411
|
242
|
|
|
|
|
|
static void su_uplevel_ud_delete(pTHX_ su_uplevel_ud *sud) { |
412
|
|
|
|
|
|
|
#define su_uplevel_ud_delete(S) su_uplevel_ud_delete(aTHX_ (S)) |
413
|
|
|
|
|
|
|
|
414
|
|
|
|
|
|
|
#if !SU_HAS_NEW_CXT |
415
|
|
|
|
|
|
|
PERL_SI *si = sud->si; |
416
|
|
|
|
|
|
|
|
417
|
|
|
|
|
|
|
Safefree(si->si_cxstack); |
418
|
|
|
|
|
|
|
SvREFCNT_dec(si->si_stack); |
419
|
|
|
|
|
|
|
Safefree(si); |
420
|
|
|
|
|
|
|
#endif |
421
|
|
|
|
|
|
|
|
422
|
242
|
|
|
|
|
|
Safefree(sud->tmp_uid_storage.map); |
423
|
|
|
|
|
|
|
|
424
|
242
|
|
|
|
|
|
Safefree(sud); |
425
|
|
|
|
|
|
|
|
426
|
242
|
|
|
|
|
|
return; |
427
|
|
|
|
|
|
|
} |
428
|
|
|
|
|
|
|
|
429
|
|
|
|
|
|
|
typedef struct { |
430
|
|
|
|
|
|
|
su_uplevel_ud *top; |
431
|
|
|
|
|
|
|
su_uplevel_ud *root; |
432
|
|
|
|
|
|
|
I32 count; |
433
|
|
|
|
|
|
|
} su_uplevel_storage; |
434
|
|
|
|
|
|
|
|
435
|
|
|
|
|
|
|
#ifndef SU_UPLEVEL_STORAGE_SIZE |
436
|
|
|
|
|
|
|
# define SU_UPLEVEL_STORAGE_SIZE 4 |
437
|
|
|
|
|
|
|
#endif |
438
|
|
|
|
|
|
|
|
439
|
|
|
|
|
|
|
/* --- Global data --------------------------------------------------------- */ |
440
|
|
|
|
|
|
|
|
441
|
|
|
|
|
|
|
typedef struct { |
442
|
|
|
|
|
|
|
su_unwind_storage unwind_storage; |
443
|
|
|
|
|
|
|
su_yield_storage yield_storage; |
444
|
|
|
|
|
|
|
su_uplevel_storage uplevel_storage; |
445
|
|
|
|
|
|
|
su_uid_storage uid_storage; |
446
|
|
|
|
|
|
|
} xsh_user_cxt_t; |
447
|
|
|
|
|
|
|
|
448
|
|
|
|
|
|
|
#define XSH_THREADS_USER_CONTEXT 1 |
449
|
|
|
|
|
|
|
#define XSH_THREADS_USER_CLONE_NEEDS_DUP 0 |
450
|
|
|
|
|
|
|
#define XSH_THREADS_COMPILE_TIME_PROTECTION 0 |
451
|
|
|
|
|
|
|
|
452
|
|
|
|
|
|
|
#if XSH_THREADSAFE |
453
|
|
|
|
|
|
|
|
454
|
|
|
|
|
|
|
static void xsh_user_clone(pTHX_ const xsh_user_cxt_t *old_cxt, xsh_user_cxt_t *new_cxt) { |
455
|
|
|
|
|
|
|
new_cxt->uplevel_storage.top = NULL; |
456
|
|
|
|
|
|
|
new_cxt->uplevel_storage.root = NULL; |
457
|
|
|
|
|
|
|
new_cxt->uplevel_storage.count = 0; |
458
|
|
|
|
|
|
|
new_cxt->uid_storage.map = NULL; |
459
|
|
|
|
|
|
|
new_cxt->uid_storage.used = 0; |
460
|
|
|
|
|
|
|
new_cxt->uid_storage.alloc = 0; |
461
|
|
|
|
|
|
|
|
462
|
|
|
|
|
|
|
su_uid_storage_dup(&new_cxt->uid_storage, &old_cxt->uid_storage, |
463
|
|
|
|
|
|
|
old_cxt->uid_storage.used); |
464
|
|
|
|
|
|
|
|
465
|
|
|
|
|
|
|
return; |
466
|
|
|
|
|
|
|
} |
467
|
|
|
|
|
|
|
|
468
|
|
|
|
|
|
|
#endif /* XSH_THREADSAFE */ |
469
|
|
|
|
|
|
|
|
470
|
|
|
|
|
|
|
#include "xsh/threads.h" |
471
|
|
|
|
|
|
|
|
472
|
|
|
|
|
|
|
/* --- Stack manipulations ------------------------------------------------- */ |
473
|
|
|
|
|
|
|
|
474
|
|
|
|
|
|
|
/* how many slots on the save stack various save types take up */ |
475
|
|
|
|
|
|
|
|
476
|
|
|
|
|
|
|
#define SU_SAVE_DESTRUCTOR_SIZE 3 /* SAVEt_DESTRUCTOR_X */ |
477
|
|
|
|
|
|
|
#define SU_SAVE_SCALAR_SIZE 3 /* SAVEt_SV */ |
478
|
|
|
|
|
|
|
#define SU_SAVE_ARY_SIZE 3 /* SAVEt_AV */ |
479
|
|
|
|
|
|
|
#define SU_SAVE_AELEM_SIZE 4 /* SAVEt_AELEM */ |
480
|
|
|
|
|
|
|
#define SU_SAVE_HASH_SIZE 3 /* SAVEt_HV */ |
481
|
|
|
|
|
|
|
#define SU_SAVE_HELEM_SIZE 4 /* SAVEt_HELEM */ |
482
|
|
|
|
|
|
|
#define SU_SAVE_HDELETE_SIZE 4 /* SAVEt_DELETE */ |
483
|
|
|
|
|
|
|
|
484
|
|
|
|
|
|
|
#define SU_SAVE_GVCV_SIZE SU_SAVE_DESTRUCTOR_SIZE |
485
|
|
|
|
|
|
|
|
486
|
|
|
|
|
|
|
/* the overhead of save_alloc() but not including any elements, |
487
|
|
|
|
|
|
|
* of which there must be at least 1 */ |
488
|
|
|
|
|
|
|
#if XSH_HAS_PERL(5, 14, 0) |
489
|
|
|
|
|
|
|
# define SU_SAVE_ALLOC_SIZE 1 /* SAVEt_ALLOC */ |
490
|
|
|
|
|
|
|
#else |
491
|
|
|
|
|
|
|
# define SU_SAVE_ALLOC_SIZE 2 /* SAVEt_ALLOC */ |
492
|
|
|
|
|
|
|
#endif |
493
|
|
|
|
|
|
|
|
494
|
|
|
|
|
|
|
#ifdef SAVEADELETE |
495
|
|
|
|
|
|
|
# define SU_SAVE_ADELETE_SIZE 3 /* SAVEt_ADELETE */ |
496
|
|
|
|
|
|
|
#else |
497
|
|
|
|
|
|
|
# define SU_SAVE_ADELETE_SIZE SU_SAVE_DESTRUCTOR_SIZE |
498
|
|
|
|
|
|
|
#endif |
499
|
|
|
|
|
|
|
|
500
|
|
|
|
|
|
|
/* (NB: it was 4 between 5.13.1 and 5.13.7) */ |
501
|
|
|
|
|
|
|
#if XSH_HAS_PERL(5, 8, 9) |
502
|
|
|
|
|
|
|
# define SU_SAVE_GP_SIZE 3 /* SAVEt_GP */ |
503
|
|
|
|
|
|
|
# else |
504
|
|
|
|
|
|
|
# define SU_SAVE_GP_SIZE 6 /* SAVEt_GP */ |
505
|
|
|
|
|
|
|
#endif |
506
|
|
|
|
|
|
|
|
507
|
|
|
|
|
|
|
/* sometimes we don't know in advance whether we're saving or deleting |
508
|
|
|
|
|
|
|
* an array/hash element. So include enough room for a variable-sized |
509
|
|
|
|
|
|
|
* save_alloc() to pad it to a fixed size. |
510
|
|
|
|
|
|
|
*/ |
511
|
|
|
|
|
|
|
|
512
|
|
|
|
|
|
|
#if SU_SAVE_AELEM_SIZE < SU_SAVE_ADELETE_SIZE |
513
|
|
|
|
|
|
|
# define SU_SAVE_AELEM_OR_ADELETE_SIZE \ |
514
|
|
|
|
|
|
|
(SU_SAVE_ADELETE_SIZE + SU_SAVE_ALLOC_SIZE + 1) |
515
|
|
|
|
|
|
|
#elif SU_SAVE_AELEM_SIZE > SU_SAVE_ADELETE_SIZE |
516
|
|
|
|
|
|
|
# define SU_SAVE_AELEM_OR_ADELETE_SIZE \ |
517
|
|
|
|
|
|
|
(SU_SAVE_AELEM_SIZE + SU_SAVE_ALLOC_SIZE + 1) |
518
|
|
|
|
|
|
|
#else |
519
|
|
|
|
|
|
|
# define SU_SAVE_AELEM_OR_ADELETE_SIZE SU_SAVE_AELEM_SIZE |
520
|
|
|
|
|
|
|
#endif |
521
|
|
|
|
|
|
|
|
522
|
|
|
|
|
|
|
#if SU_SAVE_HELEM_SIZE < SU_SAVE_HDELETE_SIZE |
523
|
|
|
|
|
|
|
# define SU_SAVE_HELEM_OR_HDELETE_SIZE \ |
524
|
|
|
|
|
|
|
(SU_SAVE_HDELETE_SIZE + SU_SAVE_ALLOC_SIZE + 1) |
525
|
|
|
|
|
|
|
#elif SU_SAVE_HELEM_SIZE > SU_SAVE_HDELETE_SIZE |
526
|
|
|
|
|
|
|
# define SU_SAVE_HELEM_OR_HDELETE_SIZE \ |
527
|
|
|
|
|
|
|
(SU_SAVE_HELEM_SIZE + SU_SAVE_ALLOC_SIZE + 1) |
528
|
|
|
|
|
|
|
#else |
529
|
|
|
|
|
|
|
# define SU_SAVE_HELEM_OR_HDELETE_SIZE SU_SAVE_HELEM_SIZE |
530
|
|
|
|
|
|
|
#endif |
531
|
|
|
|
|
|
|
|
532
|
|
|
|
|
|
|
#ifndef SvCANEXISTDELETE |
533
|
|
|
|
|
|
|
# define SvCANEXISTDELETE(sv) \ |
534
|
|
|
|
|
|
|
(!SvRMAGICAL(sv) \ |
535
|
|
|
|
|
|
|
|| ((mg = mg_find((SV *) sv, PERL_MAGIC_tied)) \ |
536
|
|
|
|
|
|
|
&& (stash = SvSTASH(SvRV(SvTIED_obj((SV *) sv, mg)))) \ |
537
|
|
|
|
|
|
|
&& gv_fetchmethod_autoload(stash, "EXISTS", TRUE) \ |
538
|
|
|
|
|
|
|
&& gv_fetchmethod_autoload(stash, "DELETE", TRUE) \ |
539
|
|
|
|
|
|
|
) \ |
540
|
|
|
|
|
|
|
) |
541
|
|
|
|
|
|
|
#endif |
542
|
|
|
|
|
|
|
|
543
|
|
|
|
|
|
|
/* ... Saving array elements ............................................... */ |
544
|
|
|
|
|
|
|
|
545
|
5129
|
|
|
|
|
|
static I32 su_av_key2idx(pTHX_ AV *av, I32 key) { |
546
|
|
|
|
|
|
|
#define su_av_key2idx(A, K) su_av_key2idx(aTHX_ (A), (K)) |
547
|
|
|
|
|
|
|
I32 idx; |
548
|
|
|
|
|
|
|
|
549
|
5129
|
100
|
|
|
|
|
if (key >= 0) |
550
|
5122
|
|
|
|
|
|
return key; |
551
|
|
|
|
|
|
|
|
552
|
|
|
|
|
|
|
/* Added by MJD in perl-5.8.1 with 6f12eb6d2a1dfaf441504d869b27d2e40ef4966a */ |
553
|
|
|
|
|
|
|
#if XSH_HAS_PERL(5, 8, 1) |
554
|
7
|
100
|
|
|
|
|
if (SvRMAGICAL(av)) { |
555
|
2
|
|
|
|
|
|
const MAGIC * const tied_magic = mg_find((SV *) av, PERL_MAGIC_tied); |
556
|
2
|
50
|
|
|
|
|
if (tied_magic) { |
557
|
2
|
50
|
|
|
|
|
SV * const * const negative_indices_glob = hv_fetch( |
558
|
|
|
|
|
|
|
SvSTASH(SvRV(SvTIED_obj((SV *) (av), tied_magic))), |
559
|
|
|
|
|
|
|
NEGATIVE_INDICES_VAR, sizeof(NEGATIVE_INDICES_VAR)-1, 0 |
560
|
|
|
|
|
|
|
); |
561
|
2
|
50
|
|
|
|
|
if (negative_indices_glob && SvTRUE(GvSV(*negative_indices_glob))) |
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
562
|
1
|
|
|
|
|
|
return key; |
563
|
|
|
|
|
|
|
} |
564
|
|
|
|
|
|
|
} |
565
|
|
|
|
|
|
|
#endif |
566
|
|
|
|
|
|
|
|
567
|
6
|
|
|
|
|
|
idx = key + av_len(av) + 1; |
568
|
6
|
100
|
|
|
|
|
if (idx < 0) |
569
|
2
|
|
|
|
|
|
return key; |
570
|
|
|
|
|
|
|
|
571
|
4
|
|
|
|
|
|
return idx; |
572
|
|
|
|
|
|
|
} |
573
|
|
|
|
|
|
|
|
574
|
|
|
|
|
|
|
#ifndef SAVEADELETE |
575
|
|
|
|
|
|
|
|
576
|
|
|
|
|
|
|
typedef struct { |
577
|
|
|
|
|
|
|
AV *av; |
578
|
|
|
|
|
|
|
I32 idx; |
579
|
|
|
|
|
|
|
} su_ud_adelete; |
580
|
|
|
|
|
|
|
|
581
|
|
|
|
|
|
|
static void su_adelete(pTHX_ void *ud_) { |
582
|
|
|
|
|
|
|
su_ud_adelete *ud = (su_ud_adelete *) ud_; |
583
|
|
|
|
|
|
|
|
584
|
|
|
|
|
|
|
av_delete(ud->av, ud->idx, G_DISCARD); |
585
|
|
|
|
|
|
|
SvREFCNT_dec(ud->av); |
586
|
|
|
|
|
|
|
|
587
|
|
|
|
|
|
|
Safefree(ud); |
588
|
|
|
|
|
|
|
} |
589
|
|
|
|
|
|
|
|
590
|
|
|
|
|
|
|
static void su_save_adelete(pTHX_ AV *av, I32 idx) { |
591
|
|
|
|
|
|
|
#define su_save_adelete(A, K) su_save_adelete(aTHX_ (A), (K)) |
592
|
|
|
|
|
|
|
su_ud_adelete *ud; |
593
|
|
|
|
|
|
|
|
594
|
|
|
|
|
|
|
Newx(ud, 1, su_ud_adelete); |
595
|
|
|
|
|
|
|
ud->av = av; |
596
|
|
|
|
|
|
|
ud->idx = idx; |
597
|
|
|
|
|
|
|
SvREFCNT_inc_simple_void(av); |
598
|
|
|
|
|
|
|
|
599
|
|
|
|
|
|
|
SAVEDESTRUCTOR_X(su_adelete, ud); |
600
|
|
|
|
|
|
|
} |
601
|
|
|
|
|
|
|
|
602
|
|
|
|
|
|
|
#define SAVEADELETE(A, K) su_save_adelete((A), (K)) |
603
|
|
|
|
|
|
|
|
604
|
|
|
|
|
|
|
#endif /* SAVEADELETE */ |
605
|
|
|
|
|
|
|
|
606
|
5129
|
|
|
|
|
|
static void su_save_aelem(pTHX_ AV *av, SV *key, SV *val) { |
607
|
|
|
|
|
|
|
#define su_save_aelem(A, K, V) su_save_aelem(aTHX_ (A), (K), (V)) |
608
|
|
|
|
|
|
|
I32 idx; |
609
|
5129
|
|
|
|
|
|
I32 preeminent = 1; |
610
|
|
|
|
|
|
|
SV **svp; |
611
|
|
|
|
|
|
|
HV *stash; |
612
|
|
|
|
|
|
|
MAGIC *mg; |
613
|
|
|
|
|
|
|
|
614
|
5129
|
50
|
|
|
|
|
idx = su_av_key2idx(av, SvIV(key)); |
615
|
|
|
|
|
|
|
|
616
|
5129
|
100
|
|
|
|
|
if (SvCANEXISTDELETE(av)) |
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
617
|
5125
|
|
|
|
|
|
preeminent = av_exists(av, idx); |
618
|
|
|
|
|
|
|
|
619
|
5129
|
|
|
|
|
|
svp = av_fetch(av, idx, 1); |
620
|
5129
|
100
|
|
|
|
|
if (!svp || *svp == &PL_sv_undef) croak(PL_no_aelem, idx); |
|
|
50
|
|
|
|
|
|
621
|
|
|
|
|
|
|
|
622
|
5127
|
100
|
|
|
|
|
if (preeminent) |
623
|
5121
|
|
|
|
|
|
save_aelem(av, idx, svp); |
624
|
|
|
|
|
|
|
else |
625
|
6
|
|
|
|
|
|
SAVEADELETE(av, idx); |
626
|
|
|
|
|
|
|
|
627
|
5127
|
100
|
|
|
|
|
if (val) { /* local $x[$idx] = $val; */ |
628
|
4031
|
50
|
|
|
|
|
SvSetMagicSV(*svp, val); |
|
|
100
|
|
|
|
|
|
629
|
|
|
|
|
|
|
} else { /* local $x[$idx]; delete $x[$idx]; */ |
630
|
1096
|
|
|
|
|
|
av_delete(av, idx, G_DISCARD); |
631
|
|
|
|
|
|
|
} |
632
|
5127
|
|
|
|
|
|
} |
633
|
|
|
|
|
|
|
|
634
|
|
|
|
|
|
|
/* ... Saving hash elements ................................................ */ |
635
|
|
|
|
|
|
|
|
636
|
3118
|
|
|
|
|
|
static void su_save_helem(pTHX_ HV *hv, SV *keysv, SV *val) { |
637
|
|
|
|
|
|
|
#define su_save_helem(H, K, V) su_save_helem(aTHX_ (H), (K), (V)) |
638
|
3118
|
|
|
|
|
|
I32 preeminent = 1; |
639
|
|
|
|
|
|
|
HE *he; |
640
|
|
|
|
|
|
|
SV **svp; |
641
|
|
|
|
|
|
|
HV *stash; |
642
|
|
|
|
|
|
|
MAGIC *mg; |
643
|
|
|
|
|
|
|
|
644
|
3118
|
100
|
|
|
|
|
if (SvCANEXISTDELETE(hv) || mg_find((SV *) hv, PERL_MAGIC_env)) |
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
645
|
3118
|
|
|
|
|
|
preeminent = hv_exists_ent(hv, keysv, 0); |
646
|
|
|
|
|
|
|
|
647
|
3118
|
|
|
|
|
|
he = hv_fetch_ent(hv, keysv, 1, 0); |
648
|
3118
|
50
|
|
|
|
|
svp = he ? &HeVAL(he) : NULL; |
649
|
3118
|
50
|
|
|
|
|
if (!svp || *svp == &PL_sv_undef) croak("Modification of non-creatable hash value attempted, subscript \"%s\"", SvPV_nolen_const(*svp)); |
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
650
|
|
|
|
|
|
|
|
651
|
3118
|
100
|
|
|
|
|
if (HvNAME_get(hv) && isGV(*svp)) { |
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
652
|
0
|
|
|
|
|
|
save_gp((GV *) *svp, 0); |
653
|
0
|
|
|
|
|
|
return; |
654
|
|
|
|
|
|
|
} |
655
|
|
|
|
|
|
|
|
656
|
3118
|
100
|
|
|
|
|
if (preeminent) { |
657
|
2295
|
|
|
|
|
|
save_helem(hv, keysv, svp); |
658
|
|
|
|
|
|
|
} else { |
659
|
|
|
|
|
|
|
STRLEN keylen; |
660
|
823
|
50
|
|
|
|
|
const char * const key = SvPV_const(keysv, keylen); |
661
|
823
|
50
|
|
|
|
|
SAVEDELETE(hv, savepvn(key, keylen), |
662
|
|
|
|
|
|
|
SvUTF8(keysv) ? -(I32)keylen : (I32)keylen); |
663
|
|
|
|
|
|
|
} |
664
|
|
|
|
|
|
|
|
665
|
3118
|
100
|
|
|
|
|
if (val) { /* local $x{$keysv} = $val; */ |
666
|
3030
|
50
|
|
|
|
|
SvSetMagicSV(*svp, val); |
|
|
100
|
|
|
|
|
|
667
|
|
|
|
|
|
|
} else { /* local $x{$keysv}; delete $x{$keysv}; */ |
668
|
88
|
|
|
|
|
|
(void)hv_delete_ent(hv, keysv, G_DISCARD, HeHASH(he)); |
669
|
|
|
|
|
|
|
} |
670
|
|
|
|
|
|
|
} |
671
|
|
|
|
|
|
|
|
672
|
|
|
|
|
|
|
/* ... Saving code slots from a glob ....................................... */ |
673
|
|
|
|
|
|
|
|
674
|
|
|
|
|
|
|
#if !XSH_HAS_PERL(5, 10, 0) && !defined(mro_method_changed_in) |
675
|
|
|
|
|
|
|
# define mro_method_changed_in(G) PL_sub_generation++ |
676
|
|
|
|
|
|
|
#endif |
677
|
|
|
|
|
|
|
|
678
|
|
|
|
|
|
|
typedef struct { |
679
|
|
|
|
|
|
|
GV *gv; |
680
|
|
|
|
|
|
|
CV *old_cv; |
681
|
|
|
|
|
|
|
} su_save_gvcv_ud; |
682
|
|
|
|
|
|
|
|
683
|
13
|
|
|
|
|
|
static void su_restore_gvcv(pTHX_ void *ud_) { |
684
|
13
|
|
|
|
|
|
su_save_gvcv_ud *ud = ud_; |
685
|
13
|
|
|
|
|
|
GV *gv = ud->gv; |
686
|
|
|
|
|
|
|
|
687
|
13
|
|
|
|
|
|
GvCV_set(gv, ud->old_cv); |
688
|
13
|
|
|
|
|
|
GvCVGEN(gv) = 0; |
689
|
13
|
|
|
|
|
|
mro_method_changed_in(GvSTASH(gv)); |
690
|
|
|
|
|
|
|
|
691
|
13
|
|
|
|
|
|
Safefree(ud); |
692
|
13
|
|
|
|
|
|
} |
693
|
|
|
|
|
|
|
|
694
|
13
|
|
|
|
|
|
static void su_save_gvcv(pTHX_ GV *gv) { |
695
|
|
|
|
|
|
|
#define su_save_gvcv(G) su_save_gvcv(aTHX_ (G)) |
696
|
|
|
|
|
|
|
su_save_gvcv_ud *ud; |
697
|
|
|
|
|
|
|
|
698
|
13
|
|
|
|
|
|
Newx(ud, 1, su_save_gvcv_ud); |
699
|
13
|
|
|
|
|
|
ud->gv = gv; |
700
|
13
|
|
|
|
|
|
ud->old_cv = GvCV(gv); |
701
|
|
|
|
|
|
|
|
702
|
13
|
|
|
|
|
|
GvCV_set(gv, NULL); |
703
|
13
|
|
|
|
|
|
GvCVGEN(gv) = 0; |
704
|
13
|
|
|
|
|
|
mro_method_changed_in(GvSTASH(gv)); |
705
|
|
|
|
|
|
|
|
706
|
13
|
|
|
|
|
|
SAVEDESTRUCTOR_X(su_restore_gvcv, ud); |
707
|
13
|
|
|
|
|
|
} |
708
|
|
|
|
|
|
|
|
709
|
|
|
|
|
|
|
/* --- Actions ------------------------------------------------------------- */ |
710
|
|
|
|
|
|
|
|
711
|
|
|
|
|
|
|
typedef struct { |
712
|
|
|
|
|
|
|
I32 orig_ix; /* original savestack_ix */ |
713
|
|
|
|
|
|
|
I32 offset; /* how much we bumped this savestack index */ |
714
|
|
|
|
|
|
|
} su_ud_origin_elem; |
715
|
|
|
|
|
|
|
|
716
|
|
|
|
|
|
|
typedef struct { |
717
|
|
|
|
|
|
|
U8 type; |
718
|
|
|
|
|
|
|
U8 private; |
719
|
|
|
|
|
|
|
/* spare */ |
720
|
|
|
|
|
|
|
I32 depth; |
721
|
|
|
|
|
|
|
su_ud_origin_elem *origin; |
722
|
|
|
|
|
|
|
} su_ud_common; |
723
|
|
|
|
|
|
|
|
724
|
|
|
|
|
|
|
#define SU_UD_TYPE(U) (((su_ud_common *) (U))->type) |
725
|
|
|
|
|
|
|
#define SU_UD_PRIVATE(U) (((su_ud_common *) (U))->private) |
726
|
|
|
|
|
|
|
#define SU_UD_DEPTH(U) (((su_ud_common *) (U))->depth) |
727
|
|
|
|
|
|
|
#define SU_UD_ORIGIN(U) (((su_ud_common *) (U))->origin) |
728
|
|
|
|
|
|
|
|
729
|
|
|
|
|
|
|
#define SU_UD_TYPE_REAP 0 |
730
|
|
|
|
|
|
|
#define SU_UD_TYPE_LOCALIZE 1 |
731
|
|
|
|
|
|
|
#define SU_UD_TYPE_UID 2 |
732
|
|
|
|
|
|
|
|
733
|
|
|
|
|
|
|
#define SU_UD_FREE(U) STMT_START { \ |
734
|
|
|
|
|
|
|
if (SU_UD_ORIGIN(U)) Safefree(SU_UD_ORIGIN(U)); \ |
735
|
|
|
|
|
|
|
Safefree(U); \ |
736
|
|
|
|
|
|
|
} STMT_END |
737
|
|
|
|
|
|
|
|
738
|
|
|
|
|
|
|
/* ... Reap ................................................................ */ |
739
|
|
|
|
|
|
|
|
740
|
|
|
|
|
|
|
#define SU_SAVE_LAST_CX (!XSH_HAS_PERL(5, 8, 4) || (XSH_HAS_PERL(5, 9, 5) && !XSH_HAS_PERL(5, 14, 0)) || XSH_HAS_PERL(5, 15, 0)) |
741
|
|
|
|
|
|
|
|
742
|
|
|
|
|
|
|
typedef struct { |
743
|
|
|
|
|
|
|
su_ud_common ci; |
744
|
|
|
|
|
|
|
SV *cb; |
745
|
|
|
|
|
|
|
} su_ud_reap; |
746
|
|
|
|
|
|
|
|
747
|
|
|
|
|
|
|
#define SU_UD_REAP_CB(U) (((su_ud_reap *) (U))->cb) |
748
|
|
|
|
|
|
|
|
749
|
4433
|
|
|
|
|
|
static void su_call(pTHX_ SV *cb) { |
750
|
|
|
|
|
|
|
#if SU_SAVE_LAST_CX |
751
|
|
|
|
|
|
|
I32 cxix; |
752
|
|
|
|
|
|
|
PERL_CONTEXT saved_cx; |
753
|
|
|
|
|
|
|
#endif /* SU_SAVE_LAST_CX */ |
754
|
|
|
|
|
|
|
|
755
|
4433
|
|
|
|
|
|
dSP; |
756
|
|
|
|
|
|
|
|
757
|
|
|
|
|
|
|
XSH_D(xsh_debug_log("@@@ call scope_ix=%2d save_ix=%2d\n", |
758
|
|
|
|
|
|
|
PL_scopestack_ix, PL_savestack_ix)); |
759
|
|
|
|
|
|
|
|
760
|
4433
|
|
|
|
|
|
ENTER; |
761
|
4433
|
|
|
|
|
|
SAVETMPS; |
762
|
|
|
|
|
|
|
|
763
|
4433
|
50
|
|
|
|
|
PUSHMARK(SP); |
764
|
4433
|
|
|
|
|
|
PUTBACK; |
765
|
|
|
|
|
|
|
|
766
|
|
|
|
|
|
|
#if SU_SAVE_LAST_CX |
767
|
|
|
|
|
|
|
/* If the recently popped context isn't saved there, it will be overwritten by |
768
|
|
|
|
|
|
|
* the sub scope from call_sv, although it's still needed in our caller. */ |
769
|
4433
|
50
|
|
|
|
|
cxix = (cxstack_ix < cxstack_max) ? (cxstack_ix + 1) : Perl_cxinc(aTHX); |
770
|
4433
|
|
|
|
|
|
saved_cx = cxstack[cxix]; |
771
|
|
|
|
|
|
|
#endif /* SU_SAVE_LAST_CX */ |
772
|
|
|
|
|
|
|
|
773
|
4433
|
|
|
|
|
|
call_sv(cb, G_VOID); |
774
|
|
|
|
|
|
|
|
775
|
|
|
|
|
|
|
#if SU_SAVE_LAST_CX |
776
|
4431
|
|
|
|
|
|
cxstack[cxix] = saved_cx; |
777
|
|
|
|
|
|
|
#endif /* SU_SAVE_LAST_CX */ |
778
|
|
|
|
|
|
|
|
779
|
4431
|
|
|
|
|
|
PUTBACK; |
780
|
|
|
|
|
|
|
|
781
|
4431
|
50
|
|
|
|
|
FREETMPS; |
782
|
4431
|
|
|
|
|
|
LEAVE; |
783
|
|
|
|
|
|
|
|
784
|
4431
|
|
|
|
|
|
SvREFCNT_dec(cb); |
785
|
|
|
|
|
|
|
|
786
|
4431
|
|
|
|
|
|
return; |
787
|
|
|
|
|
|
|
} |
788
|
|
|
|
|
|
|
|
789
|
|
|
|
|
|
|
/* ... Localize & localize array/hash element .............................. */ |
790
|
|
|
|
|
|
|
|
791
|
|
|
|
|
|
|
typedef struct { |
792
|
|
|
|
|
|
|
su_ud_common ci; |
793
|
|
|
|
|
|
|
SV *sv; |
794
|
|
|
|
|
|
|
SV *val; |
795
|
|
|
|
|
|
|
SV *elem; |
796
|
|
|
|
|
|
|
} su_ud_localize; |
797
|
|
|
|
|
|
|
|
798
|
|
|
|
|
|
|
#define SU_UD_LOCALIZE_SV(U) (((su_ud_localize *) (U))->sv) |
799
|
|
|
|
|
|
|
#define SU_UD_LOCALIZE_VAL(U) (((su_ud_localize *) (U))->val) |
800
|
|
|
|
|
|
|
#define SU_UD_LOCALIZE_ELEM(U) (((su_ud_localize *) (U))->elem) |
801
|
|
|
|
|
|
|
|
802
|
|
|
|
|
|
|
#define SU_UD_LOCALIZE_FREE(U) STMT_START { \ |
803
|
|
|
|
|
|
|
SvREFCNT_dec(SU_UD_LOCALIZE_ELEM(U)); \ |
804
|
|
|
|
|
|
|
SvREFCNT_dec(SU_UD_LOCALIZE_VAL(U)); \ |
805
|
|
|
|
|
|
|
SvREFCNT_dec(SU_UD_LOCALIZE_SV(U)); \ |
806
|
|
|
|
|
|
|
SU_UD_FREE(U); \ |
807
|
|
|
|
|
|
|
} STMT_END |
808
|
|
|
|
|
|
|
|
809
|
12346
|
|
|
|
|
|
static I32 su_ud_localize_init(pTHX_ su_ud_localize *ud, SV *sv, SV *val, SV *elem) { |
810
|
|
|
|
|
|
|
#define su_ud_localize_init(UD, S, V, E) su_ud_localize_init(aTHX_ (UD), (S), (V), (E)) |
811
|
12346
|
|
|
|
|
|
int take_ref = 0; |
812
|
12346
|
|
|
|
|
|
svtype t = SVt_NULL; |
813
|
|
|
|
|
|
|
I32 size; |
814
|
|
|
|
|
|
|
|
815
|
12346
|
50
|
|
|
|
|
SvREFCNT_inc_simple_void(sv); |
816
|
|
|
|
|
|
|
|
817
|
12346
|
100
|
|
|
|
|
if (SvTYPE(sv) >= SVt_PVGV) { |
818
|
1013
|
100
|
|
|
|
|
if (SvFAKE(sv)) { |
819
|
2
|
|
|
|
|
|
sv_force_normal(sv); |
820
|
2
|
|
|
|
|
|
goto string_spec; |
821
|
|
|
|
|
|
|
} |
822
|
|
|
|
|
|
|
|
823
|
1011
|
100
|
|
|
|
|
if (!val || !SvROK(val)) { /* local *x; or local *x = $val; */ |
|
|
100
|
|
|
|
|
|
824
|
1002
|
|
|
|
|
|
t = SVt_PVGV; |
825
|
|
|
|
|
|
|
} else { /* local *x = \$val; */ |
826
|
1011
|
|
|
|
|
|
t = SvTYPE(SvRV(val)); |
827
|
|
|
|
|
|
|
} |
828
|
11333
|
100
|
|
|
|
|
} else if (SvROK(sv)) { |
829
|
12
|
|
|
|
|
|
croak("Invalid %s reference as the localization target", |
830
|
12
|
|
|
|
|
|
sv_reftype(SvRV(sv), 0)); |
831
|
|
|
|
|
|
|
} else { |
832
|
|
|
|
|
|
|
STRLEN len, l; |
833
|
|
|
|
|
|
|
const char *p, *s; |
834
|
|
|
|
|
|
|
string_spec: |
835
|
11323
|
50
|
|
|
|
|
p = SvPV_const(sv, len); |
836
|
11324
|
100
|
|
|
|
|
for (s = p, l = len; l > 0 && isSPACE(*s); ++s, --l) { } |
|
|
100
|
|
|
|
|
|
837
|
11323
|
100
|
|
|
|
|
if (!l) { |
838
|
1
|
|
|
|
|
|
l = len; |
839
|
1
|
|
|
|
|
|
s = p; |
840
|
|
|
|
|
|
|
} |
841
|
11323
|
|
|
|
|
|
switch (*s) { |
842
|
3056
|
|
|
|
|
|
case '$': t = SVt_PV; break; |
843
|
5130
|
|
|
|
|
|
case '@': t = SVt_PVAV; break; |
844
|
3119
|
|
|
|
|
|
case '%': t = SVt_PVHV; break; |
845
|
8
|
|
|
|
|
|
case '&': t = SVt_PVCV; break; |
846
|
3
|
|
|
|
|
|
case '*': t = SVt_PVGV; break; |
847
|
|
|
|
|
|
|
} |
848
|
11323
|
100
|
|
|
|
|
if (t != SVt_NULL) { |
849
|
11316
|
|
|
|
|
|
++s; |
850
|
11316
|
|
|
|
|
|
--l; |
851
|
11316
|
100
|
|
|
|
|
if (t == SVt_PV) |
852
|
11316
|
|
|
|
|
|
take_ref = 1; |
853
|
7
|
50
|
|
|
|
|
} else if (val) { /* t == SVt_NULL, type can't be inferred from the sigil */ |
854
|
7
|
100
|
|
|
|
|
if (SvROK(val) && !sv_isobject(val)) { |
|
|
100
|
|
|
|
|
|
855
|
4
|
|
|
|
|
|
t = SvTYPE(SvRV(val)); |
856
|
|
|
|
|
|
|
} else { |
857
|
3
|
|
|
|
|
|
t = SvTYPE(val); |
858
|
3
|
|
|
|
|
|
take_ref = 1; |
859
|
|
|
|
|
|
|
} |
860
|
|
|
|
|
|
|
} |
861
|
|
|
|
|
|
|
|
862
|
11323
|
|
|
|
|
|
SvREFCNT_dec(sv); |
863
|
11323
|
|
|
|
|
|
sv = newSVpvn(s, l); |
864
|
|
|
|
|
|
|
} |
865
|
|
|
|
|
|
|
|
866
|
12334
|
|
|
|
|
|
switch (t) { |
867
|
|
|
|
|
|
|
case SVt_PVAV: |
868
|
5132
|
|
|
|
|
|
size = elem ? SU_SAVE_AELEM_OR_ADELETE_SIZE |
869
|
5132
|
100
|
|
|
|
|
: SU_SAVE_ARY_SIZE; |
870
|
5132
|
|
|
|
|
|
break; |
871
|
|
|
|
|
|
|
case SVt_PVHV: |
872
|
3121
|
|
|
|
|
|
size = elem ? SU_SAVE_HELEM_OR_HDELETE_SIZE |
873
|
3121
|
100
|
|
|
|
|
: SU_SAVE_HASH_SIZE; |
874
|
3121
|
|
|
|
|
|
break; |
875
|
|
|
|
|
|
|
case SVt_PVGV: |
876
|
1005
|
|
|
|
|
|
size = SU_SAVE_GP_SIZE; |
877
|
1005
|
|
|
|
|
|
break; |
878
|
|
|
|
|
|
|
case SVt_PVCV: |
879
|
14
|
|
|
|
|
|
size = SU_SAVE_GVCV_SIZE; |
880
|
14
|
|
|
|
|
|
break; |
881
|
|
|
|
|
|
|
default: |
882
|
3062
|
|
|
|
|
|
size = SU_SAVE_SCALAR_SIZE; |
883
|
3062
|
|
|
|
|
|
break; |
884
|
|
|
|
|
|
|
} |
885
|
|
|
|
|
|
|
|
886
|
12334
|
|
|
|
|
|
SU_UD_PRIVATE(ud) = t; |
887
|
|
|
|
|
|
|
|
888
|
12334
|
|
|
|
|
|
ud->sv = sv; |
889
|
12334
|
100
|
|
|
|
|
if (val) { |
890
|
11141
|
|
|
|
|
|
val = newSVsv(val); |
891
|
11141
|
100
|
|
|
|
|
ud->val = take_ref ? newRV_noinc(val) : val; |
892
|
|
|
|
|
|
|
} else { |
893
|
1193
|
|
|
|
|
|
ud->val = NULL; |
894
|
|
|
|
|
|
|
} |
895
|
12334
|
|
|
|
|
|
ud->elem = SvREFCNT_inc(elem); |
896
|
|
|
|
|
|
|
|
897
|
12334
|
|
|
|
|
|
return size; |
898
|
|
|
|
|
|
|
} |
899
|
|
|
|
|
|
|
|
900
|
12331
|
|
|
|
|
|
static void su_localize(pTHX_ void *ud_) { |
901
|
|
|
|
|
|
|
#define su_localize(U) su_localize(aTHX_ (U)) |
902
|
12331
|
|
|
|
|
|
su_ud_localize *ud = (su_ud_localize *) ud_; |
903
|
12331
|
|
|
|
|
|
SV *sv = ud->sv; |
904
|
12331
|
|
|
|
|
|
SV *val = ud->val; |
905
|
12331
|
|
|
|
|
|
SV *elem = ud->elem; |
906
|
12331
|
|
|
|
|
|
svtype t = SU_UD_PRIVATE(ud); |
907
|
|
|
|
|
|
|
GV *gv; |
908
|
|
|
|
|
|
|
|
909
|
12331
|
100
|
|
|
|
|
if (SvTYPE(sv) >= SVt_PVGV) { |
910
|
1011
|
|
|
|
|
|
gv = (GV *) sv; |
911
|
|
|
|
|
|
|
} else { |
912
|
|
|
|
|
|
|
/* new perl context implementation frees savestack *before* restoring |
913
|
|
|
|
|
|
|
* PL_curcop. Temporarily restore it prematurely to make gv_fetch* |
914
|
|
|
|
|
|
|
* looks up unqualified var names in the caller's package */ |
915
|
|
|
|
|
|
|
#if SU_HAS_NEW_CXT |
916
|
11320
|
|
|
|
|
|
COP *old_cop = PL_curcop; |
917
|
11320
|
|
|
|
|
|
PL_curcop = CX_CUR()->blk_oldcop; |
918
|
|
|
|
|
|
|
#endif |
919
|
|
|
|
|
|
|
|
920
|
|
|
|
|
|
|
#ifdef gv_fetchsv |
921
|
11320
|
|
|
|
|
|
gv = gv_fetchsv(sv, GV_ADDMULTI, t); |
922
|
|
|
|
|
|
|
#else |
923
|
|
|
|
|
|
|
{ |
924
|
|
|
|
|
|
|
STRLEN len; |
925
|
|
|
|
|
|
|
const char *name = SvPV_const(sv, len); |
926
|
|
|
|
|
|
|
gv = gv_fetchpvn_flags(name, len, GV_ADDMULTI, t); |
927
|
|
|
|
|
|
|
} |
928
|
|
|
|
|
|
|
#endif |
929
|
|
|
|
|
|
|
|
930
|
|
|
|
|
|
|
#if SU_HAS_NEW_CXT |
931
|
11320
|
|
|
|
|
|
CX_CUR()->blk_oldcop = old_cop; |
932
|
|
|
|
|
|
|
#endif |
933
|
|
|
|
|
|
|
} |
934
|
|
|
|
|
|
|
|
935
|
|
|
|
|
|
|
XSH_D({ |
936
|
|
|
|
|
|
|
SV *z = newSV(0); |
937
|
|
|
|
|
|
|
SvUPGRADE(z, t); |
938
|
|
|
|
|
|
|
xsh_debug_log("%p: === localize a %s\n", ud, sv_reftype(z, 0)); |
939
|
|
|
|
|
|
|
xsh_debug_log("%p: depth=%2d scope_ix=%2d save_ix=%2d\n", |
940
|
|
|
|
|
|
|
ud, SU_UD_DEPTH(ud), PL_scopestack_ix, PL_savestack_ix); |
941
|
|
|
|
|
|
|
SvREFCNT_dec(z); |
942
|
|
|
|
|
|
|
}); |
943
|
|
|
|
|
|
|
|
944
|
|
|
|
|
|
|
/* Inspired from Alias.pm */ |
945
|
12331
|
|
|
|
|
|
switch (t) { |
946
|
|
|
|
|
|
|
case SVt_PVAV: |
947
|
5132
|
100
|
|
|
|
|
if (elem) { |
948
|
5129
|
|
|
|
|
|
su_save_aelem(GvAV(gv), elem, val); |
949
|
5127
|
|
|
|
|
|
return; |
950
|
|
|
|
|
|
|
} else { |
951
|
3
|
|
|
|
|
|
save_ary(gv); |
952
|
|
|
|
|
|
|
} |
953
|
3
|
|
|
|
|
|
break; |
954
|
|
|
|
|
|
|
case SVt_PVHV: |
955
|
3121
|
100
|
|
|
|
|
if (elem) { |
956
|
3118
|
|
|
|
|
|
su_save_helem(GvHV(gv), elem, val); |
957
|
3118
|
|
|
|
|
|
return; |
958
|
|
|
|
|
|
|
} else { |
959
|
3
|
|
|
|
|
|
save_hash(gv); |
960
|
|
|
|
|
|
|
} |
961
|
3
|
|
|
|
|
|
break; |
962
|
|
|
|
|
|
|
case SVt_PVGV: |
963
|
1004
|
|
|
|
|
|
save_gp(gv, 1); /* hide previous entry in symtab */ |
964
|
1004
|
|
|
|
|
|
break; |
965
|
|
|
|
|
|
|
case SVt_PVCV: |
966
|
13
|
|
|
|
|
|
su_save_gvcv(gv); |
967
|
13
|
|
|
|
|
|
break; |
968
|
|
|
|
|
|
|
default: |
969
|
3061
|
|
|
|
|
|
save_scalar(gv); |
970
|
3061
|
|
|
|
|
|
break; |
971
|
|
|
|
|
|
|
} |
972
|
|
|
|
|
|
|
|
973
|
4084
|
100
|
|
|
|
|
if (val) |
974
|
4076
|
50
|
|
|
|
|
SvSetMagicSV((SV *) gv, val); |
|
|
50
|
|
|
|
|
|
975
|
|
|
|
|
|
|
|
976
|
4084
|
|
|
|
|
|
return; |
977
|
|
|
|
|
|
|
} |
978
|
|
|
|
|
|
|
|
979
|
|
|
|
|
|
|
/* ... Unique context ID ................................................... */ |
980
|
|
|
|
|
|
|
|
981
|
|
|
|
|
|
|
/* We must pass the index because XSH_CXT.uid_storage might be reallocated |
982
|
|
|
|
|
|
|
* between the UID fetch and the invalidation at the end of scope. */ |
983
|
|
|
|
|
|
|
|
984
|
|
|
|
|
|
|
typedef struct { |
985
|
|
|
|
|
|
|
su_ud_common ci; |
986
|
|
|
|
|
|
|
I32 idx; |
987
|
|
|
|
|
|
|
} su_ud_uid; |
988
|
|
|
|
|
|
|
|
989
|
823
|
|
|
|
|
|
static void su_uid_drop(pTHX_ void *ud_) { |
990
|
823
|
|
|
|
|
|
su_ud_uid *ud = ud_; |
991
|
|
|
|
|
|
|
dXSH_CXT; |
992
|
|
|
|
|
|
|
|
993
|
823
|
|
|
|
|
|
XSH_CXT.uid_storage.map[ud->idx].flags &= ~SU_UID_ACTIVE; |
994
|
|
|
|
|
|
|
|
995
|
823
|
50
|
|
|
|
|
SU_UD_FREE(ud); |
996
|
|
|
|
|
|
|
|
997
|
823
|
|
|
|
|
|
return; |
998
|
|
|
|
|
|
|
} |
999
|
|
|
|
|
|
|
|
1000
|
|
|
|
|
|
|
/* --- Pop a context back -------------------------------------------------- */ |
1001
|
|
|
|
|
|
|
|
1002
|
|
|
|
|
|
|
#ifdef DEBUGGING |
1003
|
|
|
|
|
|
|
# define SU_CX_TYPENAME(T) PL_block_type[(T)] |
1004
|
|
|
|
|
|
|
#else |
1005
|
|
|
|
|
|
|
# if XSH_HAS_PERL(5, 23, 8) |
1006
|
|
|
|
|
|
|
static const char *su_block_type[] = { |
1007
|
|
|
|
|
|
|
"NULL", |
1008
|
|
|
|
|
|
|
"WHEN", |
1009
|
|
|
|
|
|
|
"BLOCK", |
1010
|
|
|
|
|
|
|
"GIVEN", |
1011
|
|
|
|
|
|
|
"LOOP_ARY", |
1012
|
|
|
|
|
|
|
"LOOP_LAZYSV", |
1013
|
|
|
|
|
|
|
"LOOP_LAZYIV", |
1014
|
|
|
|
|
|
|
"LOOP_LIST", |
1015
|
|
|
|
|
|
|
"LOOP_PLAIN", |
1016
|
|
|
|
|
|
|
"SUB", |
1017
|
|
|
|
|
|
|
"FORMAT", |
1018
|
|
|
|
|
|
|
"EVAL", |
1019
|
|
|
|
|
|
|
"SUBST" |
1020
|
|
|
|
|
|
|
}; |
1021
|
|
|
|
|
|
|
# elif XSH_HAS_PERL(5, 11, 0) |
1022
|
|
|
|
|
|
|
static const char *su_block_type[] = { |
1023
|
|
|
|
|
|
|
"NULL", |
1024
|
|
|
|
|
|
|
"WHEN", |
1025
|
|
|
|
|
|
|
"BLOCK", |
1026
|
|
|
|
|
|
|
"GIVEN", |
1027
|
|
|
|
|
|
|
"LOOP_FOR", |
1028
|
|
|
|
|
|
|
"LOOP_PLAIN", |
1029
|
|
|
|
|
|
|
"LOOP_LAZYSV", |
1030
|
|
|
|
|
|
|
"LOOP_LAZYIV", |
1031
|
|
|
|
|
|
|
"SUB", |
1032
|
|
|
|
|
|
|
"FORMAT", |
1033
|
|
|
|
|
|
|
"EVAL", |
1034
|
|
|
|
|
|
|
"SUBST" |
1035
|
|
|
|
|
|
|
}; |
1036
|
|
|
|
|
|
|
# elif XSH_HAS_PERL(5, 10, 0) |
1037
|
|
|
|
|
|
|
static const char *su_block_type[] = { |
1038
|
|
|
|
|
|
|
"NULL", |
1039
|
|
|
|
|
|
|
"SUB", |
1040
|
|
|
|
|
|
|
"EVAL", |
1041
|
|
|
|
|
|
|
"LOOP", |
1042
|
|
|
|
|
|
|
"SUBST", |
1043
|
|
|
|
|
|
|
"BLOCK", |
1044
|
|
|
|
|
|
|
"FORMAT" |
1045
|
|
|
|
|
|
|
"WHEN", |
1046
|
|
|
|
|
|
|
"GIVEN" |
1047
|
|
|
|
|
|
|
}; |
1048
|
|
|
|
|
|
|
# else |
1049
|
|
|
|
|
|
|
static const char *su_block_type[] = { |
1050
|
|
|
|
|
|
|
"NULL", |
1051
|
|
|
|
|
|
|
"SUB", |
1052
|
|
|
|
|
|
|
"EVAL", |
1053
|
|
|
|
|
|
|
"LOOP", |
1054
|
|
|
|
|
|
|
"SUBST", |
1055
|
|
|
|
|
|
|
"BLOCK", |
1056
|
|
|
|
|
|
|
"FORMAT" |
1057
|
|
|
|
|
|
|
}; |
1058
|
|
|
|
|
|
|
# endif |
1059
|
|
|
|
|
|
|
# define SU_CX_TYPENAME(T) su_block_type[(T)] |
1060
|
|
|
|
|
|
|
#endif |
1061
|
|
|
|
|
|
|
|
1062
|
|
|
|
|
|
|
#define SU_CXNAME(C) SU_CX_TYPENAME(CxTYPE(C)) |
1063
|
|
|
|
|
|
|
|
1064
|
|
|
|
|
|
|
#if XSH_DEBUG |
1065
|
|
|
|
|
|
|
|
1066
|
|
|
|
|
|
|
/* for debugging. These indicate how many ENTERs each context type |
1067
|
|
|
|
|
|
|
* does before the PUSHBLOCK */ |
1068
|
|
|
|
|
|
|
|
1069
|
|
|
|
|
|
|
static const int su_cxt_enter_count[] = { |
1070
|
|
|
|
|
|
|
# if XSH_HAS_PERL(5, 23, 8) |
1071
|
|
|
|
|
|
|
0 /* context pushes no longer do ENTERs */ |
1072
|
|
|
|
|
|
|
# elif XSH_HAS_PERL(5, 11, 0) |
1073
|
|
|
|
|
|
|
/* NULL WHEN BLOCK GIVEN LOOP_FOR LOOP_PLAIN LOOP_LAZYSV |
1074
|
|
|
|
|
|
|
* LOOP_LAZYIV SUB FORMAT EVAL SUBST */ |
1075
|
|
|
|
|
|
|
0, 1, 1, 1, 2, 2, 2, 2, 1, 1, 1, 0 |
1076
|
|
|
|
|
|
|
# elif XSH_HAS_PERL(5, 10, 0) |
1077
|
|
|
|
|
|
|
/* NULL SUB EVAL LOOP SUBST BLOCK FORMAT WHEN GIVEN */ |
1078
|
|
|
|
|
|
|
0, 1, 1, 2, 0, 1, 1, 1, 1 |
1079
|
|
|
|
|
|
|
# else |
1080
|
|
|
|
|
|
|
/* NULL SUB EVAL LOOP SUBST BLOCK FORMAT */ |
1081
|
|
|
|
|
|
|
0, 1, 1, 2, 0, 1, 1 |
1082
|
|
|
|
|
|
|
# endif |
1083
|
|
|
|
|
|
|
}; |
1084
|
|
|
|
|
|
|
|
1085
|
|
|
|
|
|
|
#endif /* XSH_DEBUG */ |
1086
|
|
|
|
|
|
|
|
1087
|
|
|
|
|
|
|
/* push at least 'size' slots worth of padding onto the savestack */ |
1088
|
|
|
|
|
|
|
|
1089
|
45297
|
|
|
|
|
|
static void su_ss_push_padding(pTHX_ void *ud, I32 size) { |
1090
|
|
|
|
|
|
|
#define su_ss_push_padding(U, S) su_ss_push_padding(aTHX_ (U), (S)) |
1091
|
45297
|
100
|
|
|
|
|
if (size <= 0) |
1092
|
6966
|
|
|
|
|
|
return; |
1093
|
|
|
|
|
|
|
|
1094
|
38331
|
100
|
|
|
|
|
if (size < SU_SAVE_ALLOC_SIZE + 1) /* minimum possible SAVEt_ALLOC */ |
1095
|
5986
|
|
|
|
|
|
size = SU_SAVE_ALLOC_SIZE + 1; |
1096
|
|
|
|
|
|
|
|
1097
|
|
|
|
|
|
|
XSH_D(xsh_debug_log( |
1098
|
|
|
|
|
|
|
"%p: push %2d padding at save_ix=%d\n", |
1099
|
|
|
|
|
|
|
ud, size, PL_savestack_ix)); |
1100
|
|
|
|
|
|
|
|
1101
|
38331
|
|
|
|
|
|
save_alloc((size - SU_SAVE_ALLOC_SIZE) * sizeof(*PL_savestack), 0); |
1102
|
|
|
|
|
|
|
|
1103
|
38331
|
|
|
|
|
|
return; |
1104
|
|
|
|
|
|
|
} |
1105
|
|
|
|
|
|
|
|
1106
|
|
|
|
|
|
|
static void su_pop(pTHX_ void *ud); |
1107
|
|
|
|
|
|
|
|
1108
|
|
|
|
|
|
|
/* push an su_pop destructor onto the savestack with suitable padding. |
1109
|
|
|
|
|
|
|
* first indicates that this is the first push of a destructor */ |
1110
|
|
|
|
|
|
|
|
1111
|
40170
|
|
|
|
|
|
static void su_ss_push_destructor(pTHX_ void *ud, I32 depth, bool first) { |
1112
|
|
|
|
|
|
|
#define su_ss_push_destructor(U, D, F) su_ss_push_destructor(aTHX_ (U), (D), (F)) |
1113
|
40170
|
|
|
|
|
|
su_ud_origin_elem *origin = SU_UD_ORIGIN(ud); |
1114
|
|
|
|
|
|
|
|
1115
|
|
|
|
|
|
|
assert(first || origin[depth+1].orig_ix == PL_savestack_ix); |
1116
|
|
|
|
|
|
|
|
1117
|
40170
|
|
|
|
|
|
su_ss_push_padding(ud, |
1118
|
|
|
|
|
|
|
(origin[depth].orig_ix + origin[depth].offset) - PL_savestack_ix); |
1119
|
|
|
|
|
|
|
|
1120
|
|
|
|
|
|
|
XSH_D(xsh_debug_log( |
1121
|
|
|
|
|
|
|
"%p: push destructor at save_ix=%d depth=%d scope_ix=%d\n", |
1122
|
|
|
|
|
|
|
ud, PL_savestack_ix, depth, PL_scopestack_ix)); |
1123
|
|
|
|
|
|
|
|
1124
|
40170
|
|
|
|
|
|
SAVEDESTRUCTOR_X(su_pop, ud); |
1125
|
|
|
|
|
|
|
|
1126
|
|
|
|
|
|
|
assert(first || |
1127
|
|
|
|
|
|
|
PL_savestack_ix <= origin[depth+1].orig_ix + origin[depth+1].offset); |
1128
|
|
|
|
|
|
|
|
1129
|
40170
|
|
|
|
|
|
return; |
1130
|
|
|
|
|
|
|
} |
1131
|
|
|
|
|
|
|
|
1132
|
|
|
|
|
|
|
/* this is called during each leave_scope() via SAVEDESTRUCTOR_X */ |
1133
|
|
|
|
|
|
|
|
1134
|
40170
|
|
|
|
|
|
static void su_pop(pTHX_ void *ud) { |
1135
|
|
|
|
|
|
|
#define su_pop(U) su_pop(aTHX_ (U)) |
1136
|
|
|
|
|
|
|
I32 depth, base, mark; |
1137
|
|
|
|
|
|
|
su_ud_origin_elem *origin; |
1138
|
|
|
|
|
|
|
|
1139
|
40170
|
|
|
|
|
|
depth = SU_UD_DEPTH(ud); |
1140
|
40170
|
|
|
|
|
|
origin = SU_UD_ORIGIN(ud); |
1141
|
|
|
|
|
|
|
|
1142
|
|
|
|
|
|
|
XSH_D(xsh_debug_log("%p: ### su_pop: depth=%d\n", ud, depth)); |
1143
|
|
|
|
|
|
|
|
1144
|
40170
|
|
|
|
|
|
depth--; |
1145
|
40170
|
|
|
|
|
|
mark = PL_savestack_ix; |
1146
|
40170
|
|
|
|
|
|
base = origin[depth].orig_ix; |
1147
|
|
|
|
|
|
|
|
1148
|
|
|
|
|
|
|
XSH_D(xsh_debug_log("%p: residual savestack frame is %d(+%d)..%d\n", |
1149
|
|
|
|
|
|
|
ud, base, origin[depth].offset, mark)); |
1150
|
|
|
|
|
|
|
|
1151
|
40170
|
50
|
|
|
|
|
if (base < mark) { |
1152
|
|
|
|
|
|
|
XSH_D(xsh_debug_log("%p: clear leftovers at %d..%d\n", ud, base, mark)); |
1153
|
40170
|
|
|
|
|
|
leave_scope(base); |
1154
|
|
|
|
|
|
|
} |
1155
|
|
|
|
|
|
|
assert(PL_savestack_ix == base); |
1156
|
|
|
|
|
|
|
|
1157
|
40170
|
|
|
|
|
|
SU_UD_DEPTH(ud) = depth; |
1158
|
|
|
|
|
|
|
|
1159
|
40170
|
100
|
|
|
|
|
if (depth > 0) { |
1160
|
22583
|
|
|
|
|
|
su_ss_push_destructor(ud, depth-1, 0); |
1161
|
|
|
|
|
|
|
} else { |
1162
|
17587
|
|
|
|
|
|
I32 offset = origin[0].offset; /* grab value before origin is freed */ |
1163
|
17587
|
|
|
|
|
|
switch (SU_UD_TYPE(ud)) { |
1164
|
|
|
|
|
|
|
case SU_UD_TYPE_REAP: { |
1165
|
|
|
|
|
|
|
XSH_D( |
1166
|
|
|
|
|
|
|
xsh_debug_log("%p: === reap\n%p: depth=%d scope_ix=%d save_ix=%d\n", |
1167
|
|
|
|
|
|
|
ud, ud, SU_UD_DEPTH(ud), PL_scopestack_ix, PL_savestack_ix) |
1168
|
|
|
|
|
|
|
); |
1169
|
4433
|
|
|
|
|
|
SAVEDESTRUCTOR_X(su_call, SU_UD_REAP_CB(ud)); |
1170
|
4433
|
50
|
|
|
|
|
SU_UD_FREE(ud); |
1171
|
4433
|
|
|
|
|
|
break; |
1172
|
|
|
|
|
|
|
} |
1173
|
|
|
|
|
|
|
case SU_UD_TYPE_LOCALIZE: |
1174
|
12331
|
|
|
|
|
|
su_localize(ud); |
1175
|
12329
|
50
|
|
|
|
|
SU_UD_LOCALIZE_FREE(ud); |
1176
|
12329
|
|
|
|
|
|
break; |
1177
|
|
|
|
|
|
|
case SU_UD_TYPE_UID: |
1178
|
823
|
|
|
|
|
|
SAVEDESTRUCTOR_X(su_uid_drop, ud); |
1179
|
823
|
|
|
|
|
|
break; |
1180
|
|
|
|
|
|
|
} |
1181
|
|
|
|
|
|
|
/* perl 5.23.8 onwards is very fussy about the return from leave_scope() |
1182
|
|
|
|
|
|
|
* leaving PL_savestack_ix where it expects it to be */ |
1183
|
17585
|
100
|
|
|
|
|
if (PL_savestack_ix < base + offset) { |
1184
|
5127
|
|
|
|
|
|
I32 gap = (base + offset) - PL_savestack_ix; |
1185
|
|
|
|
|
|
|
assert(gap >= SU_SAVE_ALLOC_SIZE + 1); |
1186
|
5127
|
|
|
|
|
|
su_ss_push_padding(ud, gap); |
1187
|
|
|
|
|
|
|
} |
1188
|
|
|
|
|
|
|
assert(PL_savestack_ix == base + offset); |
1189
|
|
|
|
|
|
|
} |
1190
|
|
|
|
|
|
|
|
1191
|
|
|
|
|
|
|
XSH_D(xsh_debug_log("%p: end pop: ss_ix=%d\n", ud, PL_savestack_ix)); |
1192
|
40168
|
|
|
|
|
|
} |
1193
|
|
|
|
|
|
|
|
1194
|
|
|
|
|
|
|
/* --- Initialize the stack and the action userdata ------------------------ */ |
1195
|
|
|
|
|
|
|
|
1196
|
17587
|
|
|
|
|
|
static void su_init(pTHX_ void *ud, I32 cxix, I32 size) { |
1197
|
|
|
|
|
|
|
#define su_init(U, C, S) su_init(aTHX_ (U), (C), (S)) |
1198
|
|
|
|
|
|
|
su_ud_origin_elem *origin; |
1199
|
|
|
|
|
|
|
I32 i, depth; |
1200
|
|
|
|
|
|
|
I32 cur_cx_ix, cur_scope_ix; |
1201
|
|
|
|
|
|
|
|
1202
|
|
|
|
|
|
|
XSH_D(xsh_debug_log("%p: ### su_init(cxix=%d, size=%d)\n", ud, cxix, size)); |
1203
|
|
|
|
|
|
|
|
1204
|
17587
|
|
|
|
|
|
depth = PL_scopestack_ix - cxstack[cxix].blk_oldscopesp; |
1205
|
|
|
|
|
|
|
#if SU_HAS_NEW_CXT |
1206
|
17587
|
|
|
|
|
|
depth += (cxstack_ix - cxix); /* each context frame holds 1 scope */ |
1207
|
|
|
|
|
|
|
#endif |
1208
|
|
|
|
|
|
|
XSH_D(xsh_debug_log( |
1209
|
|
|
|
|
|
|
"%p: going down by depth=%d with scope_ix=%d save_ix=%d\n", |
1210
|
|
|
|
|
|
|
ud, depth, PL_scopestack_ix, PL_savestack_ix)); |
1211
|
|
|
|
|
|
|
|
1212
|
|
|
|
|
|
|
/* Artificially increase the position of each savestack frame boundary |
1213
|
|
|
|
|
|
|
* to make space to squeeze in a 'size' sized entry (first one) or a |
1214
|
|
|
|
|
|
|
* SU_SAVE_DESTRUCTOR_SIZE sized entry (higher ones). In addition, make |
1215
|
|
|
|
|
|
|
* sure that each boundary is higher than the previous, so that *every* |
1216
|
|
|
|
|
|
|
* scope exit triggers a call to leave_scope(). Each scope exit will call |
1217
|
|
|
|
|
|
|
* the su_pop() destructor, which is responsible for: freeing any |
1218
|
|
|
|
|
|
|
* savestack entries below the artificially raised floor; then pushing a |
1219
|
|
|
|
|
|
|
* new destructor in that space. On the final pop, the "real" savestack |
1220
|
|
|
|
|
|
|
* action is pushed rather than another destructor. |
1221
|
|
|
|
|
|
|
* |
1222
|
|
|
|
|
|
|
* On older perls, savestack frame boundaries are specified by a range of |
1223
|
|
|
|
|
|
|
* scopestack entries (one per ENTER). Each scope entry typically does |
1224
|
|
|
|
|
|
|
* one or two ENTERs followed by a PUSHBLOCK. Thus the |
1225
|
|
|
|
|
|
|
* cx->blku_oldscopesp field set by the PUSHBLOCK points to the next free |
1226
|
|
|
|
|
|
|
* slot, which is one above the last of the ENTERs. In the debugging |
1227
|
|
|
|
|
|
|
* output we indicate that by bracketing the ENTERs directly preceding |
1228
|
|
|
|
|
|
|
* that context push with dashes, e.g.: |
1229
|
|
|
|
|
|
|
* |
1230
|
|
|
|
|
|
|
* 13b98d8: ------------------ |
1231
|
|
|
|
|
|
|
* 13b98d8: ENTER origin[0] scope[3] savestack=3+3 |
1232
|
|
|
|
|
|
|
* 13b98d8: ENTER origin[1] scope[4] savestack=9+3 |
1233
|
|
|
|
|
|
|
* 13b98d8: cx=1 LOOP_LAZYIV |
1234
|
|
|
|
|
|
|
* 13b98d8: ------------------ |
1235
|
|
|
|
|
|
|
* |
1236
|
|
|
|
|
|
|
* In addition to context stack pushes, other activities can push ENTERs |
1237
|
|
|
|
|
|
|
* too, such as grep expr and XS sub calls. |
1238
|
|
|
|
|
|
|
* |
1239
|
|
|
|
|
|
|
* For newer perls (SU_HAS_NEW_CXT), a context push no longer does any |
1240
|
|
|
|
|
|
|
* ENTERs; instead the old savestack position is stored in the new |
1241
|
|
|
|
|
|
|
* cx->blk_oldsaveix field; thus this field specifies an additional |
1242
|
|
|
|
|
|
|
* savestack frame boundary point in addition to the scopestack entries, |
1243
|
|
|
|
|
|
|
* and will also need adjusting. |
1244
|
|
|
|
|
|
|
* |
1245
|
|
|
|
|
|
|
* We record the original and modified position of each boundary in the |
1246
|
|
|
|
|
|
|
* origin array. |
1247
|
|
|
|
|
|
|
* |
1248
|
|
|
|
|
|
|
* The passed cxix argument represents the scope we wish to inject into; |
1249
|
|
|
|
|
|
|
* we have to adjust all the savestack frame boundaries above (but not |
1250
|
|
|
|
|
|
|
* including) that context. |
1251
|
|
|
|
|
|
|
*/ |
1252
|
|
|
|
|
|
|
|
1253
|
17587
|
50
|
|
|
|
|
Newx(origin, depth, su_ud_origin_elem); |
1254
|
|
|
|
|
|
|
|
1255
|
17587
|
|
|
|
|
|
cur_cx_ix = cxix; |
1256
|
17587
|
|
|
|
|
|
cur_scope_ix = cxstack[cxix].blk_oldscopesp; |
1257
|
|
|
|
|
|
|
|
1258
|
|
|
|
|
|
|
#if SU_HAS_NEW_CXT |
1259
|
|
|
|
|
|
|
XSH_D(xsh_debug_log("%p: cx=%-2d %-11s\n", |
1260
|
|
|
|
|
|
|
ud, cur_cx_ix, SU_CXNAME(cxstack+cur_cx_ix))); |
1261
|
17587
|
|
|
|
|
|
cur_cx_ix++; |
1262
|
|
|
|
|
|
|
#endif |
1263
|
|
|
|
|
|
|
|
1264
|
57757
|
100
|
|
|
|
|
for (i = 0; cur_scope_ix < PL_scopestack_ix; i++) { |
1265
|
|
|
|
|
|
|
I32 *ixp; |
1266
|
|
|
|
|
|
|
I32 offset; |
1267
|
|
|
|
|
|
|
|
1268
|
|
|
|
|
|
|
#if SU_HAS_NEW_CXT |
1269
|
|
|
|
|
|
|
|
1270
|
40170
|
100
|
|
|
|
|
if (cur_cx_ix <= cxstack_ix |
1271
|
22583
|
100
|
|
|
|
|
&& cur_scope_ix == cxstack[cur_cx_ix].blk_oldscopesp) |
1272
|
22579
|
|
|
|
|
|
ixp = &(cxstack[cur_cx_ix++].blk_oldsaveix); |
1273
|
|
|
|
|
|
|
else |
1274
|
17591
|
|
|
|
|
|
ixp = &PL_scopestack[cur_scope_ix++]; /* an ENTER pushed after cur context */ |
1275
|
|
|
|
|
|
|
|
1276
|
|
|
|
|
|
|
#else |
1277
|
|
|
|
|
|
|
|
1278
|
|
|
|
|
|
|
XSH_D({ |
1279
|
|
|
|
|
|
|
if (cur_cx_ix <= cxstack_ix) { |
1280
|
|
|
|
|
|
|
if (cur_scope_ix == cxstack[cur_cx_ix].blk_oldscopesp) { |
1281
|
|
|
|
|
|
|
xsh_debug_log("%p: cx=%-2d %s\n%p: ------------------\n", |
1282
|
|
|
|
|
|
|
ud, cur_cx_ix, SU_CXNAME(cxstack+cur_cx_ix), ud); |
1283
|
|
|
|
|
|
|
cur_cx_ix++; |
1284
|
|
|
|
|
|
|
} |
1285
|
|
|
|
|
|
|
else if (cur_scope_ix + su_cxt_enter_count[CxTYPE(cxstack+cur_cx_ix)] |
1286
|
|
|
|
|
|
|
== cxstack[cur_cx_ix].blk_oldscopesp) |
1287
|
|
|
|
|
|
|
xsh_debug_log("%p: ------------------\n", ud); |
1288
|
|
|
|
|
|
|
} |
1289
|
|
|
|
|
|
|
}); |
1290
|
|
|
|
|
|
|
|
1291
|
|
|
|
|
|
|
ixp = &PL_scopestack[cur_scope_ix++]; |
1292
|
|
|
|
|
|
|
|
1293
|
|
|
|
|
|
|
#endif |
1294
|
|
|
|
|
|
|
|
1295
|
40170
|
100
|
|
|
|
|
if (i == 0) { |
1296
|
17587
|
|
|
|
|
|
offset = size; |
1297
|
|
|
|
|
|
|
} else { |
1298
|
|
|
|
|
|
|
/* we have three constraints to satisfy: |
1299
|
|
|
|
|
|
|
* 1) Each adjusted offset must be at least SU_SAVE_DESTRUCTOR_SIZE |
1300
|
|
|
|
|
|
|
* above its unadjusted boundary, so that there is space to inject a |
1301
|
|
|
|
|
|
|
* destructor into the outer scope. |
1302
|
|
|
|
|
|
|
* 2) Each adjusted boundary must be at least SU_SAVE_DESTRUCTOR_SIZE |
1303
|
|
|
|
|
|
|
* higher than the previous adjusted boundary, so that a new |
1304
|
|
|
|
|
|
|
* destructor can be added below the Nth adjusted frame boundary, |
1305
|
|
|
|
|
|
|
* but be within the (N-1)th adjusted frame and so be triggered on |
1306
|
|
|
|
|
|
|
* the next scope exit; |
1307
|
|
|
|
|
|
|
* 3) If the adjustment needs to be greater than SU_SAVE_DESTRUCTOR_SIZE, |
1308
|
|
|
|
|
|
|
* then it should be greater by an amount of at least the minimum |
1309
|
|
|
|
|
|
|
* pad side, so a destructor and padding can be pushed. |
1310
|
|
|
|
|
|
|
*/ |
1311
|
|
|
|
|
|
|
I32 pad; |
1312
|
22583
|
|
|
|
|
|
offset = SU_SAVE_DESTRUCTOR_SIZE; /* rule 1 */ |
1313
|
45166
|
|
|
|
|
|
pad = (origin[i-1].orig_ix + origin[i-1].offset) + offset |
1314
|
22583
|
|
|
|
|
|
- (*ixp + offset); |
1315
|
22583
|
100
|
|
|
|
|
if (pad > 0) { /* rule 2 */ |
1316
|
15617
|
100
|
|
|
|
|
if (pad < SU_SAVE_ALLOC_SIZE + 1) /* rule 3 */ |
1317
|
74
|
|
|
|
|
|
pad = SU_SAVE_ALLOC_SIZE + 1; |
1318
|
15617
|
|
|
|
|
|
offset += pad; |
1319
|
|
|
|
|
|
|
} |
1320
|
|
|
|
|
|
|
} |
1321
|
|
|
|
|
|
|
|
1322
|
40170
|
|
|
|
|
|
origin[i].offset = offset; |
1323
|
40170
|
|
|
|
|
|
origin[i].orig_ix = *ixp; |
1324
|
40170
|
|
|
|
|
|
*ixp += offset; |
1325
|
|
|
|
|
|
|
|
1326
|
|
|
|
|
|
|
#if SU_HAS_NEW_CXT |
1327
|
|
|
|
|
|
|
XSH_D({ |
1328
|
|
|
|
|
|
|
if (ixp == &PL_scopestack[cur_scope_ix-1]) |
1329
|
|
|
|
|
|
|
xsh_debug_log( |
1330
|
|
|
|
|
|
|
"%p: ENTER origin[%d] scope[%d] savestack=%d+%d\n", |
1331
|
|
|
|
|
|
|
ud, i, cur_scope_ix, origin[i].orig_ix, origin[i].offset); |
1332
|
|
|
|
|
|
|
else |
1333
|
|
|
|
|
|
|
xsh_debug_log( |
1334
|
|
|
|
|
|
|
"%p: cx=%-2d %-11s origin[%d] scope[%d] savestack=%d+%d\n", |
1335
|
|
|
|
|
|
|
ud, cur_cx_ix-1, SU_CXNAME(cxstack+cur_cx_ix-1), |
1336
|
|
|
|
|
|
|
i, cur_scope_ix, origin[i].orig_ix, origin[i].offset); |
1337
|
|
|
|
|
|
|
}); |
1338
|
|
|
|
|
|
|
#else |
1339
|
|
|
|
|
|
|
XSH_D(xsh_debug_log( |
1340
|
|
|
|
|
|
|
"%p: ENTER origin[%d] scope[%d] savestack=%d+%d\n", |
1341
|
|
|
|
|
|
|
ud, i, cur_scope_ix, origin[i].orig_ix, origin[i].offset)); |
1342
|
|
|
|
|
|
|
#endif |
1343
|
|
|
|
|
|
|
|
1344
|
|
|
|
|
|
|
} |
1345
|
|
|
|
|
|
|
|
1346
|
|
|
|
|
|
|
assert(i == depth); |
1347
|
|
|
|
|
|
|
|
1348
|
17587
|
|
|
|
|
|
SU_UD_DEPTH(ud) = depth; |
1349
|
17587
|
|
|
|
|
|
SU_UD_ORIGIN(ud) = origin; |
1350
|
|
|
|
|
|
|
|
1351
|
17587
|
|
|
|
|
|
su_ss_push_destructor(ud, depth-1, 1); |
1352
|
17587
|
|
|
|
|
|
} |
1353
|
|
|
|
|
|
|
|
1354
|
|
|
|
|
|
|
/* --- Unwind stack -------------------------------------------------------- */ |
1355
|
|
|
|
|
|
|
|
1356
|
5231
|
|
|
|
|
|
static void su_unwind(pTHX_ void *ud_) { |
1357
|
|
|
|
|
|
|
dXSH_CXT; |
1358
|
5231
|
|
|
|
|
|
I32 cxix = XSH_CXT.unwind_storage.cxix; |
1359
|
5231
|
|
|
|
|
|
I32 items = XSH_CXT.unwind_storage.items; |
1360
|
|
|
|
|
|
|
I32 mark; |
1361
|
|
|
|
|
|
|
|
1362
|
|
|
|
|
|
|
PERL_UNUSED_VAR(ud_); |
1363
|
|
|
|
|
|
|
|
1364
|
5231
|
|
|
|
|
|
PL_stack_sp = XSH_CXT.unwind_storage.savesp; |
1365
|
|
|
|
|
|
|
#if XSH_HAS_PERL(5, 19, 4) |
1366
|
|
|
|
|
|
|
{ |
1367
|
|
|
|
|
|
|
I32 i; |
1368
|
5231
|
|
|
|
|
|
SV **sp = PL_stack_sp; |
1369
|
10566
|
100
|
|
|
|
|
for (i = -items + 1; i <= 0; ++i) |
1370
|
5335
|
100
|
|
|
|
|
if (!SvTEMP(sp[i])) |
1371
|
5321
|
|
|
|
|
|
sv_2mortal(SvREFCNT_inc(sp[i])); |
1372
|
|
|
|
|
|
|
} |
1373
|
|
|
|
|
|
|
#endif |
1374
|
|
|
|
|
|
|
|
1375
|
5231
|
100
|
|
|
|
|
if (cxstack_ix > cxix) |
1376
|
3912
|
|
|
|
|
|
dounwind(cxix); |
1377
|
|
|
|
|
|
|
|
1378
|
5231
|
|
|
|
|
|
mark = PL_markstack[cxstack[cxix].blk_oldmarksp]; |
1379
|
5231
|
50
|
|
|
|
|
PUSHMARK(PL_stack_sp - items); |
1380
|
|
|
|
|
|
|
|
1381
|
|
|
|
|
|
|
XSH_D({ |
1382
|
|
|
|
|
|
|
I32 gimme = GIMME_V; |
1383
|
|
|
|
|
|
|
xsh_debug_log("%p: cx=%d gimme=%s items=%d sp=%d oldmark=%d mark=%d\n", |
1384
|
|
|
|
|
|
|
&XSH_CXT, cxix, |
1385
|
|
|
|
|
|
|
gimme == G_VOID ? "void" : gimme == G_ARRAY ? "list" : "scalar", |
1386
|
|
|
|
|
|
|
items, PL_stack_sp - PL_stack_base, *PL_markstack_ptr, mark); |
1387
|
|
|
|
|
|
|
}); |
1388
|
|
|
|
|
|
|
|
1389
|
5231
|
|
|
|
|
|
PL_op = (OP *) &(XSH_CXT.unwind_storage.return_op); |
1390
|
5231
|
|
|
|
|
|
PL_op = PL_op->op_ppaddr(aTHX); |
1391
|
|
|
|
|
|
|
|
1392
|
5231
|
|
|
|
|
|
*PL_markstack_ptr = mark; |
1393
|
|
|
|
|
|
|
|
1394
|
5231
|
|
|
|
|
|
XSH_CXT.unwind_storage.proxy_op.op_next = PL_op; |
1395
|
5231
|
|
|
|
|
|
PL_op = &(XSH_CXT.unwind_storage.proxy_op); |
1396
|
5231
|
|
|
|
|
|
} |
1397
|
|
|
|
|
|
|
|
1398
|
|
|
|
|
|
|
/* --- Yield --------------------------------------------------------------- */ |
1399
|
|
|
|
|
|
|
|
1400
|
|
|
|
|
|
|
#if XSH_HAS_PERL(5, 10, 0) |
1401
|
|
|
|
|
|
|
# define SU_RETOP_SUB(C) ((C)->blk_sub.retop) |
1402
|
|
|
|
|
|
|
# define SU_RETOP_EVAL(C) ((C)->blk_eval.retop) |
1403
|
|
|
|
|
|
|
# define SU_RETOP_LOOP(C) ((C)->blk_loop.my_op->op_lastop->op_next) |
1404
|
|
|
|
|
|
|
# define SU_RETOP_GIVEN(C) ((C)->blk_givwhen.leave_op->op_next) |
1405
|
|
|
|
|
|
|
#else |
1406
|
|
|
|
|
|
|
# define SU_RETOP_SUB(C) ((C)->blk_oldretsp > 0 ? PL_retstack[(C)->blk_oldretsp - 1] : NULL) |
1407
|
|
|
|
|
|
|
# define SU_RETOP_EVAL(C) SU_RETOP_SUB(C) |
1408
|
|
|
|
|
|
|
# define SU_RETOP_LOOP(C) ((C)->blk_loop.last_op->op_next) |
1409
|
|
|
|
|
|
|
#endif |
1410
|
|
|
|
|
|
|
|
1411
|
41530
|
|
|
|
|
|
static void su_yield(pTHX_ void *ud_) { |
1412
|
|
|
|
|
|
|
dXSH_CXT; |
1413
|
|
|
|
|
|
|
PERL_CONTEXT *cx; |
1414
|
41530
|
|
|
|
|
|
const char *which = ud_; |
1415
|
41530
|
|
|
|
|
|
I32 cxix = XSH_CXT.yield_storage.cxix; |
1416
|
41530
|
|
|
|
|
|
I32 items = XSH_CXT.yield_storage.items; |
1417
|
41530
|
|
|
|
|
|
opcode type = OP_NULL; |
1418
|
41530
|
|
|
|
|
|
U8 flags = 0; |
1419
|
|
|
|
|
|
|
OP *next; |
1420
|
|
|
|
|
|
|
|
1421
|
41530
|
|
|
|
|
|
cx = cxstack + cxix; |
1422
|
41530
|
|
|
|
|
|
switch (CxTYPE(cx)) { |
1423
|
|
|
|
|
|
|
case CXt_BLOCK: { |
1424
|
15584
|
|
|
|
|
|
I32 i, cur = cxstack_ix, n = 1; |
1425
|
15584
|
|
|
|
|
|
OP *o = NULL; |
1426
|
|
|
|
|
|
|
/* Is this actually a given/when block? This may occur only when yield was |
1427
|
|
|
|
|
|
|
* called with HERE (or nothing) as the context. */ |
1428
|
|
|
|
|
|
|
#if XSH_HAS_PERL(5, 10, 0) |
1429
|
15584
|
50
|
|
|
|
|
if (cxix > 0) { |
1430
|
15584
|
|
|
|
|
|
PERL_CONTEXT *prev = cx - 1; |
1431
|
15584
|
|
|
|
|
|
U8 prev_type = CxTYPE(prev); |
1432
|
15584
|
50
|
|
|
|
|
if ((prev_type == CXt_GIVEN || prev_type == CXt_WHEN) |
|
|
50
|
|
|
|
|
|
1433
|
0
|
0
|
|
|
|
|
&& (prev->blk_oldcop == cx->blk_oldcop)) { |
1434
|
0
|
|
|
|
|
|
cxix--; |
1435
|
0
|
|
|
|
|
|
cx = prev; |
1436
|
0
|
0
|
|
|
|
|
if (prev_type == CXt_GIVEN) |
1437
|
0
|
|
|
|
|
|
goto cxt_given; |
1438
|
|
|
|
|
|
|
else |
1439
|
0
|
|
|
|
|
|
goto cxt_when; |
1440
|
|
|
|
|
|
|
} |
1441
|
|
|
|
|
|
|
} |
1442
|
|
|
|
|
|
|
#endif |
1443
|
15584
|
|
|
|
|
|
type = OP_LEAVE; |
1444
|
15584
|
|
|
|
|
|
next = NULL; |
1445
|
|
|
|
|
|
|
/* Bare blocks (that appear as do { ... } blocks, map { ... } blocks or |
1446
|
|
|
|
|
|
|
* constant folded blcoks) don't need to save the op to return to anywhere |
1447
|
|
|
|
|
|
|
* since 'last' isn't supposed to work inside them. So we climb higher in |
1448
|
|
|
|
|
|
|
* the context stack until we reach a context that has a return op (i.e. a |
1449
|
|
|
|
|
|
|
* sub, an eval, a format or a real loop), recording how many blocks we |
1450
|
|
|
|
|
|
|
* crossed. Then we follow the op_next chain until we get to the leave op |
1451
|
|
|
|
|
|
|
* that closes the original block, which we are assured to reach since |
1452
|
|
|
|
|
|
|
* everything is static (the blocks we have crossed cannot be evals or |
1453
|
|
|
|
|
|
|
* subroutine calls). */ |
1454
|
15586
|
100
|
|
|
|
|
for (i = cxix + 1; i <= cur; ++i) { |
1455
|
15567
|
|
|
|
|
|
PERL_CONTEXT *cx2 = cxstack + i; |
1456
|
15567
|
|
|
|
|
|
switch (CxTYPE(cx2)) { |
1457
|
|
|
|
|
|
|
case CXt_BLOCK: |
1458
|
2
|
|
|
|
|
|
++n; |
1459
|
2
|
|
|
|
|
|
break; |
1460
|
|
|
|
|
|
|
case CXt_SUB: |
1461
|
|
|
|
|
|
|
case CXt_FORMAT: |
1462
|
15552
|
|
|
|
|
|
o = SU_RETOP_SUB(cx2); |
1463
|
15552
|
|
|
|
|
|
break; |
1464
|
|
|
|
|
|
|
case CXt_EVAL: |
1465
|
7
|
|
|
|
|
|
o = SU_RETOP_EVAL(cx2); |
1466
|
7
|
|
|
|
|
|
break; |
1467
|
|
|
|
|
|
|
#if XSH_HAS_PERL(5, 11, 0) |
1468
|
|
|
|
|
|
|
# if XSH_HAS_PERL(5, 23, 8) |
1469
|
|
|
|
|
|
|
case CXt_LOOP_ARY: |
1470
|
|
|
|
|
|
|
case CXt_LOOP_LIST: |
1471
|
|
|
|
|
|
|
# else |
1472
|
|
|
|
|
|
|
case CXt_LOOP_FOR: |
1473
|
|
|
|
|
|
|
# endif |
1474
|
|
|
|
|
|
|
case CXt_LOOP_PLAIN: |
1475
|
|
|
|
|
|
|
case CXt_LOOP_LAZYSV: |
1476
|
|
|
|
|
|
|
case CXt_LOOP_LAZYIV: |
1477
|
|
|
|
|
|
|
#else |
1478
|
|
|
|
|
|
|
case CXt_LOOP: |
1479
|
|
|
|
|
|
|
#endif |
1480
|
6
|
|
|
|
|
|
o = SU_RETOP_LOOP(cx2); |
1481
|
6
|
|
|
|
|
|
break; |
1482
|
|
|
|
|
|
|
} |
1483
|
15567
|
100
|
|
|
|
|
if (o) |
1484
|
15565
|
|
|
|
|
|
break; |
1485
|
|
|
|
|
|
|
} |
1486
|
15584
|
100
|
|
|
|
|
if (!o) |
1487
|
19
|
|
|
|
|
|
o = PL_op; |
1488
|
39079
|
50
|
|
|
|
|
while (n && o) { |
|
|
50
|
|
|
|
|
|
1489
|
|
|
|
|
|
|
/* We may find other enter/leave blocks on our way to the matching leave. |
1490
|
|
|
|
|
|
|
* Make sure the depth is incremented/decremented appropriately. */ |
1491
|
39079
|
100
|
|
|
|
|
if (o->op_type == OP_ENTER) { |
1492
|
2
|
|
|
|
|
|
++n; |
1493
|
39077
|
100
|
|
|
|
|
} else if (o->op_type == OP_LEAVE) { |
1494
|
15588
|
|
|
|
|
|
--n; |
1495
|
15588
|
100
|
|
|
|
|
if (!n) { |
1496
|
15584
|
|
|
|
|
|
next = o->op_next; |
1497
|
15584
|
|
|
|
|
|
break; |
1498
|
|
|
|
|
|
|
} |
1499
|
|
|
|
|
|
|
} |
1500
|
23495
|
|
|
|
|
|
o = o->op_next; |
1501
|
|
|
|
|
|
|
} |
1502
|
15584
|
|
|
|
|
|
break; |
1503
|
|
|
|
|
|
|
} |
1504
|
|
|
|
|
|
|
case CXt_SUB: |
1505
|
|
|
|
|
|
|
case CXt_FORMAT: |
1506
|
18158
|
|
|
|
|
|
type = OP_LEAVESUB; |
1507
|
18158
|
|
|
|
|
|
next = SU_RETOP_SUB(cx); |
1508
|
18158
|
|
|
|
|
|
break; |
1509
|
|
|
|
|
|
|
case CXt_EVAL: |
1510
|
7778
|
100
|
|
|
|
|
type = CxTRYBLOCK(cx) ? OP_LEAVETRY : OP_LEAVEEVAL; |
1511
|
7778
|
|
|
|
|
|
next = SU_RETOP_EVAL(cx); |
1512
|
7778
|
|
|
|
|
|
break; |
1513
|
|
|
|
|
|
|
#if XSH_HAS_PERL(5, 11, 0) |
1514
|
|
|
|
|
|
|
# if XSH_HAS_PERL(5, 23, 8) |
1515
|
|
|
|
|
|
|
case CXt_LOOP_ARY: |
1516
|
|
|
|
|
|
|
case CXt_LOOP_LIST: |
1517
|
|
|
|
|
|
|
# else |
1518
|
|
|
|
|
|
|
case CXt_LOOP_FOR: |
1519
|
|
|
|
|
|
|
# endif |
1520
|
|
|
|
|
|
|
case CXt_LOOP_PLAIN: |
1521
|
|
|
|
|
|
|
case CXt_LOOP_LAZYSV: |
1522
|
|
|
|
|
|
|
case CXt_LOOP_LAZYIV: |
1523
|
|
|
|
|
|
|
#else |
1524
|
|
|
|
|
|
|
case CXt_LOOP: |
1525
|
|
|
|
|
|
|
#endif |
1526
|
4
|
|
|
|
|
|
type = OP_LEAVELOOP; |
1527
|
4
|
|
|
|
|
|
next = SU_RETOP_LOOP(cx); |
1528
|
4
|
|
|
|
|
|
break; |
1529
|
|
|
|
|
|
|
#if XSH_HAS_PERL(5, 10, 0) |
1530
|
|
|
|
|
|
|
case CXt_GIVEN: |
1531
|
|
|
|
|
|
|
cxt_given: |
1532
|
1
|
|
|
|
|
|
type = OP_LEAVEGIVEN; |
1533
|
1
|
|
|
|
|
|
next = SU_RETOP_GIVEN(cx); |
1534
|
1
|
|
|
|
|
|
break; |
1535
|
|
|
|
|
|
|
case CXt_WHEN: |
1536
|
|
|
|
|
|
|
cxt_when: |
1537
|
|
|
|
|
|
|
#if XSH_HAS_PERL(5, 15, 1) |
1538
|
3
|
|
|
|
|
|
type = OP_LEAVEWHEN; |
1539
|
|
|
|
|
|
|
#else |
1540
|
|
|
|
|
|
|
type = OP_BREAK; |
1541
|
|
|
|
|
|
|
flags |= OPf_SPECIAL; |
1542
|
|
|
|
|
|
|
#endif |
1543
|
3
|
|
|
|
|
|
next = NULL; |
1544
|
3
|
|
|
|
|
|
break; |
1545
|
|
|
|
|
|
|
#endif |
1546
|
|
|
|
|
|
|
case CXt_SUBST: |
1547
|
2
|
|
|
|
|
|
croak("%s() can't target a substitution context", which); |
1548
|
|
|
|
|
|
|
break; |
1549
|
|
|
|
|
|
|
default: |
1550
|
0
|
|
|
|
|
|
croak("%s() doesn't know how to leave a %s context", |
1551
|
0
|
|
|
|
|
|
which, SU_CXNAME(cxstack + cxix)); |
1552
|
|
|
|
|
|
|
break; |
1553
|
|
|
|
|
|
|
} |
1554
|
|
|
|
|
|
|
|
1555
|
41528
|
|
|
|
|
|
PL_stack_sp = XSH_CXT.yield_storage.savesp; |
1556
|
|
|
|
|
|
|
#if XSH_HAS_PERL(5, 19, 4) |
1557
|
|
|
|
|
|
|
{ |
1558
|
|
|
|
|
|
|
I32 i; |
1559
|
41528
|
|
|
|
|
|
SV **sp = PL_stack_sp; |
1560
|
83119
|
100
|
|
|
|
|
for (i = -items + 1; i <= 0; ++i) |
1561
|
41591
|
100
|
|
|
|
|
if (!SvTEMP(sp[i])) |
1562
|
41589
|
|
|
|
|
|
sv_2mortal(SvREFCNT_inc(sp[i])); |
1563
|
|
|
|
|
|
|
} |
1564
|
|
|
|
|
|
|
#endif |
1565
|
|
|
|
|
|
|
|
1566
|
41528
|
100
|
|
|
|
|
if (cxstack_ix > cxix) |
1567
|
31124
|
|
|
|
|
|
dounwind(cxix); |
1568
|
|
|
|
|
|
|
|
1569
|
|
|
|
|
|
|
/* Copy the arguments passed to yield() where the leave op expects to find |
1570
|
|
|
|
|
|
|
* them. */ |
1571
|
41528
|
100
|
|
|
|
|
if (items) |
1572
|
27690
|
50
|
|
|
|
|
Move(PL_stack_sp - items + 1, PL_stack_base + cx->blk_oldsp + 1, items, SV *); |
1573
|
41528
|
|
|
|
|
|
PL_stack_sp = PL_stack_base + cx->blk_oldsp + items; |
1574
|
|
|
|
|
|
|
|
1575
|
41528
|
|
|
|
|
|
flags |= OP_GIMME_REVERSE(cx->blk_gimme); |
1576
|
|
|
|
|
|
|
|
1577
|
41528
|
|
|
|
|
|
XSH_CXT.yield_storage.leave_op.op_type = type; |
1578
|
41528
|
|
|
|
|
|
XSH_CXT.yield_storage.leave_op.op_ppaddr = PL_ppaddr[type]; |
1579
|
41528
|
|
|
|
|
|
XSH_CXT.yield_storage.leave_op.op_flags = flags; |
1580
|
41528
|
|
|
|
|
|
XSH_CXT.yield_storage.leave_op.op_next = next; |
1581
|
|
|
|
|
|
|
|
1582
|
41528
|
|
|
|
|
|
PL_op = (OP *) &(XSH_CXT.yield_storage.leave_op); |
1583
|
41528
|
|
|
|
|
|
PL_op = PL_op->op_ppaddr(aTHX); |
1584
|
|
|
|
|
|
|
|
1585
|
41528
|
|
|
|
|
|
XSH_CXT.yield_storage.proxy_op.op_next = PL_op; |
1586
|
41528
|
|
|
|
|
|
PL_op = &(XSH_CXT.yield_storage.proxy_op); |
1587
|
41528
|
|
|
|
|
|
} |
1588
|
|
|
|
|
|
|
|
1589
|
|
|
|
|
|
|
/* --- Uplevel ------------------------------------------------------------- */ |
1590
|
|
|
|
|
|
|
|
1591
|
|
|
|
|
|
|
#define SU_UPLEVEL_SAVE(f, t) STMT_START { sud->old_##f = PL_##f; PL_##f = (t); } STMT_END |
1592
|
|
|
|
|
|
|
#define SU_UPLEVEL_RESTORE(f) STMT_START { PL_##f = sud->old_##f; } STMT_END |
1593
|
|
|
|
|
|
|
|
1594
|
2749
|
|
|
|
|
|
static su_uplevel_ud *su_uplevel_storage_new(pTHX_ I32 cxix) { |
1595
|
|
|
|
|
|
|
#define su_uplevel_storage_new(I) su_uplevel_storage_new(aTHX_ (I)) |
1596
|
|
|
|
|
|
|
su_uplevel_ud *sud; |
1597
|
|
|
|
|
|
|
UV depth; |
1598
|
|
|
|
|
|
|
dXSH_CXT; |
1599
|
|
|
|
|
|
|
|
1600
|
2749
|
|
|
|
|
|
sud = XSH_CXT.uplevel_storage.root; |
1601
|
2749
|
100
|
|
|
|
|
if (sud) { |
1602
|
2507
|
|
|
|
|
|
XSH_CXT.uplevel_storage.root = sud->next; |
1603
|
2507
|
|
|
|
|
|
XSH_CXT.uplevel_storage.count--; |
1604
|
|
|
|
|
|
|
} else { |
1605
|
242
|
|
|
|
|
|
sud = su_uplevel_ud_new(); |
1606
|
|
|
|
|
|
|
} |
1607
|
|
|
|
|
|
|
|
1608
|
2749
|
|
|
|
|
|
sud->next = XSH_CXT.uplevel_storage.top; |
1609
|
2749
|
|
|
|
|
|
XSH_CXT.uplevel_storage.top = sud; |
1610
|
|
|
|
|
|
|
|
1611
|
2749
|
|
|
|
|
|
depth = su_uid_depth(cxix); |
1612
|
2749
|
|
|
|
|
|
su_uid_storage_dup(&sud->tmp_uid_storage, &XSH_CXT.uid_storage, depth); |
1613
|
2749
|
|
|
|
|
|
sud->old_uid_storage = XSH_CXT.uid_storage; |
1614
|
2749
|
|
|
|
|
|
XSH_CXT.uid_storage = sud->tmp_uid_storage; |
1615
|
|
|
|
|
|
|
|
1616
|
2749
|
|
|
|
|
|
return sud; |
1617
|
|
|
|
|
|
|
} |
1618
|
|
|
|
|
|
|
|
1619
|
|
|
|
|
|
|
#if XSH_HAS_PERL(5, 13, 7) |
1620
|
|
|
|
|
|
|
|
1621
|
2749
|
|
|
|
|
|
static void su_uplevel_storage_delete(pTHX_ su_uplevel_ud *sud) { |
1622
|
|
|
|
|
|
|
#define su_uplevel_storage_delete(S) su_uplevel_storage_delete(aTHX_ (S)) |
1623
|
|
|
|
|
|
|
dXSH_CXT; |
1624
|
|
|
|
|
|
|
|
1625
|
2749
|
|
|
|
|
|
sud->tmp_uid_storage = XSH_CXT.uid_storage; |
1626
|
2749
|
|
|
|
|
|
XSH_CXT.uid_storage = sud->old_uid_storage; |
1627
|
|
|
|
|
|
|
{ |
1628
|
|
|
|
|
|
|
su_uid *map; |
1629
|
|
|
|
|
|
|
STRLEN i, alloc; |
1630
|
2749
|
|
|
|
|
|
map = sud->tmp_uid_storage.map; |
1631
|
2749
|
|
|
|
|
|
alloc = sud->tmp_uid_storage.alloc; |
1632
|
16485
|
100
|
|
|
|
|
for (i = 0; i < alloc; ++i) |
1633
|
13736
|
|
|
|
|
|
map[i].flags &= ~SU_UID_ACTIVE; |
1634
|
|
|
|
|
|
|
} |
1635
|
2749
|
|
|
|
|
|
XSH_CXT.uplevel_storage.top = sud->next; |
1636
|
|
|
|
|
|
|
|
1637
|
2749
|
100
|
|
|
|
|
if (XSH_CXT.uplevel_storage.count >= SU_UPLEVEL_STORAGE_SIZE) { |
1638
|
224
|
|
|
|
|
|
su_uplevel_ud_delete(sud); |
1639
|
|
|
|
|
|
|
} else { |
1640
|
2525
|
|
|
|
|
|
sud->next = XSH_CXT.uplevel_storage.root; |
1641
|
2525
|
|
|
|
|
|
XSH_CXT.uplevel_storage.root = sud; |
1642
|
2525
|
|
|
|
|
|
XSH_CXT.uplevel_storage.count++; |
1643
|
|
|
|
|
|
|
} |
1644
|
2749
|
|
|
|
|
|
} |
1645
|
|
|
|
|
|
|
|
1646
|
|
|
|
|
|
|
#endif |
1647
|
|
|
|
|
|
|
|
1648
|
0
|
|
|
|
|
|
static int su_uplevel_goto_static(const OP *o) { |
1649
|
0
|
0
|
|
|
|
|
for (; o; o = OpSIBLING(o)) { |
|
|
0
|
|
|
|
|
|
1650
|
|
|
|
|
|
|
/* goto ops are unops with kids. */ |
1651
|
0
|
0
|
|
|
|
|
if (!(o->op_flags & OPf_KIDS)) |
1652
|
0
|
|
|
|
|
|
continue; |
1653
|
|
|
|
|
|
|
|
1654
|
0
|
|
|
|
|
|
switch (o->op_type) { |
1655
|
|
|
|
|
|
|
case OP_LEAVEEVAL: |
1656
|
|
|
|
|
|
|
case OP_LEAVETRY: |
1657
|
|
|
|
|
|
|
/* Don't care about gotos inside eval, as they are forbidden at run time. */ |
1658
|
0
|
|
|
|
|
|
break; |
1659
|
|
|
|
|
|
|
case OP_GOTO: |
1660
|
0
|
|
|
|
|
|
return 1; |
1661
|
|
|
|
|
|
|
default: |
1662
|
0
|
0
|
|
|
|
|
if (su_uplevel_goto_static(((const UNOP *) o)->op_first)) |
1663
|
0
|
|
|
|
|
|
return 1; |
1664
|
0
|
|
|
|
|
|
break; |
1665
|
|
|
|
|
|
|
} |
1666
|
|
|
|
|
|
|
} |
1667
|
|
|
|
|
|
|
|
1668
|
0
|
|
|
|
|
|
return 0; |
1669
|
|
|
|
|
|
|
} |
1670
|
|
|
|
|
|
|
|
1671
|
|
|
|
|
|
|
#if !SU_HAS_NEW_CXT && SU_UPLEVEL_HIJACKS_RUNOPS |
1672
|
|
|
|
|
|
|
|
1673
|
|
|
|
|
|
|
static int su_uplevel_goto_runops(pTHX) { |
1674
|
|
|
|
|
|
|
#define su_uplevel_goto_runops() su_uplevel_goto_runops(aTHX) |
1675
|
|
|
|
|
|
|
register OP *op; |
1676
|
|
|
|
|
|
|
dVAR; |
1677
|
|
|
|
|
|
|
|
1678
|
|
|
|
|
|
|
op = PL_op; |
1679
|
|
|
|
|
|
|
do { |
1680
|
|
|
|
|
|
|
if (op->op_type == OP_GOTO) { |
1681
|
|
|
|
|
|
|
AV *argarray = NULL; |
1682
|
|
|
|
|
|
|
I32 cxix; |
1683
|
|
|
|
|
|
|
|
1684
|
|
|
|
|
|
|
for (cxix = cxstack_ix; cxix >= 0; --cxix) { |
1685
|
|
|
|
|
|
|
const PERL_CONTEXT *cx = cxstack + cxix; |
1686
|
|
|
|
|
|
|
|
1687
|
|
|
|
|
|
|
switch (CxTYPE(cx)) { |
1688
|
|
|
|
|
|
|
case CXt_SUB: |
1689
|
|
|
|
|
|
|
if (CxHASARGS(cx)) { |
1690
|
|
|
|
|
|
|
argarray = cx->blk_sub.argarray; |
1691
|
|
|
|
|
|
|
goto done; |
1692
|
|
|
|
|
|
|
} |
1693
|
|
|
|
|
|
|
break; |
1694
|
|
|
|
|
|
|
case CXt_EVAL: |
1695
|
|
|
|
|
|
|
case CXt_FORMAT: |
1696
|
|
|
|
|
|
|
goto done; |
1697
|
|
|
|
|
|
|
default: |
1698
|
|
|
|
|
|
|
break; |
1699
|
|
|
|
|
|
|
} |
1700
|
|
|
|
|
|
|
} |
1701
|
|
|
|
|
|
|
|
1702
|
|
|
|
|
|
|
done: |
1703
|
|
|
|
|
|
|
if (argarray) { |
1704
|
|
|
|
|
|
|
dXSH_CXT; |
1705
|
|
|
|
|
|
|
|
1706
|
|
|
|
|
|
|
if (XSH_CXT.uplevel_storage.top->cxix == cxix) { |
1707
|
|
|
|
|
|
|
AV *args = GvAV(PL_defgv); |
1708
|
|
|
|
|
|
|
I32 items = AvFILLp(args); |
1709
|
|
|
|
|
|
|
|
1710
|
|
|
|
|
|
|
av_extend(argarray, items); |
1711
|
|
|
|
|
|
|
Copy(AvARRAY(args), AvARRAY(argarray), items + 1, SV *); |
1712
|
|
|
|
|
|
|
AvFILLp(argarray) = items; |
1713
|
|
|
|
|
|
|
} |
1714
|
|
|
|
|
|
|
} |
1715
|
|
|
|
|
|
|
} |
1716
|
|
|
|
|
|
|
|
1717
|
|
|
|
|
|
|
PL_op = op = op->op_ppaddr(aTHX); |
1718
|
|
|
|
|
|
|
|
1719
|
|
|
|
|
|
|
#if !XSH_HAS_PERL(5, 13, 0) |
1720
|
|
|
|
|
|
|
PERL_ASYNC_CHECK(); |
1721
|
|
|
|
|
|
|
#endif |
1722
|
|
|
|
|
|
|
} while (op); |
1723
|
|
|
|
|
|
|
|
1724
|
|
|
|
|
|
|
TAINT_NOT; |
1725
|
|
|
|
|
|
|
|
1726
|
|
|
|
|
|
|
return 0; |
1727
|
|
|
|
|
|
|
} |
1728
|
|
|
|
|
|
|
|
1729
|
|
|
|
|
|
|
#endif /* SU_UPLEVEL_HIJACKS_RUNOPS */ |
1730
|
|
|
|
|
|
|
|
1731
|
|
|
|
|
|
|
#define su_at_underscore(C) PadARRAY(PadlistARRAY(CvPADLIST(C))[CvDEPTH(C)])[0] |
1732
|
|
|
|
|
|
|
|
1733
|
|
|
|
|
|
|
#if SU_HAS_NEW_CXT |
1734
|
|
|
|
|
|
|
|
1735
|
2749
|
|
|
|
|
|
static void su_uplevel_restore_new(pTHX_ void *sus_) { |
1736
|
2749
|
|
|
|
|
|
su_uplevel_ud *sud = sus_; |
1737
|
|
|
|
|
|
|
PERL_CONTEXT *cx; |
1738
|
|
|
|
|
|
|
I32 i; |
1739
|
2749
|
|
|
|
|
|
U8 *saved_cxtypes = sud->cxtypes; |
1740
|
|
|
|
|
|
|
|
1741
|
38844
|
100
|
|
|
|
|
for (i = 0; i < sud->gap; i++) { |
1742
|
36095
|
|
|
|
|
|
PERL_CONTEXT *cx = cxstack + sud->cxix + i; |
1743
|
|
|
|
|
|
|
XSH_D(xsh_debug_log("su_uplevel_restore: i=%d cxix=%d type %s => %s\n", |
1744
|
|
|
|
|
|
|
i, cx-cxstack, SU_CX_TYPENAME(CxTYPE(cx)), |
1745
|
|
|
|
|
|
|
SU_CX_TYPENAME(saved_cxtypes[i] & CXTYPEMASK))); |
1746
|
36095
|
|
|
|
|
|
cx->cx_type = saved_cxtypes[i]; |
1747
|
|
|
|
|
|
|
} |
1748
|
2749
|
|
|
|
|
|
Safefree(saved_cxtypes); |
1749
|
|
|
|
|
|
|
|
1750
|
|
|
|
|
|
|
/* renamed is a copy of callback, but they share the same CvPADLIST. |
1751
|
|
|
|
|
|
|
* At this point any calls to renamed should have exited so that its |
1752
|
|
|
|
|
|
|
* depth is back to that of of callback. At this point its safe to free |
1753
|
|
|
|
|
|
|
* renamed, then undo the extra ref count that was ensuring that callback |
1754
|
|
|
|
|
|
|
* remains alive |
1755
|
|
|
|
|
|
|
*/ |
1756
|
|
|
|
|
|
|
assert(sud->renamed); |
1757
|
|
|
|
|
|
|
assert(sud->callback); |
1758
|
|
|
|
|
|
|
|
1759
|
2749
|
|
|
|
|
|
CvDEPTH(sud->callback)--; |
1760
|
|
|
|
|
|
|
assert(CvDEPTH(sud->callback) == CvDEPTH(sud->renamed)); |
1761
|
2749
|
100
|
|
|
|
|
if (!CvISXSUB(sud->renamed)) { |
1762
|
2744
|
|
|
|
|
|
CvDEPTH(sud->renamed) = 0; |
1763
|
2744
|
|
|
|
|
|
CvPADLIST(sud->renamed) = NULL; |
1764
|
|
|
|
|
|
|
} |
1765
|
2749
|
|
|
|
|
|
SvREFCNT_dec(sud->renamed); |
1766
|
2749
|
|
|
|
|
|
SvREFCNT_dec(sud->callback); |
1767
|
|
|
|
|
|
|
|
1768
|
2749
|
|
|
|
|
|
SU_UPLEVEL_RESTORE(curcop); |
1769
|
|
|
|
|
|
|
|
1770
|
2749
|
|
|
|
|
|
su_uplevel_storage_delete(sud); |
1771
|
|
|
|
|
|
|
|
1772
|
2749
|
|
|
|
|
|
return; |
1773
|
|
|
|
|
|
|
} |
1774
|
|
|
|
|
|
|
|
1775
|
|
|
|
|
|
|
#else |
1776
|
|
|
|
|
|
|
|
1777
|
|
|
|
|
|
|
/* 5.23.7 and earlier */ |
1778
|
|
|
|
|
|
|
|
1779
|
|
|
|
|
|
|
static void su_uplevel_restore_old(pTHX_ void *sus_) { |
1780
|
|
|
|
|
|
|
su_uplevel_ud *sud = sus_; |
1781
|
|
|
|
|
|
|
PERL_SI *cur = sud->old_curstackinfo; |
1782
|
|
|
|
|
|
|
PERL_SI *si = sud->si; |
1783
|
|
|
|
|
|
|
|
1784
|
|
|
|
|
|
|
#if SU_UPLEVEL_HIJACKS_RUNOPS |
1785
|
|
|
|
|
|
|
if (PL_runops == su_uplevel_goto_runops) |
1786
|
|
|
|
|
|
|
PL_runops = sud->old_runops; |
1787
|
|
|
|
|
|
|
#endif |
1788
|
|
|
|
|
|
|
|
1789
|
|
|
|
|
|
|
if (sud->callback) { |
1790
|
|
|
|
|
|
|
PERL_CONTEXT *cx = cxstack + sud->cxix; |
1791
|
|
|
|
|
|
|
AV *argarray = MUTABLE_AV(su_at_underscore(sud->callback)); |
1792
|
|
|
|
|
|
|
|
1793
|
|
|
|
|
|
|
/* We have to fix the pad entry for @_ in the original callback because it |
1794
|
|
|
|
|
|
|
* may have been reified. */ |
1795
|
|
|
|
|
|
|
if (AvREAL(argarray)) { |
1796
|
|
|
|
|
|
|
const I32 fill = AvFILLp(argarray); |
1797
|
|
|
|
|
|
|
SvREFCNT_dec(argarray); |
1798
|
|
|
|
|
|
|
argarray = newAV(); |
1799
|
|
|
|
|
|
|
AvREAL_off(argarray); |
1800
|
|
|
|
|
|
|
AvREIFY_on(argarray); |
1801
|
|
|
|
|
|
|
av_extend(argarray, fill); |
1802
|
|
|
|
|
|
|
su_at_underscore(sud->callback) = MUTABLE_SV(argarray); |
1803
|
|
|
|
|
|
|
} else { |
1804
|
|
|
|
|
|
|
CLEAR_ARGARRAY(argarray); |
1805
|
|
|
|
|
|
|
} |
1806
|
|
|
|
|
|
|
|
1807
|
|
|
|
|
|
|
/* If the old cv member is our renamed CV, it means that this place has been |
1808
|
|
|
|
|
|
|
* reached without a goto() happening, and the old argarray member is |
1809
|
|
|
|
|
|
|
* actually our fake argarray. Destroy it properly in that case. */ |
1810
|
|
|
|
|
|
|
if (cx->blk_sub.cv == sud->renamed) { |
1811
|
|
|
|
|
|
|
SvREFCNT_dec(cx->blk_sub.argarray); |
1812
|
|
|
|
|
|
|
cx->blk_sub.argarray = argarray; |
1813
|
|
|
|
|
|
|
} |
1814
|
|
|
|
|
|
|
|
1815
|
|
|
|
|
|
|
CvDEPTH(sud->callback)--; |
1816
|
|
|
|
|
|
|
SvREFCNT_dec(sud->callback); |
1817
|
|
|
|
|
|
|
} |
1818
|
|
|
|
|
|
|
|
1819
|
|
|
|
|
|
|
/* Free the renamed CV. We must do it ourselves so that we can force the |
1820
|
|
|
|
|
|
|
* depth to be 0, or perl would complain about it being "still in use". |
1821
|
|
|
|
|
|
|
* But we *know* that it cannot be so. */ |
1822
|
|
|
|
|
|
|
if (sud->renamed) { |
1823
|
|
|
|
|
|
|
if (!CvISXSUB(sud->renamed)) { |
1824
|
|
|
|
|
|
|
CvDEPTH(sud->renamed) = 0; |
1825
|
|
|
|
|
|
|
CvPADLIST(sud->renamed) = NULL; |
1826
|
|
|
|
|
|
|
} |
1827
|
|
|
|
|
|
|
SvREFCNT_dec(sud->renamed); |
1828
|
|
|
|
|
|
|
} |
1829
|
|
|
|
|
|
|
|
1830
|
|
|
|
|
|
|
CATCH_SET(sud->old_catch); |
1831
|
|
|
|
|
|
|
|
1832
|
|
|
|
|
|
|
SU_UPLEVEL_RESTORE(op); |
1833
|
|
|
|
|
|
|
|
1834
|
|
|
|
|
|
|
/* stack_grow() wants PL_curstack so restore the old stack first */ |
1835
|
|
|
|
|
|
|
if (PL_curstackinfo == si) { |
1836
|
|
|
|
|
|
|
PL_curstack = cur->si_stack; |
1837
|
|
|
|
|
|
|
if (sud->old_mainstack) |
1838
|
|
|
|
|
|
|
SU_UPLEVEL_RESTORE(mainstack); |
1839
|
|
|
|
|
|
|
SU_UPLEVEL_RESTORE(curstackinfo); |
1840
|
|
|
|
|
|
|
|
1841
|
|
|
|
|
|
|
if (sud->died) { |
1842
|
|
|
|
|
|
|
CV *target = sud->target; |
1843
|
|
|
|
|
|
|
I32 levels = 0, i; |
1844
|
|
|
|
|
|
|
|
1845
|
|
|
|
|
|
|
/* When we die, the depth of the target CV is not updated because of the |
1846
|
|
|
|
|
|
|
* stack switcheroo. So we have to look at all the frames between the |
1847
|
|
|
|
|
|
|
* uplevel call and the catch block to count how many call frames to the |
1848
|
|
|
|
|
|
|
* target CV were skipped. */ |
1849
|
|
|
|
|
|
|
for (i = cur->si_cxix; i > sud->cxix; i--) { |
1850
|
|
|
|
|
|
|
register const PERL_CONTEXT *cx = cxstack + i; |
1851
|
|
|
|
|
|
|
|
1852
|
|
|
|
|
|
|
if (CxTYPE(cx) == CXt_SUB) { |
1853
|
|
|
|
|
|
|
if (cx->blk_sub.cv == target) |
1854
|
|
|
|
|
|
|
++levels; |
1855
|
|
|
|
|
|
|
} |
1856
|
|
|
|
|
|
|
} |
1857
|
|
|
|
|
|
|
|
1858
|
|
|
|
|
|
|
/* If we died, the replacement stack was already unwinded to the first |
1859
|
|
|
|
|
|
|
* eval frame, and all the contexts down there were popped. We don't have |
1860
|
|
|
|
|
|
|
* to pop manually any context of the original stack, because they must |
1861
|
|
|
|
|
|
|
* have been in the replacement stack as well (since the second was copied |
1862
|
|
|
|
|
|
|
* from the first). Thus we only have to make sure the original stack index |
1863
|
|
|
|
|
|
|
* points to the context just below the first eval scope under the target |
1864
|
|
|
|
|
|
|
* frame. */ |
1865
|
|
|
|
|
|
|
for (; i >= 0; i--) { |
1866
|
|
|
|
|
|
|
register const PERL_CONTEXT *cx = cxstack + i; |
1867
|
|
|
|
|
|
|
|
1868
|
|
|
|
|
|
|
switch (CxTYPE(cx)) { |
1869
|
|
|
|
|
|
|
case CXt_SUB: |
1870
|
|
|
|
|
|
|
if (cx->blk_sub.cv == target) |
1871
|
|
|
|
|
|
|
++levels; |
1872
|
|
|
|
|
|
|
break; |
1873
|
|
|
|
|
|
|
case CXt_EVAL: |
1874
|
|
|
|
|
|
|
goto found_it; |
1875
|
|
|
|
|
|
|
break; |
1876
|
|
|
|
|
|
|
default: |
1877
|
|
|
|
|
|
|
break; |
1878
|
|
|
|
|
|
|
} |
1879
|
|
|
|
|
|
|
} |
1880
|
|
|
|
|
|
|
|
1881
|
|
|
|
|
|
|
found_it: |
1882
|
|
|
|
|
|
|
CvDEPTH(target) = sud->target_depth - levels; |
1883
|
|
|
|
|
|
|
PL_curstackinfo->si_cxix = i - 1; |
1884
|
|
|
|
|
|
|
|
1885
|
|
|
|
|
|
|
#if !XSH_HAS_PERL(5, 13, 1) |
1886
|
|
|
|
|
|
|
/* Since $@ was maybe localized between the target frame and the uplevel |
1887
|
|
|
|
|
|
|
* call, we forcefully flush the save stack to get rid of it and then |
1888
|
|
|
|
|
|
|
* reset $@ to its proper value. Note that the the call to |
1889
|
|
|
|
|
|
|
* su_uplevel_restore() must happen before the "reset $@" item of the save |
1890
|
|
|
|
|
|
|
* stack is processed, as uplevel was called after the localization. |
1891
|
|
|
|
|
|
|
* Andrew's changes to how $@ was handled, which were mainly integrated |
1892
|
|
|
|
|
|
|
* between perl 5.13.0 and 5.13.1, fixed this. */ |
1893
|
|
|
|
|
|
|
if (ERRSV && SvTRUE(ERRSV)) { |
1894
|
|
|
|
|
|
|
register const PERL_CONTEXT *cx = cxstack + i; /* This is the eval scope */ |
1895
|
|
|
|
|
|
|
SV *errsv = SvREFCNT_inc(ERRSV); |
1896
|
|
|
|
|
|
|
PL_scopestack_ix = cx->blk_oldscopesp; |
1897
|
|
|
|
|
|
|
leave_scope(PL_scopestack[PL_scopestack_ix]); |
1898
|
|
|
|
|
|
|
sv_setsv(ERRSV, errsv); |
1899
|
|
|
|
|
|
|
SvREFCNT_dec(errsv); |
1900
|
|
|
|
|
|
|
} |
1901
|
|
|
|
|
|
|
#endif |
1902
|
|
|
|
|
|
|
} |
1903
|
|
|
|
|
|
|
} |
1904
|
|
|
|
|
|
|
|
1905
|
|
|
|
|
|
|
SU_UPLEVEL_RESTORE(curcop); |
1906
|
|
|
|
|
|
|
|
1907
|
|
|
|
|
|
|
SvREFCNT_dec(sud->target); |
1908
|
|
|
|
|
|
|
|
1909
|
|
|
|
|
|
|
PL_stack_base = AvARRAY(cur->si_stack); |
1910
|
|
|
|
|
|
|
PL_stack_sp = PL_stack_base + AvFILLp(cur->si_stack); |
1911
|
|
|
|
|
|
|
PL_stack_max = PL_stack_base + AvMAX(cur->si_stack); |
1912
|
|
|
|
|
|
|
|
1913
|
|
|
|
|
|
|
/* When an exception is thrown from the uplevel'd subroutine, |
1914
|
|
|
|
|
|
|
* su_uplevel_restore() may be called by the LEAVE in die_unwind() (renamed |
1915
|
|
|
|
|
|
|
* die_where() in more recent perls), which has the sad habit of keeping a |
1916
|
|
|
|
|
|
|
* pointer to the current context frame across this call. This means that we |
1917
|
|
|
|
|
|
|
* can't free the temporary context stack we used for the uplevel call right |
1918
|
|
|
|
|
|
|
* now, or that pointer upwards would point to garbage. */ |
1919
|
|
|
|
|
|
|
#if XSH_HAS_PERL(5, 13, 7) |
1920
|
|
|
|
|
|
|
/* This issue has been fixed in perl with commit 8f89e5a9, which was made |
1921
|
|
|
|
|
|
|
* public in perl 5.13.7. */ |
1922
|
|
|
|
|
|
|
su_uplevel_storage_delete(sud); |
1923
|
|
|
|
|
|
|
#else |
1924
|
|
|
|
|
|
|
/* Otherwise, we just enqueue it back in the global storage list. */ |
1925
|
|
|
|
|
|
|
{ |
1926
|
|
|
|
|
|
|
dXSH_CXT; |
1927
|
|
|
|
|
|
|
|
1928
|
|
|
|
|
|
|
sud->tmp_uid_storage = XSH_CXT.uid_storage; |
1929
|
|
|
|
|
|
|
XSH_CXT.uid_storage = sud->old_uid_storage; |
1930
|
|
|
|
|
|
|
|
1931
|
|
|
|
|
|
|
XSH_CXT.uplevel_storage.top = sud->next; |
1932
|
|
|
|
|
|
|
sud->next = XSH_CXT.uplevel_storage.root; |
1933
|
|
|
|
|
|
|
XSH_CXT.uplevel_storage.root = sud; |
1934
|
|
|
|
|
|
|
XSH_CXT.uplevel_storage.count++; |
1935
|
|
|
|
|
|
|
} |
1936
|
|
|
|
|
|
|
#endif |
1937
|
|
|
|
|
|
|
|
1938
|
|
|
|
|
|
|
return; |
1939
|
|
|
|
|
|
|
} |
1940
|
|
|
|
|
|
|
|
1941
|
|
|
|
|
|
|
#endif |
1942
|
|
|
|
|
|
|
|
1943
|
2749
|
|
|
|
|
|
static CV *su_cv_clone(pTHX_ CV *proto, GV *gv) { |
1944
|
|
|
|
|
|
|
#define su_cv_clone(P, G) su_cv_clone(aTHX_ (P), (G)) |
1945
|
|
|
|
|
|
|
dVAR; |
1946
|
|
|
|
|
|
|
CV *cv; |
1947
|
|
|
|
|
|
|
|
1948
|
2749
|
|
|
|
|
|
cv = MUTABLE_CV(newSV_type(SvTYPE(proto))); |
1949
|
|
|
|
|
|
|
|
1950
|
2749
|
|
|
|
|
|
CvFLAGS(cv) = CvFLAGS(proto); |
1951
|
|
|
|
|
|
|
#ifdef CVf_CVGV_RC |
1952
|
2749
|
|
|
|
|
|
CvFLAGS(cv) &= ~CVf_CVGV_RC; |
1953
|
|
|
|
|
|
|
#endif |
1954
|
2749
|
|
|
|
|
|
CvDEPTH(cv) = CvDEPTH(proto); |
1955
|
|
|
|
|
|
|
#ifdef USE_ITHREADS |
1956
|
|
|
|
|
|
|
CvFILE(cv) = CvISXSUB(proto) ? CvFILE(proto) : savepv(CvFILE(proto)); |
1957
|
|
|
|
|
|
|
#else |
1958
|
2749
|
|
|
|
|
|
CvFILE(cv) = CvFILE(proto); |
1959
|
|
|
|
|
|
|
#endif |
1960
|
|
|
|
|
|
|
|
1961
|
2749
|
|
|
|
|
|
CvGV_set(cv, gv); |
1962
|
|
|
|
|
|
|
#if SU_RELEASE && XSH_HAS_PERL_EXACT(5, 21, 4) |
1963
|
|
|
|
|
|
|
CvNAMED_off(cv); |
1964
|
|
|
|
|
|
|
#endif |
1965
|
2749
|
|
|
|
|
|
CvSTASH_set(cv, CvSTASH(proto)); |
1966
|
|
|
|
|
|
|
/* Commit 4c74a7df, publicized with perl 5.13.3, began to add backrefs to |
1967
|
|
|
|
|
|
|
* stashes. CvSTASH_set() started to do it as well with commit c68d95645 |
1968
|
|
|
|
|
|
|
* (which was part of perl 5.13.7). */ |
1969
|
|
|
|
|
|
|
#if XSH_HAS_PERL(5, 13, 3) && !XSH_HAS_PERL(5, 13, 7) |
1970
|
|
|
|
|
|
|
if (CvSTASH(proto)) |
1971
|
|
|
|
|
|
|
Perl_sv_add_backref(aTHX_ CvSTASH(proto), MUTABLE_SV(cv)); |
1972
|
|
|
|
|
|
|
#endif |
1973
|
|
|
|
|
|
|
|
1974
|
2749
|
100
|
|
|
|
|
if (CvISXSUB(proto)) { |
1975
|
5
|
|
|
|
|
|
CvXSUB(cv) = CvXSUB(proto); |
1976
|
5
|
|
|
|
|
|
CvXSUBANY(cv) = CvXSUBANY(proto); |
1977
|
|
|
|
|
|
|
} else { |
1978
|
|
|
|
|
|
|
OP_REFCNT_LOCK; |
1979
|
2744
|
50
|
|
|
|
|
CvROOT(cv) = OpREFCNT_inc(CvROOT(proto)); |
1980
|
|
|
|
|
|
|
OP_REFCNT_UNLOCK; |
1981
|
2744
|
|
|
|
|
|
CvSTART(cv) = CvSTART(proto); |
1982
|
2744
|
|
|
|
|
|
CvPADLIST(cv) = CvPADLIST(proto); |
1983
|
|
|
|
|
|
|
} |
1984
|
2749
|
|
|
|
|
|
CvOUTSIDE(cv) = CvOUTSIDE(proto); |
1985
|
|
|
|
|
|
|
#ifdef CVf_WEAKOUTSIDE |
1986
|
2749
|
50
|
|
|
|
|
if (!(CvFLAGS(proto) & CVf_WEAKOUTSIDE)) |
1987
|
|
|
|
|
|
|
#endif |
1988
|
2749
|
100
|
|
|
|
|
SvREFCNT_inc_simple_void(CvOUTSIDE(cv)); |
1989
|
|
|
|
|
|
|
#ifdef CvOUTSIDE_SEQ |
1990
|
2749
|
|
|
|
|
|
CvOUTSIDE_SEQ(cv) = CvOUTSIDE_SEQ(proto); |
1991
|
|
|
|
|
|
|
#endif |
1992
|
|
|
|
|
|
|
|
1993
|
2749
|
100
|
|
|
|
|
if (SvPOK(proto)) |
1994
|
5
|
|
|
|
|
|
sv_setpvn(MUTABLE_SV(cv), SvPVX_const(proto), SvCUR(proto)); |
1995
|
|
|
|
|
|
|
|
1996
|
|
|
|
|
|
|
#ifdef CvCONST |
1997
|
2749
|
50
|
|
|
|
|
if (CvCONST(cv)) |
1998
|
0
|
|
|
|
|
|
CvCONST_off(cv); |
1999
|
|
|
|
|
|
|
#endif |
2000
|
|
|
|
|
|
|
|
2001
|
2749
|
|
|
|
|
|
return cv; |
2002
|
|
|
|
|
|
|
} |
2003
|
|
|
|
|
|
|
|
2004
|
|
|
|
|
|
|
#if SU_HAS_NEW_CXT |
2005
|
|
|
|
|
|
|
|
2006
|
|
|
|
|
|
|
/* this one-shot runops "loop" is designed to be called just before |
2007
|
|
|
|
|
|
|
* execution of the first op following an uplevel()'s entersub. It gets a |
2008
|
|
|
|
|
|
|
* chance to fix up the args as seen by caller(), before immediately |
2009
|
|
|
|
|
|
|
* falling through to the previous runops loop. Note that pp_entersub is |
2010
|
|
|
|
|
|
|
* called directly by call_sv() rather than being called from a runops |
2011
|
|
|
|
|
|
|
* loop. |
2012
|
|
|
|
|
|
|
*/ |
2013
|
|
|
|
|
|
|
|
2014
|
2744
|
|
|
|
|
|
static int su_uplevel_runops_hook_entersub(pTHX) { |
2015
|
2744
|
|
|
|
|
|
OP *op = PL_op; |
2016
|
|
|
|
|
|
|
dXSH_CXT; |
2017
|
2744
|
|
|
|
|
|
su_uplevel_ud *sud = XSH_CXT.uplevel_storage.top; |
2018
|
|
|
|
|
|
|
|
2019
|
|
|
|
|
|
|
/* Create a new array containing a copy of the original sub's call args, |
2020
|
|
|
|
|
|
|
* then stick it in PL_curpad[0] of the current running sub so that |
2021
|
|
|
|
|
|
|
* thay will be seen by caller(). |
2022
|
|
|
|
|
|
|
*/ |
2023
|
|
|
|
|
|
|
assert(sud); |
2024
|
2744
|
50
|
|
|
|
|
if (sud->argarray) { |
2025
|
|
|
|
|
|
|
I32 fill; |
2026
|
2744
|
|
|
|
|
|
AV *av = newAV(); |
2027
|
2744
|
|
|
|
|
|
AvREAL_off(av); |
2028
|
2744
|
|
|
|
|
|
AvREIFY_on(av); |
2029
|
|
|
|
|
|
|
|
2030
|
2744
|
|
|
|
|
|
fill = AvFILLp(sud->argarray); |
2031
|
2744
|
100
|
|
|
|
|
if (fill >= 0) { |
2032
|
2610
|
|
|
|
|
|
av_extend(av, fill); |
2033
|
2610
|
50
|
|
|
|
|
Copy(AvARRAY(sud->argarray), AvARRAY(av), fill + 1, SV *); |
2034
|
2610
|
|
|
|
|
|
AvFILLp(av) = fill; |
2035
|
|
|
|
|
|
|
} |
2036
|
|
|
|
|
|
|
|
2037
|
|
|
|
|
|
|
/* should be referenced by PL_curpad[0] and *_ */ |
2038
|
|
|
|
|
|
|
assert(SvREFCNT(PL_curpad[0]) > 1); |
2039
|
2744
|
|
|
|
|
|
SvREFCNT_dec(PL_curpad[0]); |
2040
|
|
|
|
|
|
|
|
2041
|
2744
|
|
|
|
|
|
PL_curpad[0] = (SV *) av; |
2042
|
|
|
|
|
|
|
} |
2043
|
|
|
|
|
|
|
|
2044
|
|
|
|
|
|
|
/* undo the temporary runops hook and fall through to a real runops loop. */ |
2045
|
|
|
|
|
|
|
assert(sud->old_runops != su_uplevel_runops_hook_entersub); |
2046
|
2744
|
|
|
|
|
|
PL_runops = sud->old_runops; |
2047
|
|
|
|
|
|
|
|
2048
|
2744
|
|
|
|
|
|
CALLRUNOPS(aTHX); |
2049
|
|
|
|
|
|
|
|
2050
|
1732
|
|
|
|
|
|
return 0; |
2051
|
|
|
|
|
|
|
} |
2052
|
|
|
|
|
|
|
|
2053
|
2749
|
|
|
|
|
|
static I32 su_uplevel_new(pTHX_ CV *callback, I32 cxix, I32 args) { |
2054
|
|
|
|
|
|
|
#define su_uplevel_new(CB, CX, A) su_uplevel_new(aTHX_ (CB), (CX), (A)) |
2055
|
|
|
|
|
|
|
su_uplevel_ud *sud; |
2056
|
|
|
|
|
|
|
U8 *saved_cxtypes; |
2057
|
|
|
|
|
|
|
I32 i, ret; |
2058
|
|
|
|
|
|
|
I32 gimme; |
2059
|
2749
|
|
|
|
|
|
CV *base_cv = cxstack[cxix].blk_sub.cv; |
2060
|
2749
|
|
|
|
|
|
dSP; |
2061
|
|
|
|
|
|
|
|
2062
|
|
|
|
|
|
|
assert(CxTYPE(&cxstack[cxix]) == CXt_SUB); |
2063
|
|
|
|
|
|
|
|
2064
|
2749
|
|
|
|
|
|
ENTER; |
2065
|
|
|
|
|
|
|
|
2066
|
2749
|
100
|
|
|
|
|
gimme = GIMME_V; |
2067
|
|
|
|
|
|
|
|
2068
|
|
|
|
|
|
|
/* At this point SP points to the top arg. |
2069
|
|
|
|
|
|
|
* Shuffle the args down by one, eliminating the CV slot */ |
2070
|
2749
|
50
|
|
|
|
|
Move(SP - args + 1, SP - args, args, SV *); |
2071
|
2749
|
|
|
|
|
|
SP--; |
2072
|
2749
|
50
|
|
|
|
|
PUSHMARK(SP - args); |
2073
|
2749
|
|
|
|
|
|
PUTBACK; |
2074
|
|
|
|
|
|
|
|
2075
|
2749
|
|
|
|
|
|
sud = su_uplevel_storage_new(cxix); |
2076
|
|
|
|
|
|
|
|
2077
|
2749
|
|
|
|
|
|
sud->cxix = cxix; |
2078
|
2749
|
|
|
|
|
|
sud->callback = (CV *) SvREFCNT_inc_simple(callback); |
2079
|
2749
|
|
|
|
|
|
sud->renamed = NULL; |
2080
|
2749
|
|
|
|
|
|
sud->gap = cxstack_ix - cxix + 1; |
2081
|
2749
|
|
|
|
|
|
sud->argarray = NULL; |
2082
|
|
|
|
|
|
|
|
2083
|
2749
|
|
|
|
|
|
Newx(saved_cxtypes, sud->gap, U8); |
2084
|
2749
|
|
|
|
|
|
sud->cxtypes = saved_cxtypes; |
2085
|
|
|
|
|
|
|
|
2086
|
2749
|
|
|
|
|
|
SAVEDESTRUCTOR_X(su_uplevel_restore_new, sud); |
2087
|
2749
|
|
|
|
|
|
SU_UPLEVEL_SAVE(curcop, cxstack[cxix].blk_oldcop); |
2088
|
|
|
|
|
|
|
|
2089
|
|
|
|
|
|
|
/* temporarily change the type of any contexts to NULL, so they're |
2090
|
|
|
|
|
|
|
* invisible to caller() etc. */ |
2091
|
38844
|
100
|
|
|
|
|
for (i = 0; i < sud->gap; i++) { |
2092
|
36095
|
|
|
|
|
|
PERL_CONTEXT *cx = cxstack + cxix + i; |
2093
|
36095
|
|
|
|
|
|
saved_cxtypes[i] = cx->cx_type; /* save type and flags */ |
2094
|
|
|
|
|
|
|
XSH_D(xsh_debug_log("su_uplevel: i=%d cxix=%d type %-11s => %s\n", |
2095
|
|
|
|
|
|
|
i, cx-cxstack, SU_CX_TYPENAME(CxTYPE(cx)), SU_CX_TYPENAME(CXt_NULL))); |
2096
|
36095
|
|
|
|
|
|
cx->cx_type = (CXt_NULL | CXp_SU_UPLEVEL_NULLED); |
2097
|
|
|
|
|
|
|
} |
2098
|
|
|
|
|
|
|
|
2099
|
|
|
|
|
|
|
/* create a copy of the callback with a doctored name (as seen by |
2100
|
|
|
|
|
|
|
* caller). It shares the padlist with callback */ |
2101
|
2749
|
|
|
|
|
|
sud->renamed = su_cv_clone(callback, CvGV(base_cv)); |
2102
|
2749
|
|
|
|
|
|
sud->old_runops = PL_runops; |
2103
|
|
|
|
|
|
|
|
2104
|
2749
|
100
|
|
|
|
|
if (!CvISXSUB(sud->renamed) && CxHASARGS(&cxstack[cxix])) { |
|
|
50
|
|
|
|
|
|
2105
|
2744
|
|
|
|
|
|
sud->argarray = (AV *) su_at_underscore(base_cv); |
2106
|
|
|
|
|
|
|
assert(PL_runops != su_uplevel_runops_hook_entersub); |
2107
|
|
|
|
|
|
|
/* set up a one-shot runops hook so that we can fake up the |
2108
|
|
|
|
|
|
|
* args as seen by caller() on return from pp_entersub */ |
2109
|
2744
|
|
|
|
|
|
PL_runops = su_uplevel_runops_hook_entersub; |
2110
|
|
|
|
|
|
|
} |
2111
|
|
|
|
|
|
|
|
2112
|
2749
|
|
|
|
|
|
CvDEPTH(callback)++; /* match what CvDEPTH(sud->renamed) is about to become */ |
2113
|
|
|
|
|
|
|
|
2114
|
2749
|
|
|
|
|
|
ret = call_sv((SV *) sud->renamed, gimme); |
2115
|
|
|
|
|
|
|
|
2116
|
1736
|
|
|
|
|
|
LEAVE; |
2117
|
|
|
|
|
|
|
|
2118
|
1736
|
|
|
|
|
|
return ret; |
2119
|
|
|
|
|
|
|
} |
2120
|
|
|
|
|
|
|
|
2121
|
|
|
|
|
|
|
#else |
2122
|
|
|
|
|
|
|
|
2123
|
|
|
|
|
|
|
static I32 su_uplevel_old(pTHX_ CV *callback, I32 cxix, I32 args) { |
2124
|
|
|
|
|
|
|
#define su_uplevel_old(CB, CX, A) su_uplevel_old(aTHX_ (CB), (CX), (A)) |
2125
|
|
|
|
|
|
|
su_uplevel_ud *sud; |
2126
|
|
|
|
|
|
|
const PERL_CONTEXT *cx = cxstack + cxix; |
2127
|
|
|
|
|
|
|
PERL_SI *si; |
2128
|
|
|
|
|
|
|
PERL_SI *cur = PL_curstackinfo; |
2129
|
|
|
|
|
|
|
SV **old_stack_sp; |
2130
|
|
|
|
|
|
|
CV *target; |
2131
|
|
|
|
|
|
|
CV *renamed; |
2132
|
|
|
|
|
|
|
UNOP sub_op; |
2133
|
|
|
|
|
|
|
I32 gimme; |
2134
|
|
|
|
|
|
|
I32 old_mark, new_mark; |
2135
|
|
|
|
|
|
|
I32 ret; |
2136
|
|
|
|
|
|
|
dSP; |
2137
|
|
|
|
|
|
|
|
2138
|
|
|
|
|
|
|
ENTER; |
2139
|
|
|
|
|
|
|
|
2140
|
|
|
|
|
|
|
gimme = GIMME_V; |
2141
|
|
|
|
|
|
|
/* Make PL_stack_sp point just before the CV. */ |
2142
|
|
|
|
|
|
|
PL_stack_sp -= args + 1; |
2143
|
|
|
|
|
|
|
old_mark = AvFILLp(PL_curstack) = PL_stack_sp - PL_stack_base; |
2144
|
|
|
|
|
|
|
SPAGAIN; |
2145
|
|
|
|
|
|
|
|
2146
|
|
|
|
|
|
|
sud = su_uplevel_storage_new(cxix); |
2147
|
|
|
|
|
|
|
|
2148
|
|
|
|
|
|
|
sud->cxix = cxix; |
2149
|
|
|
|
|
|
|
sud->died = 1; |
2150
|
|
|
|
|
|
|
sud->callback = NULL; |
2151
|
|
|
|
|
|
|
sud->renamed = NULL; |
2152
|
|
|
|
|
|
|
SAVEDESTRUCTOR_X(su_uplevel_restore_old, sud); |
2153
|
|
|
|
|
|
|
|
2154
|
|
|
|
|
|
|
si = sud->si; |
2155
|
|
|
|
|
|
|
|
2156
|
|
|
|
|
|
|
si->si_type = cur->si_type; |
2157
|
|
|
|
|
|
|
si->si_next = NULL; |
2158
|
|
|
|
|
|
|
si->si_prev = cur->si_prev; |
2159
|
|
|
|
|
|
|
#ifdef DEBUGGING |
2160
|
|
|
|
|
|
|
si->si_markoff = cx->blk_oldmarksp; |
2161
|
|
|
|
|
|
|
#endif |
2162
|
|
|
|
|
|
|
|
2163
|
|
|
|
|
|
|
/* Allocate enough space for all the elements of the original stack up to the |
2164
|
|
|
|
|
|
|
* target context, plus the forthcoming arguments. */ |
2165
|
|
|
|
|
|
|
new_mark = cx->blk_oldsp; |
2166
|
|
|
|
|
|
|
av_extend(si->si_stack, new_mark + 1 + args + 1); |
2167
|
|
|
|
|
|
|
Copy(AvARRAY(PL_curstack), AvARRAY(si->si_stack), new_mark + 1, SV *); |
2168
|
|
|
|
|
|
|
AvFILLp(si->si_stack) = new_mark; |
2169
|
|
|
|
|
|
|
SU_POISON(AvARRAY(si->si_stack) + new_mark + 1, args + 1, SV *); |
2170
|
|
|
|
|
|
|
|
2171
|
|
|
|
|
|
|
/* Specialized SWITCHSTACK() */ |
2172
|
|
|
|
|
|
|
PL_stack_base = AvARRAY(si->si_stack); |
2173
|
|
|
|
|
|
|
old_stack_sp = PL_stack_sp; |
2174
|
|
|
|
|
|
|
PL_stack_sp = PL_stack_base + AvFILLp(si->si_stack); |
2175
|
|
|
|
|
|
|
PL_stack_max = PL_stack_base + AvMAX(si->si_stack); |
2176
|
|
|
|
|
|
|
SPAGAIN; |
2177
|
|
|
|
|
|
|
|
2178
|
|
|
|
|
|
|
/* Copy the context stack up to the context just below the target. */ |
2179
|
|
|
|
|
|
|
si->si_cxix = (cxix < 0) ? -1 : (cxix - 1); |
2180
|
|
|
|
|
|
|
if (si->si_cxmax < cxix) { |
2181
|
|
|
|
|
|
|
/* The max size must be at least two so that GROW(max) = (max*3)/2 > max */ |
2182
|
|
|
|
|
|
|
si->si_cxmax = (cxix < 4) ? 4 : cxix; |
2183
|
|
|
|
|
|
|
Renew(si->si_cxstack, si->si_cxmax + 1, PERL_CONTEXT); |
2184
|
|
|
|
|
|
|
} |
2185
|
|
|
|
|
|
|
Copy(cur->si_cxstack, si->si_cxstack, cxix, PERL_CONTEXT); |
2186
|
|
|
|
|
|
|
SU_POISON(si->si_cxstack + cxix, si->si_cxmax + 1 - cxix, PERL_CONTEXT); |
2187
|
|
|
|
|
|
|
|
2188
|
|
|
|
|
|
|
target = cx->blk_sub.cv; |
2189
|
|
|
|
|
|
|
sud->target = (CV *) SvREFCNT_inc(target); |
2190
|
|
|
|
|
|
|
sud->target_depth = CvDEPTH(target); |
2191
|
|
|
|
|
|
|
|
2192
|
|
|
|
|
|
|
/* blk_oldcop is essentially needed for caller() and stack traces. It has no |
2193
|
|
|
|
|
|
|
* run-time implication, since PL_curcop will be overwritten as soon as we |
2194
|
|
|
|
|
|
|
* enter a sub (a sub starts by a nextstate/dbstate). Hence it's safe to just |
2195
|
|
|
|
|
|
|
* make it point to the blk_oldcop for the target frame, so that caller() |
2196
|
|
|
|
|
|
|
* reports the right file name, line number and lexical hints. */ |
2197
|
|
|
|
|
|
|
SU_UPLEVEL_SAVE(curcop, cx->blk_oldcop); |
2198
|
|
|
|
|
|
|
/* Don't reset PL_markstack_ptr, or we would overwrite the mark stack below |
2199
|
|
|
|
|
|
|
* this point. Don't reset PL_curpm either, we want the most recent matches. */ |
2200
|
|
|
|
|
|
|
|
2201
|
|
|
|
|
|
|
SU_UPLEVEL_SAVE(curstackinfo, si); |
2202
|
|
|
|
|
|
|
/* If those two are equal, we need to fool POPSTACK_TO() */ |
2203
|
|
|
|
|
|
|
if (PL_mainstack == PL_curstack) |
2204
|
|
|
|
|
|
|
SU_UPLEVEL_SAVE(mainstack, si->si_stack); |
2205
|
|
|
|
|
|
|
else |
2206
|
|
|
|
|
|
|
sud->old_mainstack = NULL; |
2207
|
|
|
|
|
|
|
PL_curstack = si->si_stack; |
2208
|
|
|
|
|
|
|
|
2209
|
|
|
|
|
|
|
renamed = su_cv_clone(callback, CvGV(target)); |
2210
|
|
|
|
|
|
|
sud->renamed = renamed; |
2211
|
|
|
|
|
|
|
|
2212
|
|
|
|
|
|
|
PUSHMARK(SP); |
2213
|
|
|
|
|
|
|
/* Both SP and old_stack_sp point just before the CV. */ |
2214
|
|
|
|
|
|
|
Copy(old_stack_sp + 2, SP + 1, args, SV *); |
2215
|
|
|
|
|
|
|
SP += args; |
2216
|
|
|
|
|
|
|
PUSHs((SV *) renamed); |
2217
|
|
|
|
|
|
|
PUTBACK; |
2218
|
|
|
|
|
|
|
|
2219
|
|
|
|
|
|
|
Zero(&sub_op, 1, UNOP); |
2220
|
|
|
|
|
|
|
sub_op.op_type = OP_ENTERSUB; |
2221
|
|
|
|
|
|
|
sub_op.op_next = NULL; |
2222
|
|
|
|
|
|
|
sub_op.op_flags = OP_GIMME_REVERSE(gimme) | OPf_STACKED; |
2223
|
|
|
|
|
|
|
if (PL_DBsub) |
2224
|
|
|
|
|
|
|
sub_op.op_flags |= OPpENTERSUB_DB; |
2225
|
|
|
|
|
|
|
|
2226
|
|
|
|
|
|
|
SU_UPLEVEL_SAVE(op, (OP *) &sub_op); |
2227
|
|
|
|
|
|
|
|
2228
|
|
|
|
|
|
|
#if SU_UPLEVEL_HIJACKS_RUNOPS |
2229
|
|
|
|
|
|
|
sud->old_runops = PL_runops; |
2230
|
|
|
|
|
|
|
#endif |
2231
|
|
|
|
|
|
|
|
2232
|
|
|
|
|
|
|
sud->old_catch = CATCH_GET; |
2233
|
|
|
|
|
|
|
CATCH_SET(TRUE); |
2234
|
|
|
|
|
|
|
|
2235
|
|
|
|
|
|
|
if ((PL_op = PL_ppaddr[OP_ENTERSUB](aTHX))) { |
2236
|
|
|
|
|
|
|
PERL_CONTEXT *sub_cx = cxstack + cxstack_ix; |
2237
|
|
|
|
|
|
|
AV *argarray = cx->blk_sub.argarray; |
2238
|
|
|
|
|
|
|
|
2239
|
|
|
|
|
|
|
/* If pp_entersub() returns a non-null OP, it means that the callback is not |
2240
|
|
|
|
|
|
|
* an XSUB. */ |
2241
|
|
|
|
|
|
|
|
2242
|
|
|
|
|
|
|
sud->callback = MUTABLE_CV(SvREFCNT_inc(callback)); |
2243
|
|
|
|
|
|
|
CvDEPTH(callback)++; |
2244
|
|
|
|
|
|
|
|
2245
|
|
|
|
|
|
|
if (CxHASARGS(cx) && argarray) { |
2246
|
|
|
|
|
|
|
/* The call to pp_entersub() has saved the current @_ (in XS terms, |
2247
|
|
|
|
|
|
|
* GvAV(PL_defgv)) in the savearray member, and has created a new argarray |
2248
|
|
|
|
|
|
|
* with what we put on the stack. But we want to fake up the same arguments |
2249
|
|
|
|
|
|
|
* as the ones in use at the context we uplevel to, so we replace the |
2250
|
|
|
|
|
|
|
* argarray with an unreal copy of the original @_. */ |
2251
|
|
|
|
|
|
|
AV *av = newAV(); |
2252
|
|
|
|
|
|
|
AvREAL_off(av); |
2253
|
|
|
|
|
|
|
AvREIFY_on(av); |
2254
|
|
|
|
|
|
|
av_extend(av, AvMAX(argarray)); |
2255
|
|
|
|
|
|
|
AvFILLp(av) = AvFILLp(argarray); |
2256
|
|
|
|
|
|
|
Copy(AvARRAY(argarray), AvARRAY(av), AvFILLp(av) + 1, SV *); |
2257
|
|
|
|
|
|
|
sub_cx->blk_sub.argarray = av; |
2258
|
|
|
|
|
|
|
} else { |
2259
|
|
|
|
|
|
|
SvREFCNT_inc_simple_void(sub_cx->blk_sub.argarray); |
2260
|
|
|
|
|
|
|
} |
2261
|
|
|
|
|
|
|
|
2262
|
|
|
|
|
|
|
if (su_uplevel_goto_static(CvROOT(renamed))) { |
2263
|
|
|
|
|
|
|
#if SU_UPLEVEL_HIJACKS_RUNOPS |
2264
|
|
|
|
|
|
|
if (PL_runops != PL_runops_std) { |
2265
|
|
|
|
|
|
|
if (PL_runops == PL_runops_dbg) { |
2266
|
|
|
|
|
|
|
if (PL_debug) |
2267
|
|
|
|
|
|
|
croak("uplevel() can't execute code that calls goto when debugging flags are set"); |
2268
|
|
|
|
|
|
|
} else if (PL_runops != su_uplevel_goto_runops) |
2269
|
|
|
|
|
|
|
croak("uplevel() can't execute code that calls goto with a custom runloop"); |
2270
|
|
|
|
|
|
|
} |
2271
|
|
|
|
|
|
|
|
2272
|
|
|
|
|
|
|
PL_runops = su_uplevel_goto_runops; |
2273
|
|
|
|
|
|
|
#else /* SU_UPLEVEL_HIJACKS_RUNOPS */ |
2274
|
|
|
|
|
|
|
croak("uplevel() can't execute code that calls goto before perl 5.8"); |
2275
|
|
|
|
|
|
|
#endif /* !SU_UPLEVEL_HIJACKS_RUNOPS */ |
2276
|
|
|
|
|
|
|
} |
2277
|
|
|
|
|
|
|
|
2278
|
|
|
|
|
|
|
CALLRUNOPS(aTHX); |
2279
|
|
|
|
|
|
|
} |
2280
|
|
|
|
|
|
|
|
2281
|
|
|
|
|
|
|
sud->died = 0; |
2282
|
|
|
|
|
|
|
|
2283
|
|
|
|
|
|
|
ret = PL_stack_sp - (PL_stack_base + new_mark); |
2284
|
|
|
|
|
|
|
if (ret > 0) { |
2285
|
|
|
|
|
|
|
AV *old_stack = sud->old_curstackinfo->si_stack; |
2286
|
|
|
|
|
|
|
|
2287
|
|
|
|
|
|
|
if (old_mark + ret > AvMAX(old_stack)) { |
2288
|
|
|
|
|
|
|
/* Specialized EXTEND(old_sp, ret) */ |
2289
|
|
|
|
|
|
|
av_extend(old_stack, old_mark + ret + 1); |
2290
|
|
|
|
|
|
|
old_stack_sp = AvARRAY(old_stack) + old_mark; |
2291
|
|
|
|
|
|
|
} |
2292
|
|
|
|
|
|
|
|
2293
|
|
|
|
|
|
|
Copy(PL_stack_sp - ret + 1, old_stack_sp + 1, ret, SV *); |
2294
|
|
|
|
|
|
|
PL_stack_sp += ret; |
2295
|
|
|
|
|
|
|
AvFILLp(old_stack) += ret; |
2296
|
|
|
|
|
|
|
} |
2297
|
|
|
|
|
|
|
|
2298
|
|
|
|
|
|
|
LEAVE; |
2299
|
|
|
|
|
|
|
|
2300
|
|
|
|
|
|
|
return ret; |
2301
|
|
|
|
|
|
|
} |
2302
|
|
|
|
|
|
|
|
2303
|
|
|
|
|
|
|
#endif |
2304
|
|
|
|
|
|
|
|
2305
|
|
|
|
|
|
|
/* --- Unique context ID --------------------------------------------------- */ |
2306
|
|
|
|
|
|
|
|
2307
|
839
|
|
|
|
|
|
static su_uid *su_uid_storage_fetch(pTHX_ UV depth) { |
2308
|
|
|
|
|
|
|
#define su_uid_storage_fetch(D) su_uid_storage_fetch(aTHX_ (D)) |
2309
|
|
|
|
|
|
|
su_uid *map; |
2310
|
|
|
|
|
|
|
STRLEN alloc; |
2311
|
|
|
|
|
|
|
dXSH_CXT; |
2312
|
|
|
|
|
|
|
|
2313
|
839
|
|
|
|
|
|
map = XSH_CXT.uid_storage.map; |
2314
|
839
|
|
|
|
|
|
alloc = XSH_CXT.uid_storage.alloc; |
2315
|
|
|
|
|
|
|
|
2316
|
839
|
100
|
|
|
|
|
if (depth >= alloc) { |
2317
|
|
|
|
|
|
|
STRLEN i; |
2318
|
|
|
|
|
|
|
|
2319
|
230
|
50
|
|
|
|
|
Renew(map, depth + 1, su_uid); |
2320
|
1087
|
100
|
|
|
|
|
for (i = alloc; i <= depth; ++i) { |
2321
|
857
|
|
|
|
|
|
map[i].seq = 0; |
2322
|
857
|
|
|
|
|
|
map[i].flags = 0; |
2323
|
|
|
|
|
|
|
} |
2324
|
|
|
|
|
|
|
|
2325
|
230
|
|
|
|
|
|
XSH_CXT.uid_storage.map = map; |
2326
|
230
|
|
|
|
|
|
XSH_CXT.uid_storage.alloc = depth + 1; |
2327
|
|
|
|
|
|
|
} |
2328
|
|
|
|
|
|
|
|
2329
|
839
|
100
|
|
|
|
|
if (depth >= XSH_CXT.uid_storage.used) |
2330
|
419
|
|
|
|
|
|
XSH_CXT.uid_storage.used = depth + 1; |
2331
|
|
|
|
|
|
|
|
2332
|
839
|
|
|
|
|
|
return map + depth; |
2333
|
|
|
|
|
|
|
} |
2334
|
|
|
|
|
|
|
|
2335
|
858
|
|
|
|
|
|
static int su_uid_storage_check(pTHX_ UV depth, UV seq) { |
2336
|
|
|
|
|
|
|
#define su_uid_storage_check(D, S) su_uid_storage_check(aTHX_ (D), (S)) |
2337
|
|
|
|
|
|
|
su_uid *uid; |
2338
|
|
|
|
|
|
|
dXSH_CXT; |
2339
|
|
|
|
|
|
|
|
2340
|
858
|
100
|
|
|
|
|
if (depth >= XSH_CXT.uid_storage.used) |
2341
|
454
|
|
|
|
|
|
return 0; |
2342
|
|
|
|
|
|
|
|
2343
|
404
|
|
|
|
|
|
uid = XSH_CXT.uid_storage.map + depth; |
2344
|
|
|
|
|
|
|
|
2345
|
404
|
100
|
|
|
|
|
return (uid->seq == seq) && (uid->flags & SU_UID_ACTIVE); |
|
|
100
|
|
|
|
|
|
2346
|
|
|
|
|
|
|
} |
2347
|
|
|
|
|
|
|
|
2348
|
839
|
|
|
|
|
|
static SV *su_uid_get(pTHX_ I32 cxix) { |
2349
|
|
|
|
|
|
|
#define su_uid_get(I) su_uid_get(aTHX_ (I)) |
2350
|
|
|
|
|
|
|
su_uid *uid; |
2351
|
|
|
|
|
|
|
SV *uid_sv; |
2352
|
|
|
|
|
|
|
UV depth; |
2353
|
|
|
|
|
|
|
|
2354
|
839
|
|
|
|
|
|
depth = su_uid_depth(cxix); |
2355
|
839
|
|
|
|
|
|
uid = su_uid_storage_fetch(depth); |
2356
|
|
|
|
|
|
|
|
2357
|
839
|
100
|
|
|
|
|
if (!(uid->flags & SU_UID_ACTIVE)) { |
2358
|
|
|
|
|
|
|
su_ud_uid *ud; |
2359
|
|
|
|
|
|
|
|
2360
|
823
|
|
|
|
|
|
uid->seq = su_uid_seq_next(depth); |
2361
|
823
|
|
|
|
|
|
uid->flags |= SU_UID_ACTIVE; |
2362
|
|
|
|
|
|
|
|
2363
|
823
|
|
|
|
|
|
Newx(ud, 1, su_ud_uid); |
2364
|
823
|
|
|
|
|
|
SU_UD_TYPE(ud) = SU_UD_TYPE_UID; |
2365
|
823
|
|
|
|
|
|
ud->idx = depth; |
2366
|
823
|
|
|
|
|
|
su_init(ud, cxix, SU_SAVE_DESTRUCTOR_SIZE); |
2367
|
|
|
|
|
|
|
} |
2368
|
|
|
|
|
|
|
|
2369
|
839
|
|
|
|
|
|
uid_sv = sv_newmortal(); |
2370
|
839
|
|
|
|
|
|
sv_setpvf(uid_sv, "%"UVuf"-%"UVuf, depth, uid->seq); |
2371
|
|
|
|
|
|
|
|
2372
|
839
|
|
|
|
|
|
return uid_sv; |
2373
|
|
|
|
|
|
|
} |
2374
|
|
|
|
|
|
|
|
2375
|
|
|
|
|
|
|
#ifdef grok_number |
2376
|
|
|
|
|
|
|
|
2377
|
|
|
|
|
|
|
#define su_grok_number(S, L, VP) grok_number((S), (L), (VP)) |
2378
|
|
|
|
|
|
|
|
2379
|
|
|
|
|
|
|
#else /* grok_number */ |
2380
|
|
|
|
|
|
|
|
2381
|
|
|
|
|
|
|
#define IS_NUMBER_IN_UV 0x1 |
2382
|
|
|
|
|
|
|
|
2383
|
|
|
|
|
|
|
static int su_grok_number(pTHX_ const char *s, STRLEN len, UV *valuep) { |
2384
|
|
|
|
|
|
|
#define su_grok_number(S, L, VP) su_grok_number(aTHX_ (S), (L), (VP)) |
2385
|
|
|
|
|
|
|
STRLEN i; |
2386
|
|
|
|
|
|
|
SV *tmpsv; |
2387
|
|
|
|
|
|
|
|
2388
|
|
|
|
|
|
|
/* This crude check should be good enough for a fallback implementation. |
2389
|
|
|
|
|
|
|
* Better be too strict than too lax. */ |
2390
|
|
|
|
|
|
|
for (i = 0; i < len; ++i) { |
2391
|
|
|
|
|
|
|
if (!isDIGIT(s[i])) |
2392
|
|
|
|
|
|
|
return 0; |
2393
|
|
|
|
|
|
|
} |
2394
|
|
|
|
|
|
|
|
2395
|
|
|
|
|
|
|
tmpsv = sv_newmortal(); |
2396
|
|
|
|
|
|
|
sv_setpvn(tmpsv, s, len); |
2397
|
|
|
|
|
|
|
*valuep = sv_2uv(tmpsv); |
2398
|
|
|
|
|
|
|
|
2399
|
|
|
|
|
|
|
return IS_NUMBER_IN_UV; |
2400
|
|
|
|
|
|
|
} |
2401
|
|
|
|
|
|
|
|
2402
|
|
|
|
|
|
|
#endif /* !grok_number */ |
2403
|
|
|
|
|
|
|
|
2404
|
863
|
|
|
|
|
|
static int su_uid_validate(pTHX_ SV *uid) { |
2405
|
|
|
|
|
|
|
#define su_uid_validate(U) su_uid_validate(aTHX_ (U)) |
2406
|
|
|
|
|
|
|
const char *s; |
2407
|
863
|
|
|
|
|
|
STRLEN len, p = 0; |
2408
|
|
|
|
|
|
|
UV depth, seq; |
2409
|
|
|
|
|
|
|
int type; |
2410
|
|
|
|
|
|
|
|
2411
|
863
|
50
|
|
|
|
|
s = SvPV_const(uid, len); |
2412
|
|
|
|
|
|
|
|
2413
|
2342
|
100
|
|
|
|
|
while (p < len && s[p] != '-') |
|
|
100
|
|
|
|
|
|
2414
|
1479
|
|
|
|
|
|
++p; |
2415
|
863
|
100
|
|
|
|
|
if (p >= len) |
2416
|
1
|
|
|
|
|
|
croak("UID contains only one part"); |
2417
|
|
|
|
|
|
|
|
2418
|
862
|
|
|
|
|
|
type = su_grok_number(s, p, &depth); |
2419
|
862
|
100
|
|
|
|
|
if (type != IS_NUMBER_IN_UV) |
2420
|
2
|
|
|
|
|
|
croak("First UID part is not an unsigned integer"); |
2421
|
|
|
|
|
|
|
|
2422
|
860
|
|
|
|
|
|
++p; /* Skip '-'. As we used to have p < len, len - (p + 1) >= 0. */ |
2423
|
|
|
|
|
|
|
|
2424
|
860
|
|
|
|
|
|
type = su_grok_number(s + p, len - p, &seq); |
2425
|
860
|
100
|
|
|
|
|
if (type != IS_NUMBER_IN_UV) |
2426
|
2
|
|
|
|
|
|
croak("Second UID part is not an unsigned integer"); |
2427
|
|
|
|
|
|
|
|
2428
|
858
|
|
|
|
|
|
return su_uid_storage_check(depth, seq); |
2429
|
|
|
|
|
|
|
} |
2430
|
|
|
|
|
|
|
|
2431
|
|
|
|
|
|
|
/* --- Context operations -------------------------------------------------- */ |
2432
|
|
|
|
|
|
|
|
2433
|
|
|
|
|
|
|
/* Remove sequences of BLOCKs having DB for stash, followed by a SUB context |
2434
|
|
|
|
|
|
|
* for the debugger callback. */ |
2435
|
|
|
|
|
|
|
|
2436
|
284099
|
|
|
|
|
|
static I32 su_context_skip_db(pTHX_ I32 cxix) { |
2437
|
|
|
|
|
|
|
#define su_context_skip_db(C) su_context_skip_db(aTHX_ (C)) |
2438
|
|
|
|
|
|
|
I32 i; |
2439
|
|
|
|
|
|
|
|
2440
|
284099
|
50
|
|
|
|
|
if (!PL_DBsub) |
2441
|
0
|
|
|
|
|
|
return cxix; |
2442
|
|
|
|
|
|
|
|
2443
|
284099
|
100
|
|
|
|
|
for (i = cxix; i > 0; --i) { |
2444
|
284064
|
|
|
|
|
|
PERL_CONTEXT *cx = cxstack + i; |
2445
|
|
|
|
|
|
|
|
2446
|
284064
|
|
|
|
|
|
switch (CxTYPE(cx)) { |
2447
|
|
|
|
|
|
|
#if XSH_HAS_PERL(5, 17, 1) |
2448
|
|
|
|
|
|
|
case CXt_LOOP_PLAIN: |
2449
|
|
|
|
|
|
|
#endif |
2450
|
|
|
|
|
|
|
case CXt_BLOCK: |
2451
|
93708
|
50
|
|
|
|
|
if (cx->blk_oldcop && CopSTASH(cx->blk_oldcop) == GvSTASH(PL_DBgv)) |
|
|
50
|
|
|
|
|
|
2452
|
0
|
|
|
|
|
|
continue; |
2453
|
93708
|
|
|
|
|
|
break; |
2454
|
|
|
|
|
|
|
case CXt_SUB: |
2455
|
122559
|
50
|
|
|
|
|
if (cx->blk_sub.cv == GvCV(PL_DBsub)) { |
2456
|
0
|
|
|
|
|
|
cxix = i - 1; |
2457
|
0
|
|
|
|
|
|
continue; |
2458
|
|
|
|
|
|
|
} |
2459
|
122559
|
|
|
|
|
|
break; |
2460
|
|
|
|
|
|
|
default: |
2461
|
67797
|
|
|
|
|
|
break; |
2462
|
|
|
|
|
|
|
} |
2463
|
|
|
|
|
|
|
|
2464
|
284064
|
|
|
|
|
|
break; |
2465
|
|
|
|
|
|
|
} |
2466
|
|
|
|
|
|
|
|
2467
|
284099
|
|
|
|
|
|
return cxix; |
2468
|
|
|
|
|
|
|
} |
2469
|
|
|
|
|
|
|
|
2470
|
|
|
|
|
|
|
#if SU_HAS_NEW_CXT |
2471
|
|
|
|
|
|
|
|
2472
|
|
|
|
|
|
|
/* convert a physical context stack index into the logical equivalent: |
2473
|
|
|
|
|
|
|
* one that ignores all the context frames hidden by uplevel(). |
2474
|
|
|
|
|
|
|
* Perl-level functions use logical args (e.g. UP takes an optional logical |
2475
|
|
|
|
|
|
|
* value and returns a logical value), while we use and store *real* |
2476
|
|
|
|
|
|
|
* values internally. |
2477
|
|
|
|
|
|
|
*/ |
2478
|
|
|
|
|
|
|
|
2479
|
250989
|
|
|
|
|
|
static I32 su_context_real2logical(pTHX_ I32 cxix) { |
2480
|
|
|
|
|
|
|
# define su_context_real2logical(C) su_context_real2logical(aTHX_ (C)) |
2481
|
|
|
|
|
|
|
PERL_CONTEXT *cx; |
2482
|
250989
|
|
|
|
|
|
I32 i, gaps = 0; |
2483
|
|
|
|
|
|
|
|
2484
|
3388324
|
100
|
|
|
|
|
for (i = 0; i <= cxix; i++) { |
2485
|
3137335
|
|
|
|
|
|
cx = cxstack + i; |
2486
|
3137335
|
100
|
|
|
|
|
if (cx->cx_type == (CXt_NULL | CXp_SU_UPLEVEL_NULLED)) |
2487
|
22154
|
|
|
|
|
|
gaps++; |
2488
|
|
|
|
|
|
|
} |
2489
|
|
|
|
|
|
|
|
2490
|
|
|
|
|
|
|
XSH_D(xsh_debug_log("su_context_real2logical: %d => %d\n", cxix, cxix - gaps)); |
2491
|
|
|
|
|
|
|
|
2492
|
250989
|
|
|
|
|
|
return cxix - gaps; |
2493
|
|
|
|
|
|
|
} |
2494
|
|
|
|
|
|
|
|
2495
|
|
|
|
|
|
|
/* convert a logical context stack index (one that ignores all the context |
2496
|
|
|
|
|
|
|
* frames hidden by uplevel) into the physical equivalent |
2497
|
|
|
|
|
|
|
*/ |
2498
|
|
|
|
|
|
|
|
2499
|
80741
|
|
|
|
|
|
static I32 su_context_logical2real(pTHX_ I32 cxix) { |
2500
|
|
|
|
|
|
|
# define su_context_logical2real(C) su_context_logical2real(aTHX_ (C)) |
2501
|
|
|
|
|
|
|
PERL_CONTEXT *cx; |
2502
|
80741
|
|
|
|
|
|
I32 i, seen = -1; |
2503
|
|
|
|
|
|
|
|
2504
|
1162244
|
100
|
|
|
|
|
for (i = 0; i <= cxstack_ix; i++) { |
2505
|
1162242
|
|
|
|
|
|
PERL_CONTEXT *cx = cxstack + i; |
2506
|
1162242
|
100
|
|
|
|
|
if (cx->cx_type != (CXt_NULL | CXp_SU_UPLEVEL_NULLED)) |
2507
|
1161533
|
|
|
|
|
|
seen++; |
2508
|
1162242
|
100
|
|
|
|
|
if (seen >= cxix) |
2509
|
80739
|
|
|
|
|
|
break; |
2510
|
|
|
|
|
|
|
} |
2511
|
|
|
|
|
|
|
|
2512
|
|
|
|
|
|
|
XSH_D(xsh_debug_log("su_context_logical2real: %d => %d\n", cxix, i)); |
2513
|
|
|
|
|
|
|
|
2514
|
80741
|
100
|
|
|
|
|
if (i > cxstack_ix) |
2515
|
2
|
|
|
|
|
|
i = cxstack_ix; |
2516
|
|
|
|
|
|
|
|
2517
|
80741
|
|
|
|
|
|
return i; |
2518
|
|
|
|
|
|
|
} |
2519
|
|
|
|
|
|
|
|
2520
|
|
|
|
|
|
|
#else |
2521
|
|
|
|
|
|
|
# define su_context_real2logical(C) (C) |
2522
|
|
|
|
|
|
|
# define su_context_logical2real(C) (C) |
2523
|
|
|
|
|
|
|
#endif |
2524
|
|
|
|
|
|
|
|
2525
|
284095
|
|
|
|
|
|
static I32 su_context_normalize_up(pTHX_ I32 cxix) { |
2526
|
|
|
|
|
|
|
#define su_context_normalize_up(C) su_context_normalize_up(aTHX_ (C)) |
2527
|
|
|
|
|
|
|
PERL_CONTEXT *cx; |
2528
|
|
|
|
|
|
|
|
2529
|
284095
|
100
|
|
|
|
|
if (cxix <= 0) |
2530
|
31
|
|
|
|
|
|
return 0; |
2531
|
|
|
|
|
|
|
|
2532
|
284064
|
|
|
|
|
|
cx = cxstack + cxix; |
2533
|
284064
|
100
|
|
|
|
|
if (CxTYPE(cx) == CXt_BLOCK) { |
2534
|
85360
|
|
|
|
|
|
PERL_CONTEXT *prev = cx - 1; |
2535
|
|
|
|
|
|
|
|
2536
|
85360
|
|
|
|
|
|
switch (CxTYPE(prev)) { |
2537
|
|
|
|
|
|
|
#if XSH_HAS_PERL(5, 10, 0) |
2538
|
|
|
|
|
|
|
case CXt_GIVEN: |
2539
|
|
|
|
|
|
|
case CXt_WHEN: |
2540
|
|
|
|
|
|
|
#endif |
2541
|
|
|
|
|
|
|
#if XSH_HAS_PERL(5, 11, 0) |
2542
|
|
|
|
|
|
|
/* That's the only subcategory that can cause an extra BLOCK context */ |
2543
|
|
|
|
|
|
|
case CXt_LOOP_PLAIN: |
2544
|
|
|
|
|
|
|
#else |
2545
|
|
|
|
|
|
|
case CXt_LOOP: |
2546
|
|
|
|
|
|
|
#endif |
2547
|
3754
|
100
|
|
|
|
|
if (cx->blk_oldcop == prev->blk_oldcop) |
2548
|
3285
|
|
|
|
|
|
return cxix - 1; |
2549
|
469
|
|
|
|
|
|
break; |
2550
|
|
|
|
|
|
|
case CXt_SUBST: |
2551
|
6
|
50
|
|
|
|
|
if (cx->blk_oldcop && OpSIBLING(cx->blk_oldcop) |
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
2552
|
6
|
50
|
|
|
|
|
&& OpSIBLING(cx->blk_oldcop)->op_type == OP_SUBST) |
|
|
50
|
|
|
|
|
|
2553
|
6
|
|
|
|
|
|
return cxix - 1; |
2554
|
0
|
|
|
|
|
|
break; |
2555
|
|
|
|
|
|
|
} |
2556
|
|
|
|
|
|
|
} |
2557
|
|
|
|
|
|
|
|
2558
|
280773
|
|
|
|
|
|
return cxix; |
2559
|
|
|
|
|
|
|
} |
2560
|
|
|
|
|
|
|
|
2561
|
16779
|
|
|
|
|
|
static I32 su_context_normalize_down(pTHX_ I32 cxix) { |
2562
|
|
|
|
|
|
|
#define su_context_normalize_down(C) su_context_normalize_down(aTHX_ (C)) |
2563
|
|
|
|
|
|
|
PERL_CONTEXT *next; |
2564
|
|
|
|
|
|
|
|
2565
|
16779
|
100
|
|
|
|
|
if (cxix >= cxstack_ix) |
2566
|
821
|
|
|
|
|
|
return cxstack_ix; |
2567
|
|
|
|
|
|
|
|
2568
|
15958
|
|
|
|
|
|
next = cxstack + cxix + 1; |
2569
|
15958
|
100
|
|
|
|
|
if (CxTYPE(next) == CXt_BLOCK) { |
2570
|
3126
|
|
|
|
|
|
PERL_CONTEXT *cx = next - 1; |
2571
|
|
|
|
|
|
|
|
2572
|
3126
|
|
|
|
|
|
switch (CxTYPE(cx)) { |
2573
|
|
|
|
|
|
|
#if XSH_HAS_PERL(5, 10, 0) |
2574
|
|
|
|
|
|
|
case CXt_GIVEN: |
2575
|
|
|
|
|
|
|
case CXt_WHEN: |
2576
|
|
|
|
|
|
|
#endif |
2577
|
|
|
|
|
|
|
#if XSH_HAS_PERL(5, 11, 0) |
2578
|
|
|
|
|
|
|
/* That's the only subcategory that can cause an extra BLOCK context */ |
2579
|
|
|
|
|
|
|
case CXt_LOOP_PLAIN: |
2580
|
|
|
|
|
|
|
#else |
2581
|
|
|
|
|
|
|
case CXt_LOOP: |
2582
|
|
|
|
|
|
|
#endif |
2583
|
1910
|
100
|
|
|
|
|
if (cx->blk_oldcop == next->blk_oldcop) |
2584
|
1686
|
|
|
|
|
|
return cxix + 1; |
2585
|
224
|
|
|
|
|
|
break; |
2586
|
|
|
|
|
|
|
case CXt_SUBST: |
2587
|
0
|
0
|
|
|
|
|
if (next->blk_oldcop && OpSIBLING(next->blk_oldcop) |
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
2588
|
0
|
0
|
|
|
|
|
&& OpSIBLING(next->blk_oldcop)->op_type == OP_SUBST) |
|
|
0
|
|
|
|
|
|
2589
|
0
|
|
|
|
|
|
return cxix + 1; |
2590
|
0
|
|
|
|
|
|
break; |
2591
|
|
|
|
|
|
|
} |
2592
|
|
|
|
|
|
|
} |
2593
|
|
|
|
|
|
|
|
2594
|
14272
|
|
|
|
|
|
return cxix; |
2595
|
|
|
|
|
|
|
} |
2596
|
|
|
|
|
|
|
|
2597
|
|
|
|
|
|
|
#define su_context_here() su_context_normalize_up(su_context_skip_db(cxstack_ix)) |
2598
|
|
|
|
|
|
|
|
2599
|
24
|
|
|
|
|
|
static I32 su_context_gimme(pTHX_ I32 cxix) { |
2600
|
|
|
|
|
|
|
#define su_context_gimme(C) su_context_gimme(aTHX_ (C)) |
2601
|
|
|
|
|
|
|
I32 i; |
2602
|
|
|
|
|
|
|
|
2603
|
29
|
50
|
|
|
|
|
for (i = cxix; i >= 0; --i) { |
2604
|
29
|
|
|
|
|
|
PERL_CONTEXT *cx = cxstack + i; |
2605
|
|
|
|
|
|
|
|
2606
|
29
|
100
|
|
|
|
|
switch (CxTYPE(cx)) { |
2607
|
|
|
|
|
|
|
/* gimme is always G_ARRAY for loop contexts. */ |
2608
|
|
|
|
|
|
|
#if XSH_HAS_PERL(5, 11, 0) |
2609
|
|
|
|
|
|
|
# if XSH_HAS_PERL(5, 23, 8) |
2610
|
|
|
|
|
|
|
case CXt_LOOP_ARY: |
2611
|
|
|
|
|
|
|
case CXt_LOOP_LIST: |
2612
|
|
|
|
|
|
|
# else |
2613
|
|
|
|
|
|
|
case CXt_LOOP_FOR: |
2614
|
|
|
|
|
|
|
# endif |
2615
|
|
|
|
|
|
|
case CXt_LOOP_PLAIN: |
2616
|
|
|
|
|
|
|
case CXt_LOOP_LAZYSV: |
2617
|
|
|
|
|
|
|
case CXt_LOOP_LAZYIV: |
2618
|
|
|
|
|
|
|
#else |
2619
|
|
|
|
|
|
|
case CXt_LOOP: |
2620
|
|
|
|
|
|
|
#endif |
2621
|
|
|
|
|
|
|
case CXt_SUBST: { |
2622
|
6
|
|
|
|
|
|
const COP *cop = cx->blk_oldcop; |
2623
|
6
|
50
|
|
|
|
|
if (cop && OpSIBLING(cop)) { |
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
2624
|
6
|
50
|
|
|
|
|
switch (OpSIBLING(cop)->op_flags & OPf_WANT) { |
2625
|
|
|
|
|
|
|
case OPf_WANT_VOID: |
2626
|
1
|
|
|
|
|
|
return G_VOID; |
2627
|
|
|
|
|
|
|
case OPf_WANT_SCALAR: |
2628
|
0
|
|
|
|
|
|
return G_SCALAR; |
2629
|
|
|
|
|
|
|
case OPf_WANT_LIST: |
2630
|
0
|
|
|
|
|
|
return G_ARRAY; |
2631
|
|
|
|
|
|
|
default: |
2632
|
5
|
|
|
|
|
|
break; |
2633
|
|
|
|
|
|
|
} |
2634
|
|
|
|
|
|
|
} |
2635
|
5
|
|
|
|
|
|
break; |
2636
|
|
|
|
|
|
|
} |
2637
|
|
|
|
|
|
|
default: |
2638
|
23
|
|
|
|
|
|
return CxGIMME(cx); |
2639
|
|
|
|
|
|
|
break; |
2640
|
|
|
|
|
|
|
} |
2641
|
|
|
|
|
|
|
} |
2642
|
|
|
|
|
|
|
|
2643
|
0
|
|
|
|
|
|
return G_VOID; |
2644
|
|
|
|
|
|
|
} |
2645
|
|
|
|
|
|
|
|
2646
|
|
|
|
|
|
|
/* --- Module setup/teardown ----------------------------------------------- */ |
2647
|
|
|
|
|
|
|
|
2648
|
49
|
|
|
|
|
|
static void xsh_user_global_setup(pTHX) { |
2649
|
|
|
|
|
|
|
HV *stash; |
2650
|
|
|
|
|
|
|
|
2651
|
|
|
|
|
|
|
MUTEX_INIT(&su_uid_seq_counter_mutex); |
2652
|
|
|
|
|
|
|
|
2653
|
|
|
|
|
|
|
XSH_LOCK(&su_uid_seq_counter_mutex); |
2654
|
49
|
|
|
|
|
|
su_uid_seq_counter.seqs = NULL; |
2655
|
49
|
|
|
|
|
|
su_uid_seq_counter.size = 0; |
2656
|
|
|
|
|
|
|
XSH_UNLOCK(&su_uid_seq_counter_mutex); |
2657
|
|
|
|
|
|
|
|
2658
|
49
|
|
|
|
|
|
stash = gv_stashpv(XSH_PACKAGE, 1); |
2659
|
49
|
|
|
|
|
|
newCONSTSUB(stash, "TOP", newSViv(0)); |
2660
|
49
|
|
|
|
|
|
newCONSTSUB(stash, "SU_THREADSAFE", newSVuv(XSH_THREADSAFE)); |
2661
|
|
|
|
|
|
|
|
2662
|
49
|
|
|
|
|
|
return; |
2663
|
|
|
|
|
|
|
} |
2664
|
|
|
|
|
|
|
|
2665
|
49
|
|
|
|
|
|
static void xsh_user_local_setup(pTHX_ xsh_user_cxt_t *cxt) { |
2666
|
|
|
|
|
|
|
|
2667
|
|
|
|
|
|
|
/* NewOp() calls calloc() which just zeroes the memory with memset(). */ |
2668
|
49
|
|
|
|
|
|
Zero(&(cxt->unwind_storage.return_op), 1, LISTOP); |
2669
|
49
|
|
|
|
|
|
cxt->unwind_storage.return_op.op_type = OP_RETURN; |
2670
|
49
|
|
|
|
|
|
cxt->unwind_storage.return_op.op_ppaddr = PL_ppaddr[OP_RETURN]; |
2671
|
|
|
|
|
|
|
|
2672
|
49
|
|
|
|
|
|
Zero(&(cxt->unwind_storage.proxy_op), 1, OP); |
2673
|
49
|
|
|
|
|
|
cxt->unwind_storage.proxy_op.op_type = OP_STUB; |
2674
|
49
|
|
|
|
|
|
cxt->unwind_storage.proxy_op.op_ppaddr = NULL; |
2675
|
|
|
|
|
|
|
|
2676
|
49
|
|
|
|
|
|
Zero(&(cxt->yield_storage.leave_op), 1, UNOP); |
2677
|
49
|
|
|
|
|
|
cxt->yield_storage.leave_op.op_type = OP_STUB; |
2678
|
49
|
|
|
|
|
|
cxt->yield_storage.leave_op.op_ppaddr = NULL; |
2679
|
|
|
|
|
|
|
|
2680
|
49
|
|
|
|
|
|
Zero(&(cxt->yield_storage.proxy_op), 1, OP); |
2681
|
49
|
|
|
|
|
|
cxt->yield_storage.proxy_op.op_type = OP_STUB; |
2682
|
49
|
|
|
|
|
|
cxt->yield_storage.proxy_op.op_ppaddr = NULL; |
2683
|
|
|
|
|
|
|
|
2684
|
49
|
|
|
|
|
|
cxt->uplevel_storage.top = NULL; |
2685
|
49
|
|
|
|
|
|
cxt->uplevel_storage.root = NULL; |
2686
|
49
|
|
|
|
|
|
cxt->uplevel_storage.count = 0; |
2687
|
|
|
|
|
|
|
|
2688
|
49
|
|
|
|
|
|
cxt->uid_storage.map = NULL; |
2689
|
49
|
|
|
|
|
|
cxt->uid_storage.used = 0; |
2690
|
49
|
|
|
|
|
|
cxt->uid_storage.alloc = 0; |
2691
|
|
|
|
|
|
|
|
2692
|
49
|
|
|
|
|
|
return; |
2693
|
|
|
|
|
|
|
} |
2694
|
|
|
|
|
|
|
|
2695
|
49
|
|
|
|
|
|
static void xsh_user_local_teardown(pTHX_ xsh_user_cxt_t *cxt) { |
2696
|
|
|
|
|
|
|
su_uplevel_ud *cur; |
2697
|
|
|
|
|
|
|
|
2698
|
49
|
|
|
|
|
|
Safefree(cxt->uid_storage.map); |
2699
|
|
|
|
|
|
|
|
2700
|
49
|
|
|
|
|
|
cur = cxt->uplevel_storage.root; |
2701
|
49
|
100
|
|
|
|
|
if (cur) { |
2702
|
|
|
|
|
|
|
su_uplevel_ud *prev; |
2703
|
|
|
|
|
|
|
do { |
2704
|
18
|
|
|
|
|
|
prev = cur; |
2705
|
18
|
|
|
|
|
|
cur = prev->next; |
2706
|
18
|
|
|
|
|
|
su_uplevel_ud_delete(prev); |
2707
|
18
|
100
|
|
|
|
|
} while (cur); |
2708
|
|
|
|
|
|
|
} |
2709
|
|
|
|
|
|
|
|
2710
|
49
|
|
|
|
|
|
return; |
2711
|
|
|
|
|
|
|
} |
2712
|
|
|
|
|
|
|
|
2713
|
49
|
|
|
|
|
|
static void xsh_user_global_teardown(pTHX) { |
2714
|
|
|
|
|
|
|
XSH_LOCK(&su_uid_seq_counter_mutex); |
2715
|
49
|
|
|
|
|
|
PerlMemShared_free(su_uid_seq_counter.seqs); |
2716
|
49
|
|
|
|
|
|
su_uid_seq_counter.size = 0; |
2717
|
|
|
|
|
|
|
XSH_UNLOCK(&su_uid_seq_counter_mutex); |
2718
|
|
|
|
|
|
|
|
2719
|
|
|
|
|
|
|
MUTEX_DESTROY(&su_uid_seq_counter_mutex); |
2720
|
|
|
|
|
|
|
|
2721
|
49
|
|
|
|
|
|
return; |
2722
|
|
|
|
|
|
|
} |
2723
|
|
|
|
|
|
|
|
2724
|
|
|
|
|
|
|
/* --- XS ------------------------------------------------------------------ */ |
2725
|
|
|
|
|
|
|
|
2726
|
|
|
|
|
|
|
/* D is real; B is logical. Returns real. */ |
2727
|
|
|
|
|
|
|
|
2728
|
|
|
|
|
|
|
#define SU_GET_CONTEXT(A, B, D) \ |
2729
|
|
|
|
|
|
|
STMT_START { \ |
2730
|
|
|
|
|
|
|
if (items > A) { \ |
2731
|
|
|
|
|
|
|
SV *csv = ST(B); \ |
2732
|
|
|
|
|
|
|
if (!SvOK(csv)) \ |
2733
|
|
|
|
|
|
|
goto default_cx; \ |
2734
|
|
|
|
|
|
|
cxix = SvIV(csv); \ |
2735
|
|
|
|
|
|
|
if (cxix < 0) \ |
2736
|
|
|
|
|
|
|
cxix = 0; \ |
2737
|
|
|
|
|
|
|
else if (cxix > cxstack_ix) \ |
2738
|
|
|
|
|
|
|
goto default_cx; \ |
2739
|
|
|
|
|
|
|
cxix = su_context_logical2real(cxix); \ |
2740
|
|
|
|
|
|
|
} else { \ |
2741
|
|
|
|
|
|
|
default_cx: \ |
2742
|
|
|
|
|
|
|
cxix = (D); \ |
2743
|
|
|
|
|
|
|
} \ |
2744
|
|
|
|
|
|
|
} STMT_END |
2745
|
|
|
|
|
|
|
|
2746
|
|
|
|
|
|
|
#define SU_GET_LEVEL(A, B) \ |
2747
|
|
|
|
|
|
|
STMT_START { \ |
2748
|
|
|
|
|
|
|
level = 0; \ |
2749
|
|
|
|
|
|
|
if (items > 0) { \ |
2750
|
|
|
|
|
|
|
SV *lsv = ST(B); \ |
2751
|
|
|
|
|
|
|
if (SvOK(lsv)) { \ |
2752
|
|
|
|
|
|
|
level = SvIV(lsv); \ |
2753
|
|
|
|
|
|
|
if (level < 0) \ |
2754
|
|
|
|
|
|
|
level = 0; \ |
2755
|
|
|
|
|
|
|
} \ |
2756
|
|
|
|
|
|
|
} \ |
2757
|
|
|
|
|
|
|
} STMT_END |
2758
|
|
|
|
|
|
|
|
2759
|
|
|
|
|
|
|
#if XSH_HAS_PERL(5, 10, 0) |
2760
|
|
|
|
|
|
|
# define SU_INFO_COUNT 11 |
2761
|
|
|
|
|
|
|
#else |
2762
|
|
|
|
|
|
|
# define SU_INFO_COUNT 10 |
2763
|
|
|
|
|
|
|
#endif |
2764
|
|
|
|
|
|
|
|
2765
|
5233
|
|
|
|
|
|
XS(XS_Scope__Upper_unwind) { |
2766
|
|
|
|
|
|
|
#ifdef dVAR |
2767
|
5233
|
|
|
|
|
|
dVAR; dXSARGS; |
2768
|
|
|
|
|
|
|
#else |
2769
|
|
|
|
|
|
|
dXSARGS; |
2770
|
|
|
|
|
|
|
#endif |
2771
|
|
|
|
|
|
|
dXSH_CXT; |
2772
|
|
|
|
|
|
|
I32 cxix; |
2773
|
|
|
|
|
|
|
|
2774
|
|
|
|
|
|
|
PERL_UNUSED_VAR(cv); /* -W */ |
2775
|
|
|
|
|
|
|
PERL_UNUSED_VAR(ax); /* -Wall */ |
2776
|
|
|
|
|
|
|
|
2777
|
5233
|
100
|
|
|
|
|
SU_GET_CONTEXT(0, items - 1, cxstack_ix); |
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
2778
|
|
|
|
|
|
|
do { |
2779
|
5239
|
|
|
|
|
|
PERL_CONTEXT *cx = cxstack + cxix; |
2780
|
5239
|
|
|
|
|
|
switch (CxTYPE(cx)) { |
2781
|
|
|
|
|
|
|
case CXt_SUB: |
2782
|
3283
|
50
|
|
|
|
|
if (PL_DBsub && cx->blk_sub.cv == GvCV(PL_DBsub)) |
|
|
50
|
|
|
|
|
|
2783
|
0
|
|
|
|
|
|
continue; |
2784
|
|
|
|
|
|
|
case CXt_EVAL: |
2785
|
|
|
|
|
|
|
case CXt_FORMAT: |
2786
|
5231
|
|
|
|
|
|
XSH_CXT.unwind_storage.cxix = cxix; |
2787
|
5231
|
|
|
|
|
|
XSH_CXT.unwind_storage.items = items; |
2788
|
5231
|
|
|
|
|
|
XSH_CXT.unwind_storage.savesp = PL_stack_sp; |
2789
|
5231
|
100
|
|
|
|
|
if (items > 0) { |
2790
|
5230
|
|
|
|
|
|
XSH_CXT.unwind_storage.items--; |
2791
|
5230
|
|
|
|
|
|
XSH_CXT.unwind_storage.savesp--; |
2792
|
|
|
|
|
|
|
} |
2793
|
|
|
|
|
|
|
/* pp_entersub will want to sanitize the stack after returning from there |
2794
|
|
|
|
|
|
|
* Screw that, we're insane! |
2795
|
|
|
|
|
|
|
* dXSARGS calls POPMARK, so we need to match PL_markstack_ptr[1] */ |
2796
|
5231
|
100
|
|
|
|
|
if (GIMME_V == G_SCALAR) |
|
|
100
|
|
|
|
|
|
2797
|
1740
|
|
|
|
|
|
PL_stack_sp = PL_stack_base + PL_markstack_ptr[1] + 1; |
2798
|
5231
|
|
|
|
|
|
SAVEDESTRUCTOR_X(su_unwind, NULL); |
2799
|
5231
|
|
|
|
|
|
return; |
2800
|
|
|
|
|
|
|
default: |
2801
|
8
|
|
|
|
|
|
break; |
2802
|
|
|
|
|
|
|
} |
2803
|
8
|
100
|
|
|
|
|
} while (--cxix >= 0); |
2804
|
2
|
|
|
|
|
|
croak("Can't return outside a subroutine"); |
2805
|
|
|
|
|
|
|
} |
2806
|
|
|
|
|
|
|
|
2807
|
|
|
|
|
|
|
static const char su_yield_name[] = "yield"; |
2808
|
|
|
|
|
|
|
|
2809
|
41527
|
|
|
|
|
|
XS(XS_Scope__Upper_yield) { |
2810
|
|
|
|
|
|
|
#ifdef dVAR |
2811
|
41527
|
|
|
|
|
|
dVAR; dXSARGS; |
2812
|
|
|
|
|
|
|
#else |
2813
|
|
|
|
|
|
|
dXSARGS; |
2814
|
|
|
|
|
|
|
#endif |
2815
|
|
|
|
|
|
|
dXSH_CXT; |
2816
|
|
|
|
|
|
|
I32 cxix; |
2817
|
|
|
|
|
|
|
|
2818
|
|
|
|
|
|
|
PERL_UNUSED_VAR(cv); /* -W */ |
2819
|
|
|
|
|
|
|
PERL_UNUSED_VAR(ax); /* -Wall */ |
2820
|
|
|
|
|
|
|
|
2821
|
41527
|
100
|
|
|
|
|
SU_GET_CONTEXT(0, items - 1, su_context_here()); |
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
2822
|
41527
|
|
|
|
|
|
XSH_CXT.yield_storage.cxix = cxix; |
2823
|
41527
|
|
|
|
|
|
XSH_CXT.yield_storage.items = items; |
2824
|
41527
|
|
|
|
|
|
XSH_CXT.yield_storage.savesp = PL_stack_sp; |
2825
|
41527
|
100
|
|
|
|
|
if (items > 0) { |
2826
|
41513
|
|
|
|
|
|
XSH_CXT.yield_storage.items--; |
2827
|
41513
|
|
|
|
|
|
XSH_CXT.yield_storage.savesp--; |
2828
|
|
|
|
|
|
|
} |
2829
|
|
|
|
|
|
|
/* See XS_Scope__Upper_unwind */ |
2830
|
41527
|
100
|
|
|
|
|
if (GIMME_V == G_SCALAR) |
|
|
100
|
|
|
|
|
|
2831
|
13836
|
|
|
|
|
|
PL_stack_sp = PL_stack_base + PL_markstack_ptr[1] + 1; |
2832
|
41527
|
|
|
|
|
|
SAVEDESTRUCTOR_X(su_yield, su_yield_name); |
2833
|
41527
|
|
|
|
|
|
return; |
2834
|
|
|
|
|
|
|
} |
2835
|
|
|
|
|
|
|
|
2836
|
|
|
|
|
|
|
static const char su_leave_name[] = "leave"; |
2837
|
|
|
|
|
|
|
|
2838
|
3
|
|
|
|
|
|
XS(XS_Scope__Upper_leave) { |
2839
|
|
|
|
|
|
|
#ifdef dVAR |
2840
|
3
|
|
|
|
|
|
dVAR; dXSARGS; |
2841
|
|
|
|
|
|
|
#else |
2842
|
|
|
|
|
|
|
dXSARGS; |
2843
|
|
|
|
|
|
|
#endif |
2844
|
|
|
|
|
|
|
dXSH_CXT; |
2845
|
|
|
|
|
|
|
|
2846
|
|
|
|
|
|
|
PERL_UNUSED_VAR(cv); /* -W */ |
2847
|
|
|
|
|
|
|
PERL_UNUSED_VAR(ax); /* -Wall */ |
2848
|
|
|
|
|
|
|
|
2849
|
3
|
|
|
|
|
|
XSH_CXT.yield_storage.cxix = su_context_here(); |
2850
|
3
|
|
|
|
|
|
XSH_CXT.yield_storage.items = items; |
2851
|
3
|
|
|
|
|
|
XSH_CXT.yield_storage.savesp = PL_stack_sp; |
2852
|
|
|
|
|
|
|
/* See XS_Scope__Upper_unwind */ |
2853
|
3
|
50
|
|
|
|
|
if (GIMME_V == G_SCALAR) |
|
|
50
|
|
|
|
|
|
2854
|
0
|
|
|
|
|
|
PL_stack_sp = PL_stack_base + PL_markstack_ptr[1] + 1; |
2855
|
|
|
|
|
|
|
|
2856
|
3
|
|
|
|
|
|
SAVEDESTRUCTOR_X(su_yield, su_leave_name); |
2857
|
|
|
|
|
|
|
|
2858
|
3
|
|
|
|
|
|
return; |
2859
|
|
|
|
|
|
|
} |
2860
|
|
|
|
|
|
|
|
2861
|
|
|
|
|
|
|
MODULE = Scope::Upper PACKAGE = Scope::Upper |
2862
|
|
|
|
|
|
|
|
2863
|
|
|
|
|
|
|
PROTOTYPES: ENABLE |
2864
|
|
|
|
|
|
|
|
2865
|
|
|
|
|
|
|
BOOT: |
2866
|
|
|
|
|
|
|
{ |
2867
|
49
|
|
|
|
|
|
xsh_setup(); |
2868
|
49
|
|
|
|
|
|
newXSproto("Scope::Upper::unwind", XS_Scope__Upper_unwind, file, NULL); |
2869
|
49
|
|
|
|
|
|
newXSproto("Scope::Upper::yield", XS_Scope__Upper_yield, file, NULL); |
2870
|
49
|
|
|
|
|
|
newXSproto("Scope::Upper::leave", XS_Scope__Upper_leave, file, NULL); |
2871
|
|
|
|
|
|
|
} |
2872
|
|
|
|
|
|
|
|
2873
|
|
|
|
|
|
|
#if XSH_THREADSAFE |
2874
|
|
|
|
|
|
|
|
2875
|
|
|
|
|
|
|
void |
2876
|
|
|
|
|
|
|
CLONE(...) |
2877
|
|
|
|
|
|
|
PROTOTYPE: DISABLE |
2878
|
|
|
|
|
|
|
PPCODE: |
2879
|
|
|
|
|
|
|
xsh_clone(); |
2880
|
|
|
|
|
|
|
XSRETURN(0); |
2881
|
|
|
|
|
|
|
|
2882
|
|
|
|
|
|
|
#endif /* XSH_THREADSAFE */ |
2883
|
|
|
|
|
|
|
|
2884
|
|
|
|
|
|
|
void |
2885
|
|
|
|
|
|
|
HERE() |
2886
|
|
|
|
|
|
|
PROTOTYPE: |
2887
|
|
|
|
|
|
|
PREINIT: |
2888
|
|
|
|
|
|
|
I32 cxix; |
2889
|
|
|
|
|
|
|
PPCODE: |
2890
|
165494
|
|
|
|
|
|
cxix = su_context_real2logical(su_context_here()); |
2891
|
165494
|
50
|
|
|
|
|
EXTEND(SP, 1); |
2892
|
165494
|
|
|
|
|
|
mPUSHi(cxix); |
2893
|
165494
|
|
|
|
|
|
XSRETURN(1); |
2894
|
|
|
|
|
|
|
|
2895
|
|
|
|
|
|
|
void |
2896
|
|
|
|
|
|
|
UP(...) |
2897
|
|
|
|
|
|
|
PROTOTYPE: ;$ |
2898
|
|
|
|
|
|
|
PREINIT: |
2899
|
|
|
|
|
|
|
I32 cxix; |
2900
|
|
|
|
|
|
|
PPCODE: |
2901
|
25912
|
100
|
|
|
|
|
SU_GET_CONTEXT(0, 0, su_context_here()); |
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
2902
|
25912
|
100
|
|
|
|
|
if (cxix > 0) { |
2903
|
25911
|
|
|
|
|
|
--cxix; |
2904
|
25911
|
|
|
|
|
|
cxix = su_context_skip_db(cxix); |
2905
|
25911
|
|
|
|
|
|
cxix = su_context_normalize_up(cxix); |
2906
|
25911
|
|
|
|
|
|
cxix = su_context_real2logical(cxix); |
2907
|
|
|
|
|
|
|
} else { |
2908
|
1
|
|
|
|
|
|
warn(su_stack_smash); |
2909
|
|
|
|
|
|
|
} |
2910
|
25912
|
50
|
|
|
|
|
EXTEND(SP, 1); |
2911
|
25912
|
|
|
|
|
|
mPUSHi(cxix); |
2912
|
25912
|
|
|
|
|
|
XSRETURN(1); |
2913
|
|
|
|
|
|
|
|
2914
|
|
|
|
|
|
|
void |
2915
|
|
|
|
|
|
|
SUB(...) |
2916
|
|
|
|
|
|
|
PROTOTYPE: ;$ |
2917
|
|
|
|
|
|
|
PREINIT: |
2918
|
|
|
|
|
|
|
I32 cxix; |
2919
|
|
|
|
|
|
|
PPCODE: |
2920
|
5921
|
100
|
|
|
|
|
SU_GET_CONTEXT(0, 0, cxstack_ix); |
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
2921
|
5921
|
50
|
|
|
|
|
EXTEND(SP, 1); |
2922
|
21552
|
100
|
|
|
|
|
for (; cxix >= 0; --cxix) { |
2923
|
21530
|
|
|
|
|
|
PERL_CONTEXT *cx = cxstack + cxix; |
2924
|
21530
|
100
|
|
|
|
|
switch (CxTYPE(cx)) { |
2925
|
|
|
|
|
|
|
default: |
2926
|
15631
|
|
|
|
|
|
continue; |
2927
|
|
|
|
|
|
|
case CXt_SUB: |
2928
|
5899
|
50
|
|
|
|
|
if (PL_DBsub && cx->blk_sub.cv == GvCV(PL_DBsub)) |
|
|
50
|
|
|
|
|
|
2929
|
0
|
|
|
|
|
|
continue; |
2930
|
5899
|
|
|
|
|
|
cxix = su_context_real2logical(cxix); |
2931
|
5899
|
|
|
|
|
|
mPUSHi(cxix); |
2932
|
5899
|
|
|
|
|
|
XSRETURN(1); |
2933
|
|
|
|
|
|
|
} |
2934
|
|
|
|
|
|
|
} |
2935
|
22
|
|
|
|
|
|
warn(su_no_such_target, "subroutine"); |
2936
|
22
|
|
|
|
|
|
XSRETURN_UNDEF; |
2937
|
|
|
|
|
|
|
|
2938
|
|
|
|
|
|
|
void |
2939
|
|
|
|
|
|
|
EVAL(...) |
2940
|
|
|
|
|
|
|
PROTOTYPE: ;$ |
2941
|
|
|
|
|
|
|
PREINIT: |
2942
|
|
|
|
|
|
|
I32 cxix; |
2943
|
|
|
|
|
|
|
PPCODE: |
2944
|
23
|
50
|
|
|
|
|
SU_GET_CONTEXT(0, 0, cxstack_ix); |
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
2945
|
23
|
50
|
|
|
|
|
EXTEND(SP, 1); |
2946
|
72
|
100
|
|
|
|
|
for (; cxix >= 0; --cxix) { |
2947
|
55
|
|
|
|
|
|
PERL_CONTEXT *cx = cxstack + cxix; |
2948
|
55
|
100
|
|
|
|
|
switch (CxTYPE(cx)) { |
2949
|
|
|
|
|
|
|
default: |
2950
|
49
|
|
|
|
|
|
continue; |
2951
|
|
|
|
|
|
|
case CXt_EVAL: |
2952
|
6
|
|
|
|
|
|
cxix = su_context_real2logical(cxix); |
2953
|
6
|
|
|
|
|
|
mPUSHi(cxix); |
2954
|
6
|
|
|
|
|
|
XSRETURN(1); |
2955
|
|
|
|
|
|
|
} |
2956
|
|
|
|
|
|
|
} |
2957
|
17
|
|
|
|
|
|
warn(su_no_such_target, "eval"); |
2958
|
17
|
|
|
|
|
|
XSRETURN_UNDEF; |
2959
|
|
|
|
|
|
|
|
2960
|
|
|
|
|
|
|
void |
2961
|
|
|
|
|
|
|
SCOPE(...) |
2962
|
|
|
|
|
|
|
PROTOTYPE: ;$ |
2963
|
|
|
|
|
|
|
PREINIT: |
2964
|
|
|
|
|
|
|
I32 cxix, level; |
2965
|
|
|
|
|
|
|
PPCODE: |
2966
|
23376
|
100
|
|
|
|
|
SU_GET_LEVEL(0, 0); |
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
2967
|
23376
|
|
|
|
|
|
cxix = su_context_here(); |
2968
|
75911
|
100
|
|
|
|
|
while (--level >= 0) { |
2969
|
52536
|
100
|
|
|
|
|
if (cxix <= 0) { |
2970
|
1
|
|
|
|
|
|
warn(su_stack_smash); |
2971
|
1
|
|
|
|
|
|
break; |
2972
|
|
|
|
|
|
|
} |
2973
|
52535
|
|
|
|
|
|
--cxix; |
2974
|
52535
|
|
|
|
|
|
cxix = su_context_skip_db(cxix); |
2975
|
52535
|
|
|
|
|
|
cxix = su_context_normalize_up(cxix); |
2976
|
52535
|
|
|
|
|
|
cxix = su_context_real2logical(cxix); |
2977
|
|
|
|
|
|
|
} |
2978
|
23376
|
50
|
|
|
|
|
EXTEND(SP, 1); |
2979
|
23376
|
|
|
|
|
|
mPUSHi(cxix); |
2980
|
23376
|
|
|
|
|
|
XSRETURN(1); |
2981
|
|
|
|
|
|
|
|
2982
|
|
|
|
|
|
|
void |
2983
|
|
|
|
|
|
|
CALLER(...) |
2984
|
|
|
|
|
|
|
PROTOTYPE: ;$ |
2985
|
|
|
|
|
|
|
PREINIT: |
2986
|
|
|
|
|
|
|
I32 cxix, level; |
2987
|
|
|
|
|
|
|
PPCODE: |
2988
|
1144
|
100
|
|
|
|
|
SU_GET_LEVEL(0, 0); |
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
2989
|
13273
|
100
|
|
|
|
|
for (cxix = cxstack_ix; cxix > 0; --cxix) { |
2990
|
13267
|
|
|
|
|
|
PERL_CONTEXT *cx = cxstack + cxix; |
2991
|
13267
|
|
|
|
|
|
switch (CxTYPE(cx)) { |
2992
|
|
|
|
|
|
|
case CXt_SUB: |
2993
|
6447
|
50
|
|
|
|
|
if (PL_DBsub && cx->blk_sub.cv == GvCV(PL_DBsub)) |
|
|
50
|
|
|
|
|
|
2994
|
0
|
|
|
|
|
|
continue; |
2995
|
|
|
|
|
|
|
case CXt_EVAL: |
2996
|
|
|
|
|
|
|
case CXt_FORMAT: |
2997
|
6460
|
100
|
|
|
|
|
if (--level < 0) |
2998
|
1138
|
|
|
|
|
|
goto done; |
2999
|
5322
|
|
|
|
|
|
break; |
3000
|
|
|
|
|
|
|
} |
3001
|
|
|
|
|
|
|
} |
3002
|
|
|
|
|
|
|
done: |
3003
|
1144
|
100
|
|
|
|
|
if (level >= 0) |
3004
|
6
|
|
|
|
|
|
warn(su_stack_smash); |
3005
|
1144
|
50
|
|
|
|
|
EXTEND(SP, 1); |
3006
|
1144
|
|
|
|
|
|
cxix = su_context_real2logical(cxix); |
3007
|
1144
|
|
|
|
|
|
mPUSHi(cxix); |
3008
|
1144
|
|
|
|
|
|
XSRETURN(1); |
3009
|
|
|
|
|
|
|
|
3010
|
|
|
|
|
|
|
void |
3011
|
|
|
|
|
|
|
want_at(...) |
3012
|
|
|
|
|
|
|
PROTOTYPE: ;$ |
3013
|
|
|
|
|
|
|
PREINIT: |
3014
|
|
|
|
|
|
|
I32 cxix; |
3015
|
|
|
|
|
|
|
PPCODE: |
3016
|
18
|
100
|
|
|
|
|
SU_GET_CONTEXT(0, 0, cxstack_ix); |
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
3017
|
18
|
50
|
|
|
|
|
EXTEND(SP, 1); |
3018
|
26
|
100
|
|
|
|
|
while (cxix > 0) { |
3019
|
23
|
|
|
|
|
|
PERL_CONTEXT *cx = cxstack + cxix--; |
3020
|
23
|
|
|
|
|
|
switch (CxTYPE(cx)) { |
3021
|
|
|
|
|
|
|
case CXt_SUB: |
3022
|
11
|
50
|
|
|
|
|
if (PL_DBsub && cx->blk_sub.cv == GvCV(PL_DBsub)) |
|
|
50
|
|
|
|
|
|
3023
|
0
|
|
|
|
|
|
continue; |
3024
|
|
|
|
|
|
|
case CXt_EVAL: |
3025
|
|
|
|
|
|
|
case CXt_FORMAT: { |
3026
|
15
|
|
|
|
|
|
I32 gimme = cx->blk_gimme; |
3027
|
15
|
|
|
|
|
|
switch (gimme) { |
3028
|
1
|
|
|
|
|
|
case G_VOID: XSRETURN_UNDEF; break; |
3029
|
3
|
|
|
|
|
|
case G_SCALAR: XSRETURN_NO; break; |
3030
|
11
|
|
|
|
|
|
case G_ARRAY: XSRETURN_YES; break; |
3031
|
|
|
|
|
|
|
} |
3032
|
0
|
|
|
|
|
|
break; |
3033
|
|
|
|
|
|
|
} |
3034
|
|
|
|
|
|
|
} |
3035
|
|
|
|
|
|
|
} |
3036
|
3
|
|
|
|
|
|
XSRETURN_UNDEF; |
3037
|
|
|
|
|
|
|
|
3038
|
|
|
|
|
|
|
void |
3039
|
|
|
|
|
|
|
context_info(...) |
3040
|
|
|
|
|
|
|
PROTOTYPE: ;$ |
3041
|
|
|
|
|
|
|
PREINIT: |
3042
|
|
|
|
|
|
|
I32 cxix; |
3043
|
|
|
|
|
|
|
const PERL_CONTEXT *cx, *dbcx; |
3044
|
|
|
|
|
|
|
COP *cop; |
3045
|
|
|
|
|
|
|
PPCODE: |
3046
|
24
|
100
|
|
|
|
|
SU_GET_CONTEXT(0, 0, su_context_skip_db(cxstack_ix)); |
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
3047
|
24
|
|
|
|
|
|
cxix = su_context_normalize_up(cxix); |
3048
|
24
|
|
|
|
|
|
cx = cxstack + cxix; |
3049
|
24
|
|
|
|
|
|
dbcx = cx; |
3050
|
24
|
50
|
|
|
|
|
if (PL_DBsub && cxix && (CxTYPE(cx) == CXt_SUB || CxTYPE(cx) == CXt_FORMAT)) { |
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
3051
|
9
|
|
|
|
|
|
I32 i = su_context_skip_db(cxix - 1) + 1; |
3052
|
9
|
50
|
|
|
|
|
if (i < cxix && CxTYPE(cxstack + i) == CXt_SUB) |
|
|
0
|
|
|
|
|
|
3053
|
0
|
|
|
|
|
|
cx = cxstack + i; |
3054
|
|
|
|
|
|
|
} |
3055
|
24
|
|
|
|
|
|
cop = cx->blk_oldcop; |
3056
|
24
|
50
|
|
|
|
|
EXTEND(SP, SU_INFO_COUNT); |
3057
|
|
|
|
|
|
|
/* stash (0) */ |
3058
|
|
|
|
|
|
|
{ |
3059
|
24
|
|
|
|
|
|
HV *stash = CopSTASH(cop); |
3060
|
24
|
50
|
|
|
|
|
if (stash) |
3061
|
24
|
50
|
|
|
|
|
PUSHs(su_newmortal_pvn(HvNAME(stash), HvNAMELEN(stash))); |
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
3062
|
|
|
|
|
|
|
else |
3063
|
0
|
|
|
|
|
|
PUSHs(&PL_sv_undef); |
3064
|
|
|
|
|
|
|
} |
3065
|
|
|
|
|
|
|
/* file (1) */ |
3066
|
24
|
50
|
|
|
|
|
PUSHs(su_newmortal_pvn(OutCopFILE(cop), OutCopFILE_len(cop))); |
|
|
50
|
|
|
|
|
|
3067
|
|
|
|
|
|
|
/* line (2) */ |
3068
|
24
|
|
|
|
|
|
mPUSHi(CopLINE(cop)); |
3069
|
|
|
|
|
|
|
/* subroutine (3) and has_args (4) */ |
3070
|
24
|
|
|
|
|
|
switch (CxTYPE(cx)) { |
3071
|
|
|
|
|
|
|
case CXt_SUB: |
3072
|
|
|
|
|
|
|
case CXt_FORMAT: { |
3073
|
9
|
|
|
|
|
|
GV *cvgv = CvGV(dbcx->blk_sub.cv); |
3074
|
18
|
50
|
|
|
|
|
if (cvgv && isGV(cvgv)) { |
|
|
50
|
|
|
|
|
|
3075
|
9
|
|
|
|
|
|
SV *sv = sv_newmortal(); |
3076
|
9
|
|
|
|
|
|
gv_efullname3(sv, cvgv, NULL); |
3077
|
9
|
|
|
|
|
|
PUSHs(sv); |
3078
|
|
|
|
|
|
|
} else { |
3079
|
0
|
|
|
|
|
|
PUSHs(su_newmortal_pvs("(unknown)")); |
3080
|
|
|
|
|
|
|
} |
3081
|
9
|
50
|
|
|
|
|
if (CxHASARGS(cx)) |
3082
|
9
|
|
|
|
|
|
PUSHs(&PL_sv_yes); |
3083
|
|
|
|
|
|
|
else |
3084
|
0
|
|
|
|
|
|
PUSHs(&PL_sv_no); |
3085
|
9
|
|
|
|
|
|
break; |
3086
|
|
|
|
|
|
|
} |
3087
|
|
|
|
|
|
|
case CXt_EVAL: |
3088
|
5
|
|
|
|
|
|
PUSHs(su_newmortal_pvs("(eval)")); |
3089
|
5
|
|
|
|
|
|
mPUSHi(0); |
3090
|
5
|
|
|
|
|
|
break; |
3091
|
|
|
|
|
|
|
default: |
3092
|
10
|
|
|
|
|
|
PUSHs(&PL_sv_undef); |
3093
|
10
|
|
|
|
|
|
PUSHs(&PL_sv_undef); |
3094
|
|
|
|
|
|
|
} |
3095
|
|
|
|
|
|
|
/* gimme (5) */ |
3096
|
24
|
|
|
|
|
|
switch (su_context_gimme(cxix)) { |
3097
|
|
|
|
|
|
|
case G_ARRAY: |
3098
|
11
|
|
|
|
|
|
PUSHs(&PL_sv_yes); |
3099
|
11
|
|
|
|
|
|
break; |
3100
|
|
|
|
|
|
|
case G_SCALAR: |
3101
|
3
|
|
|
|
|
|
PUSHs(&PL_sv_no); |
3102
|
3
|
|
|
|
|
|
break; |
3103
|
|
|
|
|
|
|
default: /* G_VOID */ |
3104
|
10
|
|
|
|
|
|
PUSHs(&PL_sv_undef); |
3105
|
10
|
|
|
|
|
|
break; |
3106
|
|
|
|
|
|
|
} |
3107
|
|
|
|
|
|
|
/* eval text (6) and is_require (7) */ |
3108
|
24
|
100
|
|
|
|
|
switch (CxTYPE(cx)) { |
3109
|
|
|
|
|
|
|
case CXt_EVAL: |
3110
|
5
|
100
|
|
|
|
|
if (CxOLD_OP_TYPE(cx) == OP_ENTEREVAL) { |
3111
|
|
|
|
|
|
|
/* eval STRING */ |
3112
|
|
|
|
|
|
|
#if XSH_HAS_PERL(5, 17, 4) |
3113
|
2
|
|
|
|
|
|
PUSHs(newSVpvn_flags(SvPVX(cx->blk_eval.cur_text), |
3114
|
|
|
|
|
|
|
SvCUR(cx->blk_eval.cur_text)-2, |
3115
|
|
|
|
|
|
|
SvUTF8(cx->blk_eval.cur_text)|SVs_TEMP)); |
3116
|
|
|
|
|
|
|
#else |
3117
|
|
|
|
|
|
|
PUSHs(cx->blk_eval.cur_text); |
3118
|
|
|
|
|
|
|
#endif |
3119
|
2
|
|
|
|
|
|
PUSHs(&PL_sv_no); |
3120
|
2
|
|
|
|
|
|
break; |
3121
|
3
|
50
|
|
|
|
|
} else if (cx->blk_eval.old_namesv) { |
3122
|
|
|
|
|
|
|
/* require */ |
3123
|
0
|
|
|
|
|
|
PUSHs(sv_mortalcopy(cx->blk_eval.old_namesv)); |
3124
|
0
|
|
|
|
|
|
PUSHs(&PL_sv_yes); |
3125
|
0
|
|
|
|
|
|
break; |
3126
|
|
|
|
|
|
|
} |
3127
|
|
|
|
|
|
|
/* FALLTHROUGH */ |
3128
|
|
|
|
|
|
|
default: |
3129
|
|
|
|
|
|
|
/* Anything else including eval BLOCK */ |
3130
|
22
|
|
|
|
|
|
PUSHs(&PL_sv_undef); |
3131
|
22
|
|
|
|
|
|
PUSHs(&PL_sv_undef); |
3132
|
22
|
|
|
|
|
|
break; |
3133
|
|
|
|
|
|
|
} |
3134
|
|
|
|
|
|
|
/* hints (8) */ |
3135
|
24
|
|
|
|
|
|
mPUSHi(CopHINTS_get(cop)); |
3136
|
|
|
|
|
|
|
/* warnings (9) */ |
3137
|
|
|
|
|
|
|
{ |
3138
|
24
|
|
|
|
|
|
SV *mask = NULL; |
3139
|
|
|
|
|
|
|
#if XSH_HAS_PERL(5, 9, 4) |
3140
|
24
|
|
|
|
|
|
STRLEN *old_warnings = cop->cop_warnings; |
3141
|
|
|
|
|
|
|
#else |
3142
|
|
|
|
|
|
|
SV *old_warnings = cop->cop_warnings; |
3143
|
|
|
|
|
|
|
#endif |
3144
|
24
|
100
|
|
|
|
|
if (old_warnings == pWARN_STD) { |
3145
|
3
|
50
|
|
|
|
|
if (PL_dowarn & G_WARN_ON) |
3146
|
0
|
|
|
|
|
|
goto context_info_warnings_on; |
3147
|
|
|
|
|
|
|
else |
3148
|
|
|
|
|
|
|
#if XSH_HAS_PERL(5, 17, 4) |
3149
|
3
|
|
|
|
|
|
mask = &PL_sv_undef; |
3150
|
|
|
|
|
|
|
#else |
3151
|
|
|
|
|
|
|
goto context_info_warnings_off; |
3152
|
|
|
|
|
|
|
#endif |
3153
|
21
|
50
|
|
|
|
|
} else if (old_warnings == pWARN_NONE) { |
3154
|
|
|
|
|
|
|
#if !XSH_HAS_PERL(5, 17, 4) |
3155
|
|
|
|
|
|
|
context_info_warnings_off: |
3156
|
|
|
|
|
|
|
#endif |
3157
|
0
|
|
|
|
|
|
mask = su_newmortal_pvn(WARN_NONEstring, WARNsize); |
3158
|
21
|
50
|
|
|
|
|
} else if (old_warnings == pWARN_ALL) { |
3159
|
|
|
|
|
|
|
HV *bits; |
3160
|
|
|
|
|
|
|
context_info_warnings_on: |
3161
|
|
|
|
|
|
|
#if XSH_HAS_PERL(5, 8, 7) |
3162
|
21
|
|
|
|
|
|
bits = get_hv("warnings::Bits", 0); |
3163
|
21
|
50
|
|
|
|
|
if (bits) { |
3164
|
21
|
|
|
|
|
|
SV **bits_all = hv_fetchs(bits, "all", FALSE); |
3165
|
21
|
50
|
|
|
|
|
if (bits_all) |
3166
|
21
|
|
|
|
|
|
mask = sv_mortalcopy(*bits_all); |
3167
|
|
|
|
|
|
|
} |
3168
|
|
|
|
|
|
|
#endif |
3169
|
21
|
50
|
|
|
|
|
if (!mask) |
3170
|
21
|
|
|
|
|
|
mask = su_newmortal_pvn(WARN_ALLstring, WARNsize); |
3171
|
|
|
|
|
|
|
} else { |
3172
|
|
|
|
|
|
|
#if XSH_HAS_PERL(5, 9, 4) |
3173
|
0
|
|
|
|
|
|
mask = su_newmortal_pvn((char *) (old_warnings + 1), old_warnings[0]); |
3174
|
|
|
|
|
|
|
#else |
3175
|
|
|
|
|
|
|
mask = sv_mortalcopy(old_warnings); |
3176
|
|
|
|
|
|
|
#endif |
3177
|
|
|
|
|
|
|
} |
3178
|
24
|
|
|
|
|
|
PUSHs(mask); |
3179
|
|
|
|
|
|
|
} |
3180
|
|
|
|
|
|
|
#if XSH_HAS_PERL(5, 10, 0) |
3181
|
|
|
|
|
|
|
/* hints hash (10) */ |
3182
|
|
|
|
|
|
|
{ |
3183
|
24
|
|
|
|
|
|
COPHH *hints_hash = CopHINTHASH_get(cop); |
3184
|
24
|
50
|
|
|
|
|
if (hints_hash) { |
3185
|
0
|
|
|
|
|
|
SV *rhv = sv_2mortal(newRV_noinc((SV *) cophh_2hv(hints_hash, 0))); |
3186
|
0
|
|
|
|
|
|
PUSHs(rhv); |
3187
|
|
|
|
|
|
|
} else { |
3188
|
24
|
|
|
|
|
|
PUSHs(&PL_sv_undef); |
3189
|
|
|
|
|
|
|
} |
3190
|
|
|
|
|
|
|
} |
3191
|
|
|
|
|
|
|
#endif |
3192
|
24
|
|
|
|
|
|
XSRETURN(SU_INFO_COUNT); |
3193
|
|
|
|
|
|
|
|
3194
|
|
|
|
|
|
|
void |
3195
|
|
|
|
|
|
|
reap(SV *hook, ...) |
3196
|
|
|
|
|
|
|
PROTOTYPE: &;$ |
3197
|
|
|
|
|
|
|
PREINIT: |
3198
|
|
|
|
|
|
|
I32 cxix; |
3199
|
|
|
|
|
|
|
su_ud_reap *ud; |
3200
|
|
|
|
|
|
|
CODE: |
3201
|
4433
|
100
|
|
|
|
|
SU_GET_CONTEXT(1, 1, su_context_skip_db(cxstack_ix)); |
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
3202
|
4433
|
|
|
|
|
|
cxix = su_context_normalize_down(cxix); |
3203
|
4433
|
|
|
|
|
|
Newx(ud, 1, su_ud_reap); |
3204
|
4433
|
|
|
|
|
|
SU_UD_TYPE(ud) = SU_UD_TYPE_REAP; |
3205
|
4433
|
50
|
|
|
|
|
ud->cb = (SvROK(hook) && SvTYPE(SvRV(hook)) >= SVt_PVCV) |
3206
|
8866
|
50
|
|
|
|
|
? SvRV(hook) : hook; |
3207
|
4433
|
50
|
|
|
|
|
SvREFCNT_inc_simple_void(ud->cb); |
3208
|
4433
|
|
|
|
|
|
su_init(ud, cxix, SU_SAVE_DESTRUCTOR_SIZE); |
3209
|
|
|
|
|
|
|
|
3210
|
|
|
|
|
|
|
void |
3211
|
|
|
|
|
|
|
localize(SV *sv, SV *val, ...) |
3212
|
|
|
|
|
|
|
PROTOTYPE: $$;$ |
3213
|
|
|
|
|
|
|
PREINIT: |
3214
|
|
|
|
|
|
|
I32 cxix; |
3215
|
|
|
|
|
|
|
I32 size; |
3216
|
|
|
|
|
|
|
su_ud_localize *ud; |
3217
|
|
|
|
|
|
|
CODE: |
3218
|
4080
|
50
|
|
|
|
|
SU_GET_CONTEXT(2, 2, su_context_skip_db(cxstack_ix)); |
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
3219
|
4080
|
|
|
|
|
|
cxix = su_context_normalize_down(cxix); |
3220
|
4080
|
|
|
|
|
|
Newx(ud, 1, su_ud_localize); |
3221
|
4080
|
|
|
|
|
|
SU_UD_TYPE(ud) = SU_UD_TYPE_LOCALIZE; |
3222
|
4080
|
|
|
|
|
|
size = su_ud_localize_init(ud, sv, val, NULL); |
3223
|
4076
|
|
|
|
|
|
su_init(ud, cxix, size); |
3224
|
|
|
|
|
|
|
|
3225
|
|
|
|
|
|
|
void |
3226
|
|
|
|
|
|
|
localize_elem(SV *sv, SV *elem, SV *val, ...) |
3227
|
|
|
|
|
|
|
PROTOTYPE: $$$;$ |
3228
|
|
|
|
|
|
|
PREINIT: |
3229
|
|
|
|
|
|
|
I32 cxix; |
3230
|
|
|
|
|
|
|
I32 size; |
3231
|
|
|
|
|
|
|
su_ud_localize *ud; |
3232
|
|
|
|
|
|
|
CODE: |
3233
|
7074
|
100
|
|
|
|
|
if (SvTYPE(sv) >= SVt_PVGV) |
3234
|
5
|
|
|
|
|
|
croak("Can't infer the element localization type from a glob and the value"); |
3235
|
7069
|
100
|
|
|
|
|
SU_GET_CONTEXT(3, 3, su_context_skip_db(cxstack_ix)); |
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
3236
|
7069
|
|
|
|
|
|
cxix = su_context_normalize_down(cxix); |
3237
|
7069
|
|
|
|
|
|
Newx(ud, 1, su_ud_localize); |
3238
|
|
|
|
|
|
|
/* Initialize SU_UD_ORIGIN(ud) in case SU_UD_LOCALIZE_FREE(ud) needs it */ |
3239
|
7069
|
|
|
|
|
|
SU_UD_ORIGIN(ud) = NULL; |
3240
|
7069
|
|
|
|
|
|
SU_UD_TYPE(ud) = SU_UD_TYPE_LOCALIZE; |
3241
|
7069
|
|
|
|
|
|
size = su_ud_localize_init(ud, sv, val, elem); |
3242
|
7065
|
100
|
|
|
|
|
if (SU_UD_PRIVATE(ud) != SVt_PVAV && SU_UD_PRIVATE(ud) != SVt_PVHV) { |
|
|
100
|
|
|
|
|
|
3243
|
3
|
50
|
|
|
|
|
SU_UD_LOCALIZE_FREE(ud); |
3244
|
3
|
|
|
|
|
|
croak("Can't localize an element of something that isn't an array or a hash"); |
3245
|
|
|
|
|
|
|
} |
3246
|
7062
|
|
|
|
|
|
su_init(ud, cxix, size); |
3247
|
|
|
|
|
|
|
|
3248
|
|
|
|
|
|
|
void |
3249
|
|
|
|
|
|
|
localize_delete(SV *sv, SV *elem, ...) |
3250
|
|
|
|
|
|
|
PROTOTYPE: $$;$ |
3251
|
|
|
|
|
|
|
PREINIT: |
3252
|
|
|
|
|
|
|
I32 cxix; |
3253
|
|
|
|
|
|
|
I32 size; |
3254
|
|
|
|
|
|
|
su_ud_localize *ud; |
3255
|
|
|
|
|
|
|
CODE: |
3256
|
1197
|
100
|
|
|
|
|
SU_GET_CONTEXT(2, 2, su_context_skip_db(cxstack_ix)); |
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
3257
|
1197
|
|
|
|
|
|
cxix = su_context_normalize_down(cxix); |
3258
|
1197
|
|
|
|
|
|
Newx(ud, 1, su_ud_localize); |
3259
|
1197
|
|
|
|
|
|
SU_UD_TYPE(ud) = SU_UD_TYPE_LOCALIZE; |
3260
|
1197
|
|
|
|
|
|
size = su_ud_localize_init(ud, sv, NULL, elem); |
3261
|
1193
|
|
|
|
|
|
su_init(ud, cxix, size); |
3262
|
|
|
|
|
|
|
|
3263
|
|
|
|
|
|
|
void |
3264
|
|
|
|
|
|
|
uplevel(SV *code, ...) |
3265
|
|
|
|
|
|
|
PROTOTYPE: &@ |
3266
|
|
|
|
|
|
|
PREINIT: |
3267
|
2754
|
|
|
|
|
|
I32 cxix, ret, args = 0; |
3268
|
|
|
|
|
|
|
PPCODE: |
3269
|
2754
|
100
|
|
|
|
|
if (SvROK(code)) |
3270
|
2753
|
|
|
|
|
|
code = SvRV(code); |
3271
|
2754
|
100
|
|
|
|
|
if (SvTYPE(code) < SVt_PVCV) |
3272
|
2
|
|
|
|
|
|
croak("First argument to uplevel must be a code reference"); |
3273
|
2752
|
100
|
|
|
|
|
SU_GET_CONTEXT(1, items - 1, cxstack_ix); |
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
3274
|
|
|
|
|
|
|
do { |
3275
|
3527
|
|
|
|
|
|
PERL_CONTEXT *cx = cxstack + cxix; |
3276
|
3527
|
|
|
|
|
|
switch (CxTYPE(cx)) { |
3277
|
|
|
|
|
|
|
case CXt_EVAL: |
3278
|
2
|
|
|
|
|
|
croak("Can't uplevel to an eval frame"); |
3279
|
|
|
|
|
|
|
case CXt_FORMAT: |
3280
|
0
|
|
|
|
|
|
croak("Can't uplevel to a format frame"); |
3281
|
|
|
|
|
|
|
case CXt_SUB: |
3282
|
2749
|
50
|
|
|
|
|
if (PL_DBsub && cx->blk_sub.cv == GvCV(PL_DBsub)) |
|
|
50
|
|
|
|
|
|
3283
|
0
|
|
|
|
|
|
continue; |
3284
|
2749
|
100
|
|
|
|
|
if (items > 1) { |
3285
|
2336
|
|
|
|
|
|
PL_stack_sp--; |
3286
|
2336
|
|
|
|
|
|
args = items - 2; |
3287
|
|
|
|
|
|
|
} |
3288
|
|
|
|
|
|
|
/* su_uplevel() takes care of extending the stack if needed. */ |
3289
|
|
|
|
|
|
|
#if SU_HAS_NEW_CXT |
3290
|
2749
|
|
|
|
|
|
ret = su_uplevel_new((CV *) code, cxix, args); |
3291
|
|
|
|
|
|
|
#else |
3292
|
|
|
|
|
|
|
ret = su_uplevel_old((CV *) code, cxix, args); |
3293
|
|
|
|
|
|
|
#endif |
3294
|
1736
|
|
|
|
|
|
XSRETURN(ret); |
3295
|
|
|
|
|
|
|
default: |
3296
|
776
|
|
|
|
|
|
break; |
3297
|
|
|
|
|
|
|
} |
3298
|
776
|
100
|
|
|
|
|
} while (--cxix >= 0); |
3299
|
1
|
|
|
|
|
|
croak("Can't uplevel outside a subroutine"); |
3300
|
|
|
|
|
|
|
|
3301
|
|
|
|
|
|
|
void |
3302
|
|
|
|
|
|
|
uid(...) |
3303
|
|
|
|
|
|
|
PROTOTYPE: ;$ |
3304
|
|
|
|
|
|
|
PREINIT: |
3305
|
|
|
|
|
|
|
I32 cxix; |
3306
|
|
|
|
|
|
|
SV *uid; |
3307
|
|
|
|
|
|
|
PPCODE: |
3308
|
839
|
100
|
|
|
|
|
SU_GET_CONTEXT(0, 0, su_context_here()); |
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
3309
|
839
|
|
|
|
|
|
uid = su_uid_get(cxix); |
3310
|
839
|
50
|
|
|
|
|
EXTEND(SP, 1); |
3311
|
839
|
|
|
|
|
|
PUSHs(uid); |
3312
|
839
|
|
|
|
|
|
XSRETURN(1); |
3313
|
|
|
|
|
|
|
|
3314
|
|
|
|
|
|
|
void |
3315
|
|
|
|
|
|
|
validate_uid(SV *uid) |
3316
|
|
|
|
|
|
|
PROTOTYPE: $ |
3317
|
|
|
|
|
|
|
PREINIT: |
3318
|
|
|
|
|
|
|
SV *ret; |
3319
|
|
|
|
|
|
|
PPCODE: |
3320
|
863
|
100
|
|
|
|
|
ret = su_uid_validate(uid) ? &PL_sv_yes : &PL_sv_no; |
3321
|
858
|
50
|
|
|
|
|
EXTEND(SP, 1); |
3322
|
858
|
|
|
|
|
|
PUSHs(ret); |
3323
|
858
|
|
|
|
|
|
XSRETURN(1); |