typedef struct {
SV *comp;
SV *exec;
+ SV *free;
} xsh_hints_user_t;
static SV *rep_validate_callback(SV *code) {
static void xsh_hints_user_init(pTHX_ xsh_hints_user_t *hv, xsh_hints_user_t *v) {
hv->comp = rep_validate_callback(v->comp);
hv->exec = rep_validate_callback(v->exec);
+ hv->free = rep_validate_callback(v->free);
return;
}
static void xsh_hints_user_clone(pTHX_ xsh_hints_user_t *nv, xsh_hints_user_t *ov, CLONE_PARAMS *params) {
nv->comp = xsh_dup_inc(ov->comp, params);
nv->exec = xsh_dup_inc(ov->exec, params);
+ nv->free = xsh_dup_inc(ov->free, params);
return;
}
static void xsh_hints_user_deinit(pTHX_ xsh_hints_user_t *hv) {
SvREFCNT_dec(hv->comp);
SvREFCNT_dec(hv->exec);
+ SvREFCNT_dec(hv->free);
return;
}
/* --- Custom regexp engine ------------------------------------------------ */
-#define GET_SELF_FROM_PPRIVATE(pprivate) \
- re__engine__Plugin self; \
- SELF_FROM_PPRIVATE(self,pprivate);
-
/* re__engine__Plugin self; SELF_FROM_PPRIVATE(self,rx->pprivate) */
#define SELF_FROM_PPRIVATE(self, pprivate) \
if (sv_isobject(pprivate)) { \
Plugin_comp(pTHX_ const SV * const pattern, const U32 flags)
#endif
{
- dSP;
- struct regexp *rx;
- REGEXP *RX;
-
- re__engine__Plugin re;
const xsh_hints_user_t *h;
-
+ REGEXP *RX;
+ struct regexp *rx;
+ re__engine__Plugin re;
+ char *pbuf;
STRLEN plen;
- char *pbuf;
-
- SV *obj;
+ SV *obj;
h = rep_hint();
if (!h) /* This looks like a pragma leak. Apply the default behaviour */
/* Our blessed object */
obj = newSV(0);
- SvREFCNT_inc_simple_void_NN(obj);
- Newxz(re, 1, struct replug);
- sv_setref_pv(obj, "re::engine::Plugin", (void *) re);
+ XSH_LOCAL_ALLOC(re, 1, struct replug);
+ sv_setref_pv(obj, XSH_PACKAGE, (void *) re);
newREGEXP(RX);
rx = rxREGEXP(RX);
re->pattern = (SV *) pattern;
SvREFCNT_inc_simple_void(re->pattern);
- /* If there's an exec callback, store it into the private object so that it
- * will be the one to be called, even if the engine changes in between */
- if (h->exec) {
- re->cb_exec = h->exec;
- SvREFCNT_inc_simple_void_NN(h->exec);
- }
+ re->str = NULL;
+ re->stash = NULL;
+
+ /* Store the default exec callback (which may be NULL) into the regexp
+ * object. */
+ re->cb_exec = h->exec;
+ SvREFCNT_inc_simple_void(h->exec);
+
+ /* Same goes for the free callback. */
+ re->cb_free = h->free;
+ SvREFCNT_inc_simple_void(h->free);
re->cb_num_capture_buff_FETCH = NULL;
re->cb_num_capture_buff_STORE = NULL;
/* Call our callback function if one was defined, if not we've already set up
* all the stuff we're going to to need for subsequent exec and other calls */
if (h->comp) {
+ dSP;
+
ENTER;
SAVETMPS;
char *strbeg, REP_ENG_EXEC_MINEND_TYPE minend,
SV *sv, void *data, U32 flags)
{
- dSP;
+ struct regexp *rx;
+ re__engine__Plugin self;
I32 matched;
- struct regexp *rx = rxREGEXP(RX);
- GET_SELF_FROM_PPRIVATE(rx->pprivate);
+ rx = rxREGEXP(RX);
+ SELF_FROM_PPRIVATE(self, rx->pprivate);
if (self->cb_exec) {
SV *ret;
+ dSP;
/* Store the current str for ->str */
SvREFCNT_dec(self->str);
void
Plugin_free(pTHX_ REGEXP * const RX)
{
- struct regexp *rx;
+ struct regexp *rx;
re__engine__Plugin self;
+ SV *callback;
if (PL_dirty)
return;
rx = rxREGEXP(RX);
SELF_FROM_PPRIVATE(self, rx->pprivate);
- SvREFCNT_dec(self->pattern);
- SvREFCNT_dec(self->str);
-
- SvREFCNT_dec(self->cb_exec);
-
- SvREFCNT_dec(self->cb_num_capture_buff_FETCH);
- SvREFCNT_dec(self->cb_num_capture_buff_STORE);
- SvREFCNT_dec(self->cb_num_capture_buff_LENGTH);
-
- self->rx = NULL;
- Safefree(self);
-
-/*
- dSP;
- SV *callback;
-
callback = self->cb_free;
if (callback) {
+ dSP;
+
ENTER;
SAVETMPS;
FREETMPS;
LEAVE;
}
+
+ SvREFCNT_dec(self->pattern);
+ SvREFCNT_dec(self->str);
+ SvREFCNT_dec(self->stash);
+
+ SvREFCNT_dec(self->cb_exec);
+
+ SvREFCNT_dec(self->cb_num_capture_buff_FETCH);
+ SvREFCNT_dec(self->cb_num_capture_buff_STORE);
+ SvREFCNT_dec(self->cb_num_capture_buff_LENGTH);
+
+ self->rx = NULL;
+
+ XSH_LOCAL_FREE(self, 1, struct replug);
+
+ SvREFCNT_dec(rx->pprivate);
+
return;
-*/
}
void *
Plugin_numbered_buff_FETCH(pTHX_ REGEXP * const RX, const I32 paren,
SV * const sv)
{
- dSP;
- I32 items;
+ struct regexp *rx;
+ re__engine__Plugin self;
SV *callback;
- struct regexp *rx = rxREGEXP(RX);
- GET_SELF_FROM_PPRIVATE(rx->pprivate);
+ rx = rxREGEXP(RX);
+ SELF_FROM_PPRIVATE(self, rx->pprivate);
callback = self->cb_num_capture_buff_FETCH;
if (callback) {
+ I32 items;
+ dSP;
+
ENTER;
SAVETMPS;
PUSHMARK(SP);
XPUSHs(rx->pprivate);
- XPUSHs(sv_2mortal(newSViv(paren)));
+ mXPUSHi(paren);
PUTBACK;
items = call_sv(callback, G_SCALAR);
Plugin_numbered_buff_STORE(pTHX_ REGEXP * const RX, const I32 paren,
SV const * const value)
{
- dSP;
+ struct regexp *rx;
+ re__engine__Plugin self;
SV *callback;
- struct regexp *rx = rxREGEXP(RX);
- GET_SELF_FROM_PPRIVATE(rx->pprivate);
+ rx = rxREGEXP(RX);
+ SELF_FROM_PPRIVATE(self, rx->pprivate);
callback = self->cb_num_capture_buff_STORE;
if (callback) {
+ dSP;
+
ENTER;
SAVETMPS;
PUSHMARK(SP);
XPUSHs(rx->pprivate);
- XPUSHs(sv_2mortal(newSViv(paren)));
+ mXPUSHi(paren);
XPUSHs((SV *) value);
PUTBACK;
Plugin_numbered_buff_LENGTH(pTHX_ REGEXP * const RX, const SV * const sv,
const I32 paren)
{
- dSP;
+ struct regexp *rx;
+ re__engine__Plugin self;
SV *callback;
- struct regexp *rx = rxREGEXP(RX);
- GET_SELF_FROM_PPRIVATE(rx->pprivate);
+ rx = rxREGEXP(RX);
+ SELF_FROM_PPRIVATE(self, rx->pprivate);
callback = self->cb_num_capture_buff_LENGTH;
if (callback) {
IV ret;
+ dSP;
ENTER;
SAVETMPS;
PUSHMARK(SP);
XPUSHs(rx->pprivate);
- XPUSHs(sv_2mortal(newSViv(paren)));
+ mXPUSHi(paren);
PUTBACK;
call_sv(callback, G_SCALAR);
{
PERL_UNUSED_ARG(RX);
- return newSVpvs("re::engine::Plugin");
+ return newSVpvs(XSH_PACKAGE);
}
static void xsh_user_global_setup(pTHX) {
pattern(re::engine::Plugin self, ...)
PPCODE:
XPUSHs(self->pattern);
+ XSRETURN(1);
void
str(re::engine::Plugin self, ...)
PPCODE:
XPUSHs(self->str);
+ XSRETURN(1);
void
mod(re::engine::Plugin self)
XSRETURN_EMPTY;
} else {
XPUSHs(self->stash);
+ XSRETURN(1);
}
void
if (items > 1) {
self->rx->minlen = (I32)SvIV(ST(1));
XSRETURN_EMPTY;
+ } else if (self->rx->minlen) {
+ mXPUSHi(self->rx->minlen);
+ XSRETURN(1);
} else {
- if (self->rx->minlen) {
- XPUSHs(sv_2mortal(newSViv(self->rx->minlen)));
- } else {
- XPUSHs(sv_2mortal(&PL_sv_undef));
- }
+ XSRETURN_UNDEF;
}
void
if (items > 1) {
self->rx->gofs = (U32)SvIV(ST(1));
XSRETURN_EMPTY;
+ } else if (self->rx->gofs) {
+ mXPUSHu(self->rx->gofs);
+ XSRETURN(1);
} else {
- if (self->rx->gofs) {
- XPUSHs(sv_2mortal(newSVuv(self->rx->gofs)));
- } else {
- XPUSHs(sv_2mortal(&PL_sv_undef));
- }
+ XSRETURN_UNDEF;
}
void
if (items > 1) {
self->rx->nparens = (U32)SvIV(ST(1));
XSRETURN_EMPTY;
+ } else if (self->rx->nparens) {
+ mXPUSHu(self->rx->nparens);
+ XSRETURN(1);
} else {
- if (self->rx->nparens) {
- XPUSHs(sv_2mortal(newSVuv(self->rx->nparens)));
- } else {
- XPUSHs(sv_2mortal(&PL_sv_undef));
- }
+ XSRETURN_UNDEF;
}
void
self->cb_exec = ST(1);
SvREFCNT_inc_simple_void(self->cb_exec);
}
+ XSRETURN(0);
+
+void
+_free(re::engine::Plugin self, ...)
+PPCODE:
+ if (items > 1) {
+ SvREFCNT_dec(self->cb_free);
+ self->cb_free = ST(1);
+ SvREFCNT_inc_simple_void(self->cb_free);
+ }
+ XSRETURN(0);
void
_num_capture_buff_FETCH(re::engine::Plugin self, ...)
self->cb_num_capture_buff_FETCH = ST(1);
SvREFCNT_inc_simple_void(self->cb_num_capture_buff_FETCH);
}
+ XSRETURN(0);
void
_num_capture_buff_STORE(re::engine::Plugin self, ...)
self->cb_num_capture_buff_STORE = ST(1);
SvREFCNT_inc_simple_void(self->cb_num_capture_buff_STORE);
}
+ XSRETURN(0);
void
_num_capture_buff_LENGTH(re::engine::Plugin self, ...)
self->cb_num_capture_buff_LENGTH = ST(1);
SvREFCNT_inc_simple_void(self->cb_num_capture_buff_LENGTH);
}
+ XSRETURN(0);
SV *
-_tag(SV *comp, SV *exec)
+_tag(SV *comp, SV *exec, SV *free)
PREINIT:
xsh_hints_user_t arg;
CODE:
arg.comp = comp;
arg.exec = exec;
+ arg.free = free;
RETVAL = xsh_hints_tag(&arg);
OUTPUT:
RETVAL
void
ENGINE()
PPCODE:
- XPUSHs(sv_2mortal(newSViv(PTR2IV(&engine_plugin))));
+ mXPUSHi(PTR2IV(&engine_plugin));
+ XSRETURN(1);