1 /* This file is part of the re::engine::Plugin Perl module.
2 * See http://search.cpan.org/dist/re-engine-Plugin/ */
4 #define PERL_NO_GET_CONTEXT
11 #define __PACKAGE__ "re::engine::Plugin"
12 #define __PACKAGE_LEN__ (sizeof(__PACKAGE__)-1)
14 #define REP_HAS_PERL(R, V, S) (PERL_REVISION > (R) || (PERL_REVISION == (R) && (PERL_VERSION > (V) || (PERL_VERSION == (V) && (PERL_SUBVERSION >= (S))))))
16 #ifndef REP_WORKAROUND_REQUIRE_PROPAGATION
17 # define REP_WORKAROUND_REQUIRE_PROPAGATION !REP_HAS_PERL(5, 10, 1)
20 /* ... Thread safety and multiplicity ...................................... */
22 #ifndef REP_MULTIPLICITY
23 # if defined(MULTIPLICITY) || defined(PERL_IMPLICIT_CONTEXT)
24 # define REP_MULTIPLICITY 1
26 # define REP_MULTIPLICITY 0
29 #if REP_MULTIPLICITY && !defined(tTHX)
30 # define tTHX PerlInterpreter*
33 #if REP_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))
34 # define REP_THREADSAFE 1
36 # define MY_CXT_CLONE \
38 my_cxt_t *my_cxtp = (my_cxt_t*)SvPVX(newSV(sizeof(my_cxt_t)-1)); \
39 Copy(INT2PTR(my_cxt_t*, SvUV(my_cxt_sv)), my_cxtp, 1, my_cxt_t); \
40 sv_setuv(my_cxt_sv, PTR2UV(my_cxtp))
43 # define REP_THREADSAFE 0
45 # define dMY_CXT dNOOP
47 # define MY_CXT rep_globaldata
49 # define START_MY_CXT STATIC my_cxt_t MY_CXT;
51 # define MY_CXT_INIT NOOP
53 # define MY_CXT_CLONE NOOP
56 /* --- Helpers ------------------------------------------------------------- */
58 /* ... Thread-safe hints ................................................... */
63 #if REP_WORKAROUND_REQUIRE_PROPAGATION
70 #define PTABLE_VAL_FREE(V) { \
71 rep_hint_t *h = (V); \
72 SvREFCNT_dec(h->comp); \
73 SvREFCNT_dec(h->exec); \
74 PerlMemShared_free(h); \
84 #define ptable_store(T, K, V) ptable_store(aTHX_ (T), (K), (V))
85 #define ptable_free(T) ptable_free(aTHX_ (T))
87 #define MY_CXT_KEY __PACKAGE__ "::_guts" XS_VERSION
98 #if REP_HAS_PERL(5, 13, 2)
103 } rep_ptable_clone_ud;
105 #if REP_HAS_PERL(5, 13, 2)
106 # define rep_ptable_clone_ud_init(U, T, O) \
108 (U).params = Perl_clone_params_new((O), aTHX)
109 # define rep_ptable_clone_ud_deinit(U) Perl_clone_params_del((U).params)
110 # define rep_dup_inc(S, U) SvREFCNT_inc(sv_dup((S), (U)->params))
112 # define rep_ptable_clone_ud_init(U, T, O) \
114 (U).params.stashes = newAV(); \
115 (U).params.flags = 0; \
116 (U).params.proto_perl = (O)
117 # define rep_ptable_clone_ud_deinit(U) SvREFCNT_dec((U).params.stashes)
118 # define rep_dup_inc(S, U) SvREFCNT_inc(sv_dup((S), &((U)->params)))
121 STATIC void rep_ptable_clone(pTHX_ ptable_ent *ent, void *ud_) {
122 rep_ptable_clone_ud *ud = ud_;
123 rep_hint_t *h1 = ent->val;
126 h2 = PerlMemShared_malloc(sizeof *h2);
127 h2->comp = rep_dup_inc(h1->comp, ud);
128 h2->exec = rep_dup_inc(h1->exec, ud);
129 #if REP_WORKAROUND_REQUIRE_PROPAGATION
130 h2->require_tag = PTR2IV(rep_dup_inc(INT2PTR(SV *, h1->require_tag), ud));
133 ptable_store(ud->tbl, ent->key, h2);
138 STATIC void rep_thread_cleanup(pTHX_ void *ud) {
141 ptable_free(MY_CXT.tbl);
144 #endif /* REP_THREADSAFE */
146 STATIC SV *rep_validate_callback(SV *code) {
151 if (SvTYPE(code) < SVt_PVCV)
154 return SvREFCNT_inc_simple_NN(code);
157 #if REP_WORKAROUND_REQUIRE_PROPAGATION
158 STATIC IV rep_require_tag(pTHX) {
159 #define rep_require_tag() rep_require_tag(aTHX)
160 const CV *cv, *outside;
165 /* If for some reason the pragma is operational at run-time, try to discover
166 * the current cv in use. */
169 for (si = PL_curstackinfo; si; si = si->si_prev) {
172 for (cxix = si->si_cxix; cxix >= 0; --cxix) {
173 const PERL_CONTEXT *cx = si->si_cxstack + cxix;
175 switch (CxTYPE(cx)) {
178 /* The propagation workaround is only needed up to 5.10.0 and at that
179 * time format and sub contexts were still identical. And even later the
180 * cv members offsets should have been kept the same. */
182 goto get_enclosing_cv;
184 cv = cx->blk_eval.cv;
185 goto get_enclosing_cv;
196 for (outside = CvOUTSIDE(cv); outside; outside = CvOUTSIDE(cv))
201 #endif /* REP_WORKAROUND_REQUIRE_PROPAGATION */
203 STATIC SV *rep_tag(pTHX_ SV *comp, SV *exec) {
204 #define rep_tag(C, E) rep_tag(aTHX_ (C), (E))
208 h = PerlMemShared_malloc(sizeof *h);
209 h->comp = rep_validate_callback(comp);
210 h->exec = rep_validate_callback(exec);
211 #if REP_WORKAROUND_REQUIRE_PROPAGATION
212 h->require_tag = rep_require_tag();
213 #endif /* REP_WORKAROUND_REQUIRE_PROPAGATION */
218 /* We only need for the key to be an unique tag for looking up the value later
219 * Allocated memory provides convenient unique identifiers, so that's why we
220 * use the hint as the key itself. */
221 ptable_store(MY_CXT.tbl, h, h);
223 #endif /* REP_THREADSAFE */
225 return newSViv(PTR2IV(h));
228 STATIC const rep_hint_t *rep_detag(pTHX_ const SV *hint) {
229 #define rep_detag(H) rep_detag(aTHX_ (H))
232 if (!(hint && SvIOK(hint)))
235 h = INT2PTR(rep_hint_t *, SvIVX(hint));
239 h = ptable_fetch(MY_CXT.tbl, h);
241 #endif /* REP_THREADSAFE */
243 #if REP_WORKAROUND_REQUIRE_PROPAGATION
244 if (rep_require_tag() != h->require_tag)
246 #endif /* REP_WORKAROUND_REQUIRE_PROPAGATION */
251 STATIC U32 rep_hash = 0;
253 STATIC const rep_hint_t *rep_hint(pTHX) {
254 #define rep_hint() rep_hint(aTHX)
257 #ifdef cop_hints_fetch_pvn
258 hint = cop_hints_fetch_pvn(PL_curcop,
259 __PACKAGE__, __PACKAGE_LEN__, rep_hash, 0);
261 /* We already require 5.9.5 for the regexp engine API. */
262 hint = Perl_refcounted_he_fetch(aTHX_ PL_curcop->cop_hints_hash,
264 __PACKAGE__, __PACKAGE_LEN__,
269 return rep_detag(hint);
273 #if PERL_VERSION <= 10
274 Plugin_comp(pTHX_ const SV * const pattern, const U32 flags)
276 Plugin_comp(pTHX_ SV * const pattern, U32 flags)
283 re__engine__Plugin re;
292 if (!h) /* This looks like a pragma leak. Apply the default behaviour */
293 return re_compile(pattern, flags);
295 /* exp/xend version of the pattern & length */
296 pbuf = SvPV((SV*)pattern, plen);
298 /* Our blessed object */
300 SvREFCNT_inc_simple_void_NN(obj);
301 Newxz(re, 1, struct replug);
302 sv_setref_pv(obj, "re::engine::Plugin", (void*)re);
307 re->rx = rx; /* Make the rx accessible from self->rx */
308 rx->intflags = flags; /* Flags for internal use */
309 rx->extflags = flags; /* Flags for perl to use */
310 rx->engine = RE_ENGINE_PLUGIN; /* Compile to use this engine */
312 #if PERL_VERSION <= 10
313 rx->refcnt = 1; /* Refcount so we won't be destroyed */
315 /* Precompiled pattern for pp_regcomp to use */
317 rx->precomp = savepvn(pbuf, rx->prelen);
319 /* Set up qr// stringification to be equivalent to the supplied
320 * pattern, this should be done via overload eventually.
322 rx->wraplen = rx->prelen;
323 Newx(rx->wrapped, rx->wraplen, char);
324 Copy(rx->precomp, rx->wrapped, rx->wraplen, char);
327 /* Store our private object */
330 /* Store the pattern for ->pattern */
331 re->pattern = (SV*)pattern;
332 SvREFCNT_inc_simple_void(re->pattern);
334 /* If there's an exec callback, store it into the private object so
335 * that it will be the one to be called, even if the engine changes
338 re->cb_exec = h->exec;
339 SvREFCNT_inc_simple_void_NN(h->exec);
342 re->cb_num_capture_buff_FETCH = NULL;
343 re->cb_num_capture_buff_STORE = NULL;
344 re->cb_num_capture_buff_LENGTH = NULL;
346 /* Call our callback function if one was defined, if not we've
347 * already set up all the stuff we're going to to need for
348 * subsequent exec and other calls */
357 call_sv(h->comp, G_DISCARD);
363 /* If any of the comp-time accessors were called we'll have to
364 * update the regexp struct with the new info.
367 Newxz(rx->offs, rx->nparens + 1, regexp_paren_pair);
373 Plugin_exec(pTHX_ REGEXP * const RX, char *stringarg, char *strend,
374 char *strbeg, I32 minend, SV *sv, void *data, U32 flags)
378 struct regexp *rx = rxREGEXP(RX);
379 GET_SELF_FROM_PPRIVATE(rx->pprivate);
384 /* Store the current str for ->str */
385 SvREFCNT_dec(self->str);
387 SvREFCNT_inc_simple_void(self->str);
393 XPUSHs(rx->pprivate);
397 call_sv(self->cb_exec, G_SCALAR);
418 Plugin_intuit(pTHX_ REGEXP * const RX, SV *sv, char *strpos,
419 char *strend, U32 flags, re_scream_pos_data *data)
423 PERL_UNUSED_ARG(strpos);
424 PERL_UNUSED_ARG(strend);
425 PERL_UNUSED_ARG(flags);
426 PERL_UNUSED_ARG(data);
431 Plugin_checkstr(pTHX_ REGEXP * const RX)
438 Plugin_free(pTHX_ REGEXP * const RX)
440 struct regexp *rx = rxREGEXP(RX);
441 GET_SELF_FROM_PPRIVATE(rx->pprivate);
443 SvREFCNT_dec(self->pattern);
444 SvREFCNT_dec(self->str);
446 SvREFCNT_dec(self->cb_exec);
448 SvREFCNT_dec(self->cb_num_capture_buff_FETCH);
449 SvREFCNT_dec(self->cb_num_capture_buff_STORE);
450 SvREFCNT_dec(self->cb_num_capture_buff_LENGTH);
459 callback = self->cb_free;
466 XPUSHs(rx->pprivate);
469 call_sv(callback, G_DISCARD);
480 Plugin_dupe(pTHX_ REGEXP * const RX, CLONE_PARAMS *param)
482 struct regexp *rx = rxREGEXP(RX);
483 Perl_croak(aTHX_ "dupe not supported yet");
489 Plugin_numbered_buff_FETCH(pTHX_ REGEXP * const RX, const I32 paren,
495 struct regexp *rx = rxREGEXP(RX);
496 GET_SELF_FROM_PPRIVATE(rx->pprivate);
498 callback = self->cb_num_capture_buff_FETCH;
505 XPUSHs(rx->pprivate);
506 XPUSHs(sv_2mortal(newSViv(paren)));
509 items = call_sv(callback, G_SCALAR);
518 sv_setsv(sv, &PL_sv_undef);
525 sv_setsv(sv, &PL_sv_undef);
530 Plugin_numbered_buff_STORE(pTHX_ REGEXP * const RX, const I32 paren,
531 SV const * const value)
535 struct regexp *rx = rxREGEXP(RX);
536 GET_SELF_FROM_PPRIVATE(rx->pprivate);
538 callback = self->cb_num_capture_buff_STORE;
545 XPUSHs(rx->pprivate);
546 XPUSHs(sv_2mortal(newSViv(paren)));
547 XPUSHs((SV *) value);
550 call_sv(callback, G_DISCARD);
559 Plugin_numbered_buff_LENGTH(pTHX_ REGEXP * const RX, const SV * const sv,
564 struct regexp *rx = rxREGEXP(RX);
565 GET_SELF_FROM_PPRIVATE(rx->pprivate);
567 callback = self->cb_num_capture_buff_LENGTH;
576 XPUSHs(rx->pprivate);
577 XPUSHs(sv_2mortal(newSViv(paren)));
580 call_sv(callback, G_SCALAR);
592 /* TODO: call FETCH and get the length on that value */
599 Plugin_named_buff (pTHX_ REGEXP * const RX, SV * const key, SV * const value,
606 Plugin_named_buff_iter (pTHX_ REGEXP * const RX, const SV * const lastkey,
613 Plugin_package(pTHX_ REGEXP * const RX)
616 return newSVpvs("re::engine::Plugin");
621 STATIC U32 rep_initialized = 0;
623 STATIC void rep_teardown(pTHX_ void *root) {
624 if (!rep_initialized || aTHX != root)
629 ptable_free(MY_CXT.tbl);
635 STATIC void rep_setup(pTHX) {
636 #define rep_setup() rep_setup(aTHX)
642 MY_CXT.tbl = ptable_new();
646 call_atexit(rep_teardown, aTHX);
651 #else /* REP_THREADSAFE */
655 #endif /* !REP_THREADSAFE */
657 STATIC U32 rep_booted = 0;
659 /* --- XS ------------------------------------------------------------------ */
661 MODULE = re::engine::Plugin PACKAGE = re::engine::Plugin
668 PERL_HASH(rep_hash, __PACKAGE__, __PACKAGE_LEN__);
682 rep_ptable_clone_ud ud;
686 rep_ptable_clone_ud_init(ud, t, MY_CXT.owner);
687 ptable_walk(MY_CXT.tbl, rep_ptable_clone, &ud);
688 rep_ptable_clone_ud_deinit(ud);
695 reap(3, rep_thread_cleanup, NULL);
698 #endif /* REP_THREADSAFE */
701 pattern(re::engine::Plugin self, ...)
703 XPUSHs(self->pattern);
706 str(re::engine::Plugin self, ...)
711 mod(re::engine::Plugin self)
717 flags = self->rx->intflags;
718 if (flags & PMf_FOLD) /* /i */
720 if (flags & PMf_MULTILINE) /* /m */
722 if (flags & PMf_SINGLELINE) /* /s */
724 if (flags & PMf_EXTENDED) /* /x */
726 if (flags & RXf_PMf_KEEPCOPY) /* /p */
730 for (i = 0; i < n; ++i) {
737 stash(re::engine::Plugin self, ...)
740 SvREFCNT_dec(self->stash);
742 SvREFCNT_inc_simple_void(self->stash);
749 minlen(re::engine::Plugin self, ...)
752 self->rx->minlen = (I32)SvIV(ST(1));
755 if (self->rx->minlen) {
756 XPUSHs(sv_2mortal(newSViv(self->rx->minlen)));
758 XPUSHs(sv_2mortal(&PL_sv_undef));
763 gofs(re::engine::Plugin self, ...)
766 self->rx->gofs = (U32)SvIV(ST(1));
769 if (self->rx->gofs) {
770 XPUSHs(sv_2mortal(newSVuv(self->rx->gofs)));
772 XPUSHs(sv_2mortal(&PL_sv_undef));
777 nparens(re::engine::Plugin self, ...)
780 self->rx->nparens = (U32)SvIV(ST(1));
783 if (self->rx->nparens) {
784 XPUSHs(sv_2mortal(newSVuv(self->rx->nparens)));
786 XPUSHs(sv_2mortal(&PL_sv_undef));
791 _exec(re::engine::Plugin self, ...)
794 SvREFCNT_dec(self->cb_exec);
795 self->cb_exec = ST(1);
796 SvREFCNT_inc_simple_void(self->cb_exec);
800 _num_capture_buff_FETCH(re::engine::Plugin self, ...)
803 SvREFCNT_dec(self->cb_num_capture_buff_FETCH);
804 self->cb_num_capture_buff_FETCH = ST(1);
805 SvREFCNT_inc_simple_void(self->cb_num_capture_buff_FETCH);
809 _num_capture_buff_STORE(re::engine::Plugin self, ...)
812 SvREFCNT_dec(self->cb_num_capture_buff_STORE);
813 self->cb_num_capture_buff_STORE = ST(1);
814 SvREFCNT_inc_simple_void(self->cb_num_capture_buff_STORE);
818 _num_capture_buff_LENGTH(re::engine::Plugin self, ...)
821 SvREFCNT_dec(self->cb_num_capture_buff_LENGTH);
822 self->cb_num_capture_buff_LENGTH = ST(1);
823 SvREFCNT_inc_simple_void(self->cb_num_capture_buff_LENGTH);
827 _tag(SV *comp, SV *exec)
829 RETVAL = rep_tag(comp, exec);
836 XPUSHs(sv_2mortal(newSViv(PTR2IV(&engine_plugin))));