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