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