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
9 /* --- Helpers ------------------------------------------------------------- */
11 #define XSH_PACKAGE "re::engine::Plugin"
16 /* ... Lexical hints ....................................................... */
23 static SV *rep_validate_callback(SV *code) {
28 if (SvTYPE(code) < SVt_PVCV)
31 return SvREFCNT_inc_simple_NN(code);
34 static void xsh_hints_user_init(pTHX_ xsh_hints_user_t *hv, xsh_hints_user_t *v) {
35 hv->comp = rep_validate_callback(v->comp);
36 hv->exec = rep_validate_callback(v->exec);
43 static void xsh_hints_user_clone(pTHX_ xsh_hints_user_t *nv, xsh_hints_user_t *ov, CLONE_PARAMS *params) {
44 nv->comp = xsh_dup_inc(ov->comp, params);
45 nv->exec = xsh_dup_inc(ov->exec, params);
50 #endif /* XSH_THREADSAFE */
52 static void xsh_hints_user_deinit(pTHX_ xsh_hints_user_t *hv) {
53 SvREFCNT_dec(hv->comp);
54 SvREFCNT_dec(hv->exec);
59 #define rep_hint() xsh_hints_detag(xsh_hints_fetch())
61 #define XSH_HINTS_TYPE_USER 1
62 #define XSH_HINTS_ONLY_COMPILE_TIME 0
64 #include "xsh/hints.h"
66 /* ... Thread-local storage ................................................ */
68 #define XSH_THREADS_USER_CONTEXT 0
69 #define XSH_THREADS_USER_LOCAL_SETUP 0
70 #define XSH_THREADS_USER_LOCAL_TEARDOWN 0
71 #define XSH_THREADS_USER_GLOBAL_TEARDOWN 0
72 #define XSH_THREADS_COMPILE_TIME_PROTECTION 0
74 #include "xsh/threads.h"
76 /* --- Custom regexp engine ------------------------------------------------ */
78 /* re__engine__Plugin self; SELF_FROM_PPRIVATE(self,rx->pprivate) */
79 #define SELF_FROM_PPRIVATE(self, pprivate) \
80 if (sv_isobject(pprivate)) { \
81 SV *ref = SvRV((SV *) pprivate); \
82 IV tmp = SvIV((SV *) ref); \
83 self = INT2PTR(re__engine__Plugin, tmp); \
85 Perl_croak(aTHX_ "Not an object"); \
88 #if XSH_HAS_PERL(5, 19, 4)
89 # define REP_ENG_EXEC_MINEND_TYPE SSize_t
91 # define REP_ENG_EXEC_MINEND_TYPE I32
95 EXTERN_C const regexp_engine engine_plugin;
96 #if XSH_HAS_PERL(5, 11, 0)
97 EXTERN_C REGEXP * Plugin_comp(pTHX_ SV * const, U32);
99 EXTERN_C REGEXP * Plugin_comp(pTHX_ const SV * const, const U32);
101 EXTERN_C I32 Plugin_exec(pTHX_ REGEXP * const, char *, char *,
102 char *, REP_ENG_EXEC_MINEND_TYPE, SV *, void *, U32);
103 #if XSH_HAS_PERL(5, 19, 1)
104 EXTERN_C char * Plugin_intuit(pTHX_ REGEXP * const, SV *, const char * const,
105 char *, char *, U32, re_scream_pos_data *);
107 EXTERN_C char * Plugin_intuit(pTHX_ REGEXP * const, SV *, char *,
108 char *, U32, re_scream_pos_data *);
110 EXTERN_C SV * Plugin_checkstr(pTHX_ REGEXP * const);
111 EXTERN_C void Plugin_free(pTHX_ REGEXP * const);
112 EXTERN_C void * Plugin_dupe(pTHX_ REGEXP * const, CLONE_PARAMS *);
113 EXTERN_C void Plugin_numbered_buff_FETCH(pTHX_ REGEXP * const,
114 const I32, SV * const);
115 EXTERN_C void Plugin_numbered_buff_STORE(pTHX_ REGEXP * const,
116 const I32, SV const * const);
117 EXTERN_C I32 Plugin_numbered_buff_LENGTH(pTHX_ REGEXP * const,
118 const SV * const, const I32);
119 EXTERN_C SV * Plugin_named_buff(pTHX_ REGEXP * const, SV * const,
120 SV * const, const U32);
121 EXTERN_C SV * Plugin_named_buff_iter(pTHX_ REGEXP * const, const SV * const,
123 EXTERN_C SV * Plugin_package(pTHX_ REGEXP * const);
125 EXTERN_C void * Plugin_dupe(pTHX_ REGEXP * const, CLONE_PARAMS *);
128 EXTERN_C const regexp_engine engine_plugin;
131 #define RE_ENGINE_PLUGIN (&engine_plugin)
132 const regexp_engine engine_plugin = {
138 Plugin_numbered_buff_FETCH,
139 Plugin_numbered_buff_STORE,
140 Plugin_numbered_buff_LENGTH,
142 Plugin_named_buff_iter,
144 #if defined(USE_ITHREADS)
147 #if XSH_HAS_PERL(5, 17, 0)
152 typedef struct replug {
153 /* Pointer back to the containing regexp struct so that accessors
154 * can modify nparens, gofs, etc... */
157 /* A copy of the pattern given to comp, for ->pattern */
160 /* A copy of the string being matched against, for ->str */
171 SV *cb_num_capture_buff_FETCH;
172 SV *cb_num_capture_buff_STORE;
173 SV *cb_num_capture_buff_LENGTH;
174 } *re__engine__Plugin;
176 #if XSH_HAS_PERL(5, 11, 0)
177 # define rxREGEXP(RX) (SvANY(RX))
178 # define newREGEXP(RX) ((RX) = ((REGEXP *) newSV_type(SVt_REGEXP)))
180 # define rxREGEXP(RX) (RX)
181 # define newREGEXP(RX) (Newxz((RX), 1, struct regexp))
185 #if XSH_HAS_PERL(5, 11, 0)
186 Plugin_comp(pTHX_ SV * const pattern, U32 flags)
188 Plugin_comp(pTHX_ const SV * const pattern, const U32 flags)
195 re__engine__Plugin re;
196 const xsh_hints_user_t *h;
204 if (!h) /* This looks like a pragma leak. Apply the default behaviour */
205 return re_compile(pattern, flags);
207 /* exp/xend version of the pattern & length */
208 pbuf = SvPV((SV *) pattern, plen);
210 /* Our blessed object */
212 SvREFCNT_inc_simple_void_NN(obj);
213 Newxz(re, 1, struct replug);
214 sv_setref_pv(obj, XSH_PACKAGE, (void *) re);
219 re->rx = rx; /* Make the rx accessible from self->rx */
220 rx->intflags = flags; /* Flags for internal use */
221 rx->extflags = flags; /* Flags for perl to use */
222 rx->engine = RE_ENGINE_PLUGIN; /* Compile to use this engine */
224 #if !XSH_HAS_PERL(5, 11, 0)
225 rx->refcnt = 1; /* Refcount so we won't be destroyed */
227 /* Precompiled pattern for pp_regcomp to use */
229 rx->precomp = savepvn(pbuf, rx->prelen);
231 /* Set up qr// stringification to be equivalent to the supplied
232 * pattern, this should be done via overload eventually */
233 rx->wraplen = rx->prelen;
234 Newx(rx->wrapped, rx->wraplen, char);
235 Copy(rx->precomp, rx->wrapped, rx->wraplen, char);
238 /* Store our private object */
241 /* Store the pattern for ->pattern */
242 re->pattern = (SV *) pattern;
243 SvREFCNT_inc_simple_void(re->pattern);
245 /* If there's an exec callback, store it into the private object so that it
246 * will be the one to be called, even if the engine changes in between */
248 re->cb_exec = h->exec;
249 SvREFCNT_inc_simple_void_NN(h->exec);
252 re->cb_num_capture_buff_FETCH = NULL;
253 re->cb_num_capture_buff_STORE = NULL;
254 re->cb_num_capture_buff_LENGTH = NULL;
256 /* Call our callback function if one was defined, if not we've already set up
257 * all the stuff we're going to to need for subsequent exec and other calls */
266 call_sv(h->comp, G_DISCARD);
272 /* If any of the comp-time accessors were called we'll have to
273 * update the regexp struct with the new info */
274 Newxz(rx->offs, rx->nparens + 1, regexp_paren_pair);
280 Plugin_exec(pTHX_ REGEXP * const RX, char *stringarg, char *strend,
281 char *strbeg, REP_ENG_EXEC_MINEND_TYPE minend,
282 SV *sv, void *data, U32 flags)
285 re__engine__Plugin self;
289 SELF_FROM_PPRIVATE(self, rx->pprivate);
295 /* Store the current str for ->str */
296 SvREFCNT_dec(self->str);
298 SvREFCNT_inc_simple_void(self->str);
304 XPUSHs(rx->pprivate);
308 call_sv(self->cb_exec, G_SCALAR);
329 #if XSH_HAS_PERL(5, 19, 1)
330 Plugin_intuit(pTHX_ REGEXP * const RX, SV *sv, const char * const strbeg,
331 char *strpos, char *strend, U32 flags, re_scream_pos_data *data)
333 Plugin_intuit(pTHX_ REGEXP * const RX, SV *sv, char *strpos,
334 char *strend, U32 flags, re_scream_pos_data *data)
339 #if XSH_HAS_PERL(5, 19, 1)
340 PERL_UNUSED_ARG(strbeg);
342 PERL_UNUSED_ARG(strpos);
343 PERL_UNUSED_ARG(strend);
344 PERL_UNUSED_ARG(flags);
345 PERL_UNUSED_ARG(data);
351 Plugin_checkstr(pTHX_ REGEXP * const RX)
359 Plugin_free(pTHX_ REGEXP * const RX)
362 re__engine__Plugin self;
368 SELF_FROM_PPRIVATE(self, rx->pprivate);
370 SvREFCNT_dec(self->pattern);
371 SvREFCNT_dec(self->str);
373 SvREFCNT_dec(self->cb_exec);
375 SvREFCNT_dec(self->cb_num_capture_buff_FETCH);
376 SvREFCNT_dec(self->cb_num_capture_buff_STORE);
377 SvREFCNT_dec(self->cb_num_capture_buff_LENGTH);
386 callback = self->cb_free;
393 XPUSHs(rx->pprivate);
396 call_sv(callback, G_DISCARD);
407 Plugin_dupe(pTHX_ REGEXP * const RX, CLONE_PARAMS *param)
409 struct regexp *rx = rxREGEXP(RX);
411 Perl_croak(aTHX_ "dupe not supported yet");
418 Plugin_numbered_buff_FETCH(pTHX_ REGEXP * const RX, const I32 paren,
422 re__engine__Plugin self;
426 SELF_FROM_PPRIVATE(self, rx->pprivate);
428 callback = self->cb_num_capture_buff_FETCH;
438 XPUSHs(rx->pprivate);
439 XPUSHs(sv_2mortal(newSViv(paren)));
442 items = call_sv(callback, G_SCALAR);
450 sv_setsv(sv, &PL_sv_undef);
457 sv_setsv(sv, &PL_sv_undef);
462 Plugin_numbered_buff_STORE(pTHX_ REGEXP * const RX, const I32 paren,
463 SV const * const value)
466 re__engine__Plugin self;
470 SELF_FROM_PPRIVATE(self, rx->pprivate);
472 callback = self->cb_num_capture_buff_STORE;
481 XPUSHs(rx->pprivate);
482 XPUSHs(sv_2mortal(newSViv(paren)));
483 XPUSHs((SV *) value);
486 call_sv(callback, G_DISCARD);
495 Plugin_numbered_buff_LENGTH(pTHX_ REGEXP * const RX, const SV * const sv,
499 re__engine__Plugin self;
503 SELF_FROM_PPRIVATE(self, rx->pprivate);
505 callback = self->cb_num_capture_buff_LENGTH;
515 XPUSHs(rx->pprivate);
516 XPUSHs(sv_2mortal(newSViv(paren)));
519 call_sv(callback, G_SCALAR);
531 /* TODO: call FETCH and get the length on that value */
537 Plugin_named_buff(pTHX_ REGEXP * const RX, SV * const key, SV * const value,
544 Plugin_named_buff_iter(pTHX_ REGEXP * const RX, const SV * const lastkey,
551 Plugin_package(pTHX_ REGEXP * const RX)
555 return newSVpvs(XSH_PACKAGE);
558 static void xsh_user_global_setup(pTHX) {
561 stash = gv_stashpvn(XSH_PACKAGE, XSH_PACKAGE_LEN, 1);
562 newCONSTSUB(stash, "REP_THREADSAFE", newSVuv(XSH_THREADSAFE));
563 newCONSTSUB(stash, "REP_FORKSAFE", newSVuv(XSH_FORKSAFE));
568 /* --- XS ------------------------------------------------------------------ */
570 MODULE = re::engine::Plugin PACKAGE = re::engine::Plugin
587 #endif /* XSH_THREADSAFE */
590 pattern(re::engine::Plugin self, ...)
592 XPUSHs(self->pattern);
596 str(re::engine::Plugin self, ...)
602 mod(re::engine::Plugin self)
608 flags = self->rx->intflags;
609 if (flags & PMf_FOLD) /* /i */
611 if (flags & PMf_MULTILINE) /* /m */
613 if (flags & PMf_SINGLELINE) /* /s */
615 if (flags & PMf_EXTENDED) /* /x */
617 if (flags & RXf_PMf_KEEPCOPY) /* /p */
621 for (i = 0; i < n; ++i) {
628 stash(re::engine::Plugin self, ...)
631 SvREFCNT_dec(self->stash);
633 SvREFCNT_inc_simple_void(self->stash);
641 minlen(re::engine::Plugin self, ...)
644 self->rx->minlen = (I32)SvIV(ST(1));
647 if (self->rx->minlen) {
648 XPUSHs(sv_2mortal(newSViv(self->rx->minlen)));
650 XPUSHs(sv_2mortal(&PL_sv_undef));
656 gofs(re::engine::Plugin self, ...)
659 self->rx->gofs = (U32)SvIV(ST(1));
662 if (self->rx->gofs) {
663 XPUSHs(sv_2mortal(newSVuv(self->rx->gofs)));
665 XPUSHs(sv_2mortal(&PL_sv_undef));
671 nparens(re::engine::Plugin self, ...)
674 self->rx->nparens = (U32)SvIV(ST(1));
677 if (self->rx->nparens) {
678 XPUSHs(sv_2mortal(newSVuv(self->rx->nparens)));
680 XPUSHs(sv_2mortal(&PL_sv_undef));
686 _exec(re::engine::Plugin self, ...)
689 SvREFCNT_dec(self->cb_exec);
690 self->cb_exec = ST(1);
691 SvREFCNT_inc_simple_void(self->cb_exec);
696 _num_capture_buff_FETCH(re::engine::Plugin self, ...)
699 SvREFCNT_dec(self->cb_num_capture_buff_FETCH);
700 self->cb_num_capture_buff_FETCH = ST(1);
701 SvREFCNT_inc_simple_void(self->cb_num_capture_buff_FETCH);
706 _num_capture_buff_STORE(re::engine::Plugin self, ...)
709 SvREFCNT_dec(self->cb_num_capture_buff_STORE);
710 self->cb_num_capture_buff_STORE = ST(1);
711 SvREFCNT_inc_simple_void(self->cb_num_capture_buff_STORE);
716 _num_capture_buff_LENGTH(re::engine::Plugin self, ...)
719 SvREFCNT_dec(self->cb_num_capture_buff_LENGTH);
720 self->cb_num_capture_buff_LENGTH = ST(1);
721 SvREFCNT_inc_simple_void(self->cb_num_capture_buff_LENGTH);
726 _tag(SV *comp, SV *exec)
728 xsh_hints_user_t arg;
732 RETVAL = xsh_hints_tag(&arg);
739 XPUSHs(sv_2mortal(newSViv(PTR2IV(&engine_plugin))));