]> git.vpit.fr Git - perl/modules/indirect.git/blob - indirect.xs
7c264c5553c7f85738675b8b801f68514c3604b7
[perl/modules/indirect.git] / indirect.xs
1 /* This file is part of the indirect Perl module.
2  * See http://search.cpan.org/dist/indirect/ */
3
4 #define PERL_NO_GET_CONTEXT
5 #include "EXTERN.h"
6 #include "perl.h"
7 #include "XSUB.h"
8
9 #define __PACKAGE__     "indirect"
10 #define __PACKAGE_LEN__ (sizeof(__PACKAGE__)-1)
11
12 /* --- Compatibility wrappers ---------------------------------------------- */
13
14 #ifndef NOOP
15 # define NOOP
16 #endif
17
18 #ifndef dNOOP
19 # define dNOOP
20 #endif
21
22 #ifndef Newx
23 # define Newx(v, n, c) New(0, v, n, c)
24 #endif
25
26 #ifndef SvPV_const
27 # define SvPV_const SvPV
28 #endif
29
30 #ifndef SvPV_nolen_const
31 # define SvPV_nolen_const SvPV_nolen
32 #endif
33
34 #ifndef SvPVX_const
35 # define SvPVX_const SvPVX
36 #endif
37
38 #ifndef SvREFCNT_inc_simple_void_NN
39 # ifdef SvREFCNT_inc_simple_NN
40 #  define SvREFCNT_inc_simple_void_NN SvREFCNT_inc_simple_NN
41 # else
42 #  define SvREFCNT_inc_simple_void_NN SvREFCNT_inc
43 # endif
44 #endif
45
46 #ifndef sv_catpvn_nomg
47 # define sv_catpvn_nomg sv_catpvn
48 #endif
49
50 #ifndef mPUSHp
51 # define mPUSHp(P, L) PUSHs(sv_2mortal(newSVpvn((P), (L))))
52 #endif
53
54 #ifndef mPUSHu
55 # define mPUSHu(U) PUSHs(sv_2mortal(newSVuv(U)))
56 #endif
57
58 #ifndef HvNAME_get
59 # define HvNAME_get(H) HvNAME(H)
60 #endif
61
62 #ifndef HvNAMELEN_get
63 # define HvNAMELEN_get(H) strlen(HvNAME_get(H))
64 #endif
65
66 #ifndef OP_SIBLING
67 # define OP_SIBLING(O) ((O)->op_sibling)
68 #endif
69
70 #define I_HAS_PERL(R, V, S) (PERL_REVISION > (R) || (PERL_REVISION == (R) && (PERL_VERSION > (V) || (PERL_VERSION == (V) && (PERL_SUBVERSION >= (S))))))
71
72 #if I_HAS_PERL(5, 10, 0) || defined(PL_parser)
73 # ifndef PL_linestr
74 #  define PL_linestr PL_parser->linestr
75 # endif
76 # ifndef PL_bufptr
77 #  define PL_bufptr PL_parser->bufptr
78 # endif
79 # ifndef PL_oldbufptr
80 #  define PL_oldbufptr PL_parser->oldbufptr
81 # endif
82 # ifndef PL_lex_inwhat
83 #  define PL_lex_inwhat PL_parser->lex_inwhat
84 # endif
85 #else
86 # ifndef PL_linestr
87 #  define PL_linestr PL_Ilinestr
88 # endif
89 # ifndef PL_bufptr
90 #  define PL_bufptr PL_Ibufptr
91 # endif
92 # ifndef PL_oldbufptr
93 #  define PL_oldbufptr PL_Ioldbufptr
94 # endif
95 # ifndef PL_lex_inwhat
96 #  define PL_lex_inwhat PL_Ilex_inwhat
97 # endif
98 #endif
99
100 #ifndef I_WORKAROUND_REQUIRE_PROPAGATION
101 # define I_WORKAROUND_REQUIRE_PROPAGATION !I_HAS_PERL(5, 10, 1)
102 #endif
103
104 /* ... Thread safety and multiplicity ...................................... */
105
106 /* Safe unless stated otherwise in Makefile.PL */
107 #ifndef I_FORKSAFE
108 # define I_FORKSAFE 1
109 #endif
110
111 #ifndef I_MULTIPLICITY
112 # if defined(MULTIPLICITY) || defined(PERL_IMPLICIT_CONTEXT)
113 #  define I_MULTIPLICITY 1
114 # else
115 #  define I_MULTIPLICITY 0
116 # endif
117 #endif
118 #if I_MULTIPLICITY && !defined(tTHX)
119 # define tTHX PerlInterpreter*
120 #endif
121
122 #if I_MULTIPLICITY && defined(USE_ITHREADS) && defined(dMY_CXT) && defined(MY_CXT) && defined(START_MY_CXT) && defined(MY_CXT_INIT) && (defined(MY_CXT_CLONE) || defined(dMY_CXT_SV))
123 # define I_THREADSAFE 1
124 # ifndef MY_CXT_CLONE
125 #  define MY_CXT_CLONE \
126     dMY_CXT_SV;                                                      \
127     my_cxt_t *my_cxtp = (my_cxt_t*)SvPVX(newSV(sizeof(my_cxt_t)-1)); \
128     Copy(INT2PTR(my_cxt_t*, SvUV(my_cxt_sv)), my_cxtp, 1, my_cxt_t); \
129     sv_setuv(my_cxt_sv, PTR2UV(my_cxtp))
130 # endif
131 #else
132 # define I_THREADSAFE 0
133 # undef  dMY_CXT
134 # define dMY_CXT      dNOOP
135 # undef  MY_CXT
136 # define MY_CXT       indirect_globaldata
137 # undef  START_MY_CXT
138 # define START_MY_CXT STATIC my_cxt_t MY_CXT;
139 # undef  MY_CXT_INIT
140 # define MY_CXT_INIT  NOOP
141 # undef  MY_CXT_CLONE
142 # define MY_CXT_CLONE NOOP
143 #endif
144
145 #if defined(OP_CHECK_MUTEX_LOCK) && defined(OP_CHECK_MUTEX_UNLOCK)
146 # define I_CHECK_MUTEX_LOCK   OP_CHECK_MUTEX_LOCK
147 # define I_CHECK_MUTEX_UNLOCK OP_CHECK_MUTEX_UNLOCK
148 #else
149 # define I_CHECK_MUTEX_LOCK   OP_REFCNT_LOCK
150 # define I_CHECK_MUTEX_UNLOCK OP_REFCNT_UNLOCK
151 #endif
152
153 typedef OP *(*indirect_ck_t)(pTHX_ OP *);
154
155 #ifdef wrap_op_checker
156
157 # define indirect_ck_replace(T, NC, OCP) wrap_op_checker((T), (NC), (OCP))
158
159 #else
160
161 STATIC void indirect_ck_replace(pTHX_ OPCODE type, indirect_ck_t new_ck, indirect_ck_t *old_ck_p) {
162 #define indirect_ck_replace(T, NC, OCP) indirect_ck_replace(aTHX_ (T), (NC), (OCP))
163  I_CHECK_MUTEX_LOCK;
164  if (!*old_ck_p) {
165   *old_ck_p      = PL_check[type];
166   PL_check[type] = new_ck;
167  }
168  I_CHECK_MUTEX_UNLOCK;
169 }
170
171 #endif
172
173 STATIC void indirect_ck_restore(pTHX_ OPCODE type, indirect_ck_t *old_ck_p) {
174 #define indirect_ck_restore(T, OCP) indirect_ck_restore(aTHX_ (T), (OCP))
175  I_CHECK_MUTEX_LOCK;
176  if (*old_ck_p) {
177   PL_check[type] = *old_ck_p;
178   *old_ck_p      = 0;
179  }
180  I_CHECK_MUTEX_UNLOCK;
181 }
182
183 /* --- Helpers ------------------------------------------------------------- */
184
185 /* ... Thread-safe hints ................................................... */
186
187 #if I_WORKAROUND_REQUIRE_PROPAGATION
188
189 typedef struct {
190  SV *code;
191  IV  require_tag;
192 } indirect_hint_t;
193
194 #define I_HINT_STRUCT 1
195
196 #define I_HINT_CODE(H) ((H)->code)
197
198 #define I_HINT_FREE(H) {   \
199  indirect_hint_t *h = (H); \
200  SvREFCNT_dec(h->code);    \
201  PerlMemShared_free(h);    \
202 }
203
204 #else  /*  I_WORKAROUND_REQUIRE_PROPAGATION */
205
206 typedef SV indirect_hint_t;
207
208 #define I_HINT_STRUCT 0
209
210 #define I_HINT_CODE(H) (H)
211
212 #define I_HINT_FREE(H) SvREFCNT_dec(H);
213
214 #endif /* !I_WORKAROUND_REQUIRE_PROPAGATION */
215
216 #if I_THREADSAFE
217
218 #define PTABLE_NAME        ptable_hints
219 #define PTABLE_VAL_FREE(V) I_HINT_FREE(V)
220
221 #define pPTBL  pTHX
222 #define pPTBL_ pTHX_
223 #define aPTBL  aTHX
224 #define aPTBL_ aTHX_
225
226 #include "ptable.h"
227
228 #define ptable_hints_store(T, K, V) ptable_hints_store(aTHX_ (T), (K), (V))
229 #define ptable_hints_free(T)        ptable_hints_free(aTHX_ (T))
230
231 #endif /* I_THREADSAFE */
232
233 /* Define the op->str ptable here because we need to be able to clean it during
234  * thread cleanup. */
235
236 typedef struct {
237  char   *buf;
238  STRLEN  pos;
239  STRLEN  size;
240  STRLEN  len;
241  line_t  line;
242 } indirect_op_info_t;
243
244 #define PTABLE_NAME        ptable
245 #define PTABLE_VAL_FREE(V) if (V) { Safefree(((indirect_op_info_t *) (V))->buf); Safefree(V); }
246
247 #define pPTBL  pTHX
248 #define pPTBL_ pTHX_
249 #define aPTBL  aTHX
250 #define aPTBL_ aTHX_
251
252 #include "ptable.h"
253
254 #define ptable_store(T, K, V) ptable_store(aTHX_ (T), (K), (V))
255 #define ptable_delete(T, K)   ptable_delete(aTHX_ (T), (K))
256 #define ptable_clear(T)       ptable_clear(aTHX_ (T))
257 #define ptable_free(T)        ptable_free(aTHX_ (T))
258
259 #define MY_CXT_KEY __PACKAGE__ "::_guts" XS_VERSION
260
261 typedef struct {
262 #if I_THREADSAFE
263  ptable *tbl; /* It really is a ptable_hints */
264  tTHX    owner;
265 #endif
266  ptable *map;
267  SV     *global_code;
268 } my_cxt_t;
269
270 START_MY_CXT
271
272 #if I_THREADSAFE
273
274 typedef struct {
275  ptable *tbl;
276 #if I_HAS_PERL(5, 13, 2)
277  CLONE_PARAMS *params;
278 #else
279  CLONE_PARAMS params;
280 #endif
281 } indirect_ptable_clone_ud;
282
283 #if I_HAS_PERL(5, 13, 2)
284 # define indirect_ptable_clone_ud_init(U, T, O) \
285    (U).tbl    = (T); \
286    (U).params = Perl_clone_params_new((O), aTHX)
287 # define indirect_ptable_clone_ud_deinit(U) Perl_clone_params_del((U).params)
288 # define indirect_dup_inc(S, U)             SvREFCNT_inc(sv_dup((S), (U)->params))
289 #else
290 # define indirect_ptable_clone_ud_init(U, T, O) \
291    (U).tbl               = (T);     \
292    (U).params.stashes    = newAV(); \
293    (U).params.flags      = 0;       \
294    (U).params.proto_perl = (O)
295 # define indirect_ptable_clone_ud_deinit(U) SvREFCNT_dec((U).params.stashes)
296 # define indirect_dup_inc(S, U)             SvREFCNT_inc(sv_dup((S), &((U)->params)))
297 #endif
298
299 STATIC void indirect_ptable_clone(pTHX_ ptable_ent *ent, void *ud_) {
300  indirect_ptable_clone_ud *ud = ud_;
301  indirect_hint_t          *h1 = ent->val;
302  indirect_hint_t          *h2;
303
304 #if I_HINT_STRUCT
305
306  h2              = PerlMemShared_malloc(sizeof *h2);
307  h2->code        = indirect_dup_inc(h1->code, ud);
308 #if I_WORKAROUND_REQUIRE_PROPAGATION
309  h2->require_tag = PTR2IV(indirect_dup_inc(INT2PTR(SV *, h1->require_tag), ud));
310 #endif
311
312 #else  /*  I_HINT_STRUCT */
313
314  h2 = indirect_dup_inc(h1, ud);
315
316 #endif /* !I_HINT_STRUCT */
317
318  ptable_hints_store(ud->tbl, ent->key, h2);
319 }
320
321 STATIC void indirect_thread_cleanup(pTHX_ void *ud) {
322  dMY_CXT;
323
324  SvREFCNT_dec(MY_CXT.global_code);
325  MY_CXT.global_code = NULL;
326  ptable_free(MY_CXT.map);
327  MY_CXT.map = NULL;
328  ptable_hints_free(MY_CXT.tbl);
329  MY_CXT.tbl = NULL;
330 }
331
332 STATIC int indirect_endav_free(pTHX_ SV *sv, MAGIC *mg) {
333  SAVEDESTRUCTOR_X(indirect_thread_cleanup, NULL);
334
335  return 0;
336 }
337
338 STATIC MGVTBL indirect_endav_vtbl = {
339  0,
340  0,
341  0,
342  0,
343  indirect_endav_free
344 #if MGf_COPY
345  , 0
346 #endif
347 #if MGf_DUP
348  , 0
349 #endif
350 #if MGf_LOCAL
351  , 0
352 #endif
353 };
354
355 #endif /* I_THREADSAFE */
356
357 #if I_WORKAROUND_REQUIRE_PROPAGATION
358 STATIC IV indirect_require_tag(pTHX) {
359 #define indirect_require_tag() indirect_require_tag(aTHX)
360  const CV *cv, *outside;
361
362  cv = PL_compcv;
363
364  if (!cv) {
365   /* If for some reason the pragma is operational at run-time, try to discover
366    * the current cv in use. */
367   const PERL_SI *si;
368
369   for (si = PL_curstackinfo; si; si = si->si_prev) {
370    I32 cxix;
371
372    for (cxix = si->si_cxix; cxix >= 0; --cxix) {
373     const PERL_CONTEXT *cx = si->si_cxstack + cxix;
374
375     switch (CxTYPE(cx)) {
376      case CXt_SUB:
377      case CXt_FORMAT:
378       /* The propagation workaround is only needed up to 5.10.0 and at that
379        * time format and sub contexts were still identical. And even later the
380        * cv members offsets should have been kept the same. */
381       cv = cx->blk_sub.cv;
382       goto get_enclosing_cv;
383      case CXt_EVAL:
384       cv = cx->blk_eval.cv;
385       goto get_enclosing_cv;
386      default:
387       break;
388     }
389    }
390   }
391
392   cv = PL_main_cv;
393  }
394
395 get_enclosing_cv:
396  for (outside = CvOUTSIDE(cv); outside; outside = CvOUTSIDE(cv))
397   cv = outside;
398
399  return PTR2IV(cv);
400 }
401 #endif /* I_WORKAROUND_REQUIRE_PROPAGATION */
402
403 STATIC SV *indirect_tag(pTHX_ SV *value) {
404 #define indirect_tag(V) indirect_tag(aTHX_ (V))
405  indirect_hint_t *h;
406  SV *code = NULL;
407
408  if (SvROK(value)) {
409   value = SvRV(value);
410   if (SvTYPE(value) >= SVt_PVCV) {
411    code = value;
412    SvREFCNT_inc_simple_void_NN(code);
413   }
414  }
415
416 #if I_HINT_STRUCT
417  h = PerlMemShared_malloc(sizeof *h);
418  h->code        = code;
419 # if I_WORKAROUND_REQUIRE_PROPAGATION
420  h->require_tag = indirect_require_tag();
421 # endif /* I_WORKAROUND_REQUIRE_PROPAGATION */
422 #else  /*  I_HINT_STRUCT */
423  h = code;
424 #endif /* !I_HINT_STRUCT */
425
426 #if I_THREADSAFE
427  {
428   dMY_CXT;
429   /* We only need for the key to be an unique tag for looking up the value later
430    * Allocated memory provides convenient unique identifiers, so that's why we
431    * use the hint as the key itself. */
432   ptable_hints_store(MY_CXT.tbl, h, h);
433  }
434 #endif /* I_THREADSAFE */
435
436  return newSViv(PTR2IV(h));
437 }
438
439 STATIC SV *indirect_detag(pTHX_ const SV *hint) {
440 #define indirect_detag(H) indirect_detag(aTHX_ (H))
441  indirect_hint_t *h;
442 #if I_THREADSAFE || I_WORKAROUND_REQUIRE_PROPAGATION
443  dMY_CXT;
444 #endif
445
446  h = INT2PTR(indirect_hint_t *, SvIVX(hint));
447 #if I_THREADSAFE
448  h = ptable_fetch(MY_CXT.tbl, h);
449 #endif /* I_THREADSAFE */
450
451 #if I_WORKAROUND_REQUIRE_PROPAGATION
452  if (indirect_require_tag() != h->require_tag)
453   return MY_CXT.global_code;
454 #endif /* I_WORKAROUND_REQUIRE_PROPAGATION */
455
456  return I_HINT_CODE(h);
457 }
458
459 STATIC U32 indirect_hash = 0;
460
461 STATIC SV *indirect_hint(pTHX) {
462 #define indirect_hint() indirect_hint(aTHX)
463  SV *hint = NULL;
464
465  if (IN_PERL_RUNTIME)
466   return NULL;
467
468 #if I_HAS_PERL(5, 10, 0) || defined(PL_parser)
469  if (!PL_parser)
470   return NULL;
471 #endif
472
473 #ifdef cop_hints_fetch_pvn
474  hint = cop_hints_fetch_pvn(PL_curcop, __PACKAGE__, __PACKAGE_LEN__,
475                                                               indirect_hash, 0);
476 #elif I_HAS_PERL(5, 9, 5)
477  hint = Perl_refcounted_he_fetch(aTHX_ PL_curcop->cop_hints_hash,
478                                        NULL,
479                                        __PACKAGE__, __PACKAGE_LEN__,
480                                        0,
481                                        indirect_hash);
482 #else
483  {
484   SV **val = hv_fetch(GvHV(PL_hintgv), __PACKAGE__, __PACKAGE_LEN__, 0);
485   if (val)
486    hint = *val;
487  }
488 #endif
489
490  if (hint && SvIOK(hint))
491   return indirect_detag(hint);
492  else {
493   dMY_CXT;
494   return MY_CXT.global_code;
495  }
496 }
497
498 /* ... op -> source position ............................................... */
499
500 STATIC void indirect_map_store(pTHX_ const OP *o, STRLEN pos, SV *sv, line_t line) {
501 #define indirect_map_store(O, P, N, L) indirect_map_store(aTHX_ (O), (P), (N), (L))
502  indirect_op_info_t *oi;
503  const char *s;
504  STRLEN len;
505  dMY_CXT;
506
507  if (!(oi = ptable_fetch(MY_CXT.map, o))) {
508   Newx(oi, 1, indirect_op_info_t);
509   ptable_store(MY_CXT.map, o, oi);
510   oi->buf  = NULL;
511   oi->size = 0;
512  }
513
514  if (sv) {
515   s = SvPV_const(sv, len);
516  } else {
517   s   = "{";
518   len = 1;
519  }
520
521  if (len > oi->size) {
522   Safefree(oi->buf);
523   Newx(oi->buf, len, char);
524   oi->size = len;
525  }
526  Copy(s, oi->buf, len, char);
527
528  oi->len  = len;
529  oi->pos  = pos;
530  oi->line = line;
531 }
532
533 STATIC const indirect_op_info_t *indirect_map_fetch(pTHX_ const OP *o) {
534 #define indirect_map_fetch(O) indirect_map_fetch(aTHX_ (O))
535  dMY_CXT;
536
537  return ptable_fetch(MY_CXT.map, o);
538 }
539
540 STATIC void indirect_map_delete(pTHX_ const OP *o) {
541 #define indirect_map_delete(O) indirect_map_delete(aTHX_ (O))
542  dMY_CXT;
543
544  ptable_delete(MY_CXT.map, o);
545 }
546
547 /* --- Check functions ----------------------------------------------------- */
548
549 STATIC int indirect_find(pTHX_ SV *name_sv, const char *line_bufptr, STRLEN *name_pos) {
550 #define indirect_find(NSV, LBP, NP) indirect_find(aTHX_ (NSV), (LBP), (NP))
551  STRLEN      name_len, line_len;
552  const char *name, *name_end;
553  const char *line, *line_end;
554  const char *p;
555
556  line     = SvPV_const(PL_linestr, line_len);
557  line_end = line + line_len;
558
559  name = SvPV_const(name_sv, name_len);
560  if (name_len >= 1 && *name == '$') {
561   ++name;
562   --name_len;
563   while (line_bufptr < line_end && *line_bufptr != '$')
564    ++line_bufptr;
565   if (line_bufptr >= line_end)
566    return 0;
567  }
568  name_end = name + name_len;
569
570  p = line_bufptr;
571  while (1) {
572   p = ninstr(p, line_end, name, name_end);
573   if (!p)
574    return 0;
575   if (!isALNUM(p[name_len]))
576    break;
577   /* p points to a word that has name as prefix, skip the rest of the word */
578   p += name_len + 1;
579   while (isALNUM(*p))
580    ++p;
581  }
582
583  *name_pos = p - line;
584
585  return 1;
586 }
587
588 /* ... ck_const ............................................................ */
589
590 STATIC OP *(*indirect_old_ck_const)(pTHX_ OP *) = 0;
591
592 STATIC OP *indirect_ck_const(pTHX_ OP *o) {
593  o = indirect_old_ck_const(aTHX_ o);
594
595  if (indirect_hint()) {
596   SV *sv = cSVOPo_sv;
597
598   if (SvPOK(sv) && (SvTYPE(sv) >= SVt_PV)) {
599    STRLEN pos;
600
601    if (indirect_find(sv, PL_oldbufptr, &pos)) {
602     STRLEN len;
603
604     /* If the constant is equal to the current package name, try to look for
605      * a "__PACKAGE__" coming before what we got. We only need to check this
606      * when we already had a match because __PACKAGE__ can only appear in
607      * direct method calls ("new __PACKAGE__" is a syntax error). */
608     len = SvCUR(sv);
609     if (PL_curstash
610         && len == (STRLEN) HvNAMELEN_get(PL_curstash)
611         && memcmp(SvPVX(sv), HvNAME_get(PL_curstash), len) == 0) {
612      STRLEN pos_pkg;
613      SV    *pkg = sv_newmortal();
614      sv_setpvn(pkg, "__PACKAGE__", sizeof("__PACKAGE__")-1);
615
616      if (indirect_find(pkg, PL_oldbufptr, &pos_pkg) && pos_pkg < pos) {
617       sv  = pkg;
618       pos = pos_pkg;
619      }
620     }
621
622     indirect_map_store(o, pos, sv, CopLINE(&PL_compiling));
623     return o;
624    }
625   }
626  }
627
628  indirect_map_delete(o);
629  return o;
630 }
631
632 /* ... ck_rv2sv ............................................................ */
633
634 STATIC OP *(*indirect_old_ck_rv2sv)(pTHX_ OP *) = 0;
635
636 STATIC OP *indirect_ck_rv2sv(pTHX_ OP *o) {
637  if (indirect_hint()) {
638   OP *op = cUNOPo->op_first;
639   SV *sv;
640   const char *name = NULL;
641   STRLEN pos, len;
642   OPCODE type = (OPCODE) op->op_type;
643
644   switch (type) {
645    case OP_GV:
646    case OP_GVSV: {
647     GV *gv = cGVOPx_gv(op);
648     name = GvNAME(gv);
649     len  = GvNAMELEN(gv);
650     break;
651    }
652    default:
653     if ((PL_opargs[type] & OA_CLASS_MASK) == OA_SVOP) {
654      SV *nsv = cSVOPx_sv(op);
655      if (SvPOK(nsv) && (SvTYPE(nsv) >= SVt_PV))
656       name = SvPV_const(nsv, len);
657     }
658   }
659   if (!name)
660    goto done;
661
662   sv = sv_2mortal(newSVpvn("$", 1));
663   sv_catpvn_nomg(sv, name, len);
664   if (!indirect_find(sv, PL_oldbufptr, &pos)) {
665    /* If it failed, retry without the current stash */
666    const char *stash = HvNAME_get(PL_curstash);
667    STRLEN stashlen = HvNAMELEN_get(PL_curstash);
668
669    if ((len < stashlen + 2) || strnNE(name, stash, stashlen)
670        || name[stashlen] != ':' || name[stashlen+1] != ':') {
671     /* Failed again ? Try to remove main */
672     stash = "main";
673     stashlen = 4;
674     if ((len < stashlen + 2) || strnNE(name, stash, stashlen)
675         || name[stashlen] != ':' || name[stashlen+1] != ':')
676      goto done;
677    }
678
679    sv_setpvn(sv, "$", 1);
680    stashlen += 2;
681    sv_catpvn_nomg(sv, name + stashlen, len - stashlen);
682    if (!indirect_find(sv, PL_oldbufptr, &pos))
683     goto done;
684   }
685
686   o = indirect_old_ck_rv2sv(aTHX_ o);
687
688   indirect_map_store(o, pos, sv, CopLINE(&PL_compiling));
689   return o;
690  }
691
692 done:
693  o = indirect_old_ck_rv2sv(aTHX_ o);
694
695  indirect_map_delete(o);
696  return o;
697 }
698
699 /* ... ck_padany ........................................................... */
700
701 STATIC OP *(*indirect_old_ck_padany)(pTHX_ OP *) = 0;
702
703 STATIC OP *indirect_ck_padany(pTHX_ OP *o) {
704  o = indirect_old_ck_padany(aTHX_ o);
705
706  if (indirect_hint()) {
707   SV *sv;
708   const char *s = PL_oldbufptr, *t = PL_bufptr - 1;
709
710   while (s < t && isSPACE(*s)) ++s;
711   if (*s == '$' && ++s <= t) {
712    while (s < t && isSPACE(*s)) ++s;
713    while (s < t && isSPACE(*t)) --t;
714    sv = sv_2mortal(newSVpvn("$", 1));
715    sv_catpvn_nomg(sv, s, t - s + 1);
716    indirect_map_store(o, s - SvPVX_const(PL_linestr),
717                          sv, CopLINE(&PL_compiling));
718    return o;
719   }
720  }
721
722  indirect_map_delete(o);
723  return o;
724 }
725
726 /* ... ck_scope ............................................................ */
727
728 STATIC OP *(*indirect_old_ck_scope)  (pTHX_ OP *) = 0;
729 STATIC OP *(*indirect_old_ck_lineseq)(pTHX_ OP *) = 0;
730
731 STATIC OP *indirect_ck_scope(pTHX_ OP *o) {
732  OP *(*old_ck)(pTHX_ OP *) = 0;
733
734  switch (o->op_type) {
735   case OP_SCOPE:   old_ck = indirect_old_ck_scope;   break;
736   case OP_LINESEQ: old_ck = indirect_old_ck_lineseq; break;
737  }
738  o = old_ck(aTHX_ o);
739
740  if (indirect_hint()) {
741   indirect_map_store(o, PL_oldbufptr - SvPVX_const(PL_linestr),
742                         NULL, CopLINE(&PL_compiling));
743   return o;
744  }
745
746  indirect_map_delete(o);
747  return o;
748 }
749
750 /* We don't need to clean the map entries for leave ops because they can only
751  * be created by mutating from a lineseq. */
752
753 /* ... ck_method ........................................................... */
754
755 STATIC OP *(*indirect_old_ck_method)(pTHX_ OP *) = 0;
756
757 STATIC OP *indirect_ck_method(pTHX_ OP *o) {
758  if (indirect_hint()) {
759   OP *op = cUNOPo->op_first;
760
761   /* Indirect method call is only possible when the method is a bareword, so
762    * don't trip up on $obj->$meth. */
763   if (op && op->op_type == OP_CONST) {
764    const indirect_op_info_t *oi = indirect_map_fetch(op);
765    STRLEN pos;
766    line_t line;
767    SV *sv;
768
769    if (!oi)
770     goto done;
771
772    sv   = sv_2mortal(newSVpvn(oi->buf, oi->len));
773    pos  = oi->pos;
774    /* Keep the old line so that we really point to the first line of the
775     * expression. */
776    line = oi->line;
777
778    o = indirect_old_ck_method(aTHX_ o);
779    /* o may now be a method_named */
780
781    indirect_map_store(o, pos, sv, line);
782    return o;
783   }
784  }
785
786 done:
787  o = indirect_old_ck_method(aTHX_ o);
788
789  indirect_map_delete(o);
790  return o;
791 }
792
793 /* ... ck_method_named ..................................................... */
794
795 /* "use foo/no foo" compiles its call to import/unimport directly to a
796  * method_named op. */
797
798 STATIC OP *(*indirect_old_ck_method_named)(pTHX_ OP *) = 0;
799
800 STATIC OP *indirect_ck_method_named(pTHX_ OP *o) {
801  if (indirect_hint()) {
802   STRLEN pos;
803   line_t line;
804   SV *sv;
805
806   sv = cSVOPo_sv;
807   if (!SvPOK(sv) || (SvTYPE(sv) < SVt_PV))
808    goto done;
809   sv = sv_mortalcopy(sv);
810
811   if (!indirect_find(sv, PL_oldbufptr, &pos))
812    goto done;
813   line = CopLINE(&PL_compiling);
814
815   o = indirect_old_ck_method_named(aTHX_ o);
816
817   indirect_map_store(o, pos, sv, line);
818   return o;
819  }
820
821 done:
822  o = indirect_old_ck_method_named(aTHX_ o);
823
824  indirect_map_delete(o);
825  return o;
826 }
827
828 /* ... ck_entersub ......................................................... */
829
830 STATIC OP *(*indirect_old_ck_entersub)(pTHX_ OP *) = 0;
831
832 STATIC OP *indirect_ck_entersub(pTHX_ OP *o) {
833  SV *code = indirect_hint();
834
835  o = indirect_old_ck_entersub(aTHX_ o);
836
837  if (code) {
838   const indirect_op_info_t *moi, *ooi;
839   OP     *mop, *oop;
840   LISTOP *lop;
841
842   oop = o;
843   do {
844    lop = (LISTOP *) oop;
845    if (!(lop->op_flags & OPf_KIDS))
846     goto done;
847    oop = lop->op_first;
848   } while (oop->op_type != OP_PUSHMARK);
849   oop = OP_SIBLING(oop);
850   mop = lop->op_last;
851
852   if (!oop)
853    goto done;
854
855   switch (oop->op_type) {
856    case OP_CONST:
857    case OP_RV2SV:
858    case OP_PADSV:
859    case OP_SCOPE:
860    case OP_LEAVE:
861     break;
862    default:
863     goto done;
864   }
865
866   if (mop->op_type == OP_METHOD)
867    mop = cUNOPx(mop)->op_first;
868   else if (mop->op_type != OP_METHOD_NAMED)
869    goto done;
870
871   moi = indirect_map_fetch(mop);
872   if (!moi)
873    goto done;
874
875   ooi = indirect_map_fetch(oop);
876   if (!ooi)
877    goto done;
878
879   /* When positions are identical, the method and the object must have the
880    * same name. But it also means that it is an indirect call, as "foo->foo"
881    * results in different positions. */
882   if (   moi->line < ooi->line
883       || (moi->line == ooi->line && moi->pos <= ooi->pos)) {
884    SV *file;
885    dSP;
886
887    ENTER;
888    SAVETMPS;
889
890 #ifdef USE_ITHREADS
891    file = sv_2mortal(newSVpv(CopFILE(&PL_compiling), 0));
892 #else
893    file = sv_mortalcopy(CopFILESV(&PL_compiling));
894 #endif
895
896    PUSHMARK(SP);
897    EXTEND(SP, 4);
898    mPUSHp(ooi->buf, ooi->len);
899    mPUSHp(moi->buf, moi->len);
900    PUSHs(file);
901    mPUSHu(moi->line);
902    PUTBACK;
903
904    call_sv(code, G_VOID);
905
906    PUTBACK;
907
908    FREETMPS;
909    LEAVE;
910   }
911  }
912
913 done:
914  return o;
915 }
916
917 STATIC U32 indirect_initialized = 0;
918
919 STATIC void indirect_teardown(pTHX_ void *root) {
920  if (!indirect_initialized)
921   return;
922
923 #if I_MULTIPLICITY
924  if (aTHX != root)
925   return;
926 #endif
927
928  {
929   dMY_CXT;
930   ptable_free(MY_CXT.map);
931   MY_CXT.map = NULL;
932 #if I_THREADSAFE
933   ptable_hints_free(MY_CXT.tbl);
934   MY_CXT.tbl = NULL;
935 #endif
936  }
937
938  indirect_ck_restore(OP_CONST,   &indirect_old_ck_const);
939  indirect_ck_restore(OP_RV2SV,   &indirect_old_ck_rv2sv);
940  indirect_ck_restore(OP_PADANY,  &indirect_old_ck_padany);
941  indirect_ck_restore(OP_SCOPE,   &indirect_old_ck_scope);
942  indirect_ck_restore(OP_LINESEQ, &indirect_old_ck_lineseq);
943
944  indirect_ck_restore(OP_METHOD,       &indirect_old_ck_method);
945  indirect_ck_restore(OP_METHOD_NAMED, &indirect_old_ck_method_named);
946  indirect_ck_restore(OP_ENTERSUB,     &indirect_old_ck_entersub);
947
948  indirect_initialized = 0;
949 }
950
951 STATIC void indirect_setup(pTHX) {
952 #define indirect_setup() indirect_setup(aTHX)
953  if (indirect_initialized)
954   return;
955
956  {
957   MY_CXT_INIT;
958 #if I_THREADSAFE
959   MY_CXT.tbl         = ptable_new();
960   MY_CXT.owner       = aTHX;
961 #endif
962   MY_CXT.map         = ptable_new();
963   MY_CXT.global_code = NULL;
964  }
965
966  indirect_ck_replace(OP_CONST,   indirect_ck_const,  &indirect_old_ck_const);
967  indirect_ck_replace(OP_RV2SV,   indirect_ck_rv2sv,  &indirect_old_ck_rv2sv);
968  indirect_ck_replace(OP_PADANY,  indirect_ck_padany, &indirect_old_ck_padany);
969  indirect_ck_replace(OP_SCOPE,   indirect_ck_scope,  &indirect_old_ck_scope);
970  indirect_ck_replace(OP_LINESEQ, indirect_ck_scope,  &indirect_old_ck_lineseq);
971
972  indirect_ck_replace(OP_METHOD,       indirect_ck_method,
973                                       &indirect_old_ck_method);
974  indirect_ck_replace(OP_METHOD_NAMED, indirect_ck_method_named,
975                                       &indirect_old_ck_method_named);
976  indirect_ck_replace(OP_ENTERSUB,     indirect_ck_entersub,
977                                       &indirect_old_ck_entersub);
978
979 #if I_MULTIPLICITY
980  call_atexit(indirect_teardown, aTHX);
981 #else
982  call_atexit(indirect_teardown, NULL);
983 #endif
984
985  indirect_initialized = 1;
986 }
987
988 STATIC U32 indirect_booted = 0;
989
990 /* --- XS ------------------------------------------------------------------ */
991
992 MODULE = indirect      PACKAGE = indirect
993
994 PROTOTYPES: ENABLE
995
996 BOOT:
997 {
998  if (!indirect_booted++) {
999   HV *stash;
1000
1001   PERL_HASH(indirect_hash, __PACKAGE__, __PACKAGE_LEN__);
1002
1003   stash = gv_stashpvn(__PACKAGE__, __PACKAGE_LEN__, 1);
1004   newCONSTSUB(stash, "I_THREADSAFE", newSVuv(I_THREADSAFE));
1005   newCONSTSUB(stash, "I_FORKSAFE",   newSVuv(I_FORKSAFE));
1006  }
1007
1008  indirect_setup();
1009 }
1010
1011 #if I_THREADSAFE
1012
1013 void
1014 CLONE(...)
1015 PROTOTYPE: DISABLE
1016 PREINIT:
1017  ptable *t;
1018  SV     *global_code_dup;
1019  GV     *gv;
1020 PPCODE:
1021  {
1022   indirect_ptable_clone_ud ud;
1023   dMY_CXT;
1024   t = ptable_new();
1025   indirect_ptable_clone_ud_init(ud, t, MY_CXT.owner);
1026   ptable_walk(MY_CXT.tbl, indirect_ptable_clone, &ud);
1027   global_code_dup = indirect_dup_inc(MY_CXT.global_code, &ud);
1028   indirect_ptable_clone_ud_deinit(ud);
1029  }
1030  {
1031   MY_CXT_CLONE;
1032   MY_CXT.map         = ptable_new();
1033   MY_CXT.tbl         = t;
1034   MY_CXT.owner       = aTHX;
1035   MY_CXT.global_code = global_code_dup;
1036  }
1037  gv = gv_fetchpv(__PACKAGE__ "::_THREAD_CLEANUP", 0, SVt_PVCV);
1038  if (gv) {
1039   CV *cv = GvCV(gv);
1040   if (!PL_endav)
1041    PL_endav = newAV();
1042   SvREFCNT_inc(cv);
1043   if (!av_store(PL_endav, av_len(PL_endav) + 1, (SV *) cv))
1044    SvREFCNT_dec(cv);
1045   sv_magicext((SV *) PL_endav, NULL, PERL_MAGIC_ext, &indirect_endav_vtbl, NULL, 0);
1046  }
1047  XSRETURN(0);
1048
1049 void
1050 _THREAD_CLEANUP(...)
1051 PROTOTYPE: DISABLE
1052 PPCODE:
1053  indirect_thread_cleanup(aTHX_ NULL);
1054  XSRETURN(0);
1055
1056 #endif
1057
1058 SV *
1059 _tag(SV *value)
1060 PROTOTYPE: $
1061 CODE:
1062  RETVAL = indirect_tag(value);
1063 OUTPUT:
1064  RETVAL
1065
1066 void
1067 _global(SV *code)
1068 PROTOTYPE: $
1069 PPCODE:
1070  if (!SvOK(code))
1071   code = NULL;
1072  else if (SvROK(code))
1073   code = SvRV(code);
1074  {
1075   dMY_CXT;
1076   SvREFCNT_dec(MY_CXT.global_code);
1077   MY_CXT.global_code = SvREFCNT_inc(code);
1078  }
1079  XSRETURN(0);