X-Git-Url: http://git.vpit.fr/?a=blobdiff_plain;f=Plugin.xs;h=cc90e2b16d5c559aa9e4accf95c1c9c3a84ee019;hb=ba92a5781ed7ee39a62fb0490e291a52b97e69a9;hp=07a5d259d0854c66e7ddaee7e842630f53975642;hpb=5496a5f466ffb76891996678f464fb48428a28c3;p=perl%2Fmodules%2Fre-engine-Plugin.git diff --git a/Plugin.xs b/Plugin.xs index 07a5d25..cc90e2b 100644 --- a/Plugin.xs +++ b/Plugin.xs @@ -6,266 +6,214 @@ #include "perl.h" #include "XSUB.h" -#include "Plugin.h" - -#define __PACKAGE__ "re::engine::Plugin" -#define __PACKAGE_LEN__ (sizeof(__PACKAGE__)-1) - -#define REP_HAS_PERL(R, V, S) (PERL_REVISION > (R) || (PERL_REVISION == (R) && (PERL_VERSION > (V) || (PERL_VERSION == (V) && (PERL_SUBVERSION >= (S)))))) - -#ifndef REP_WORKAROUND_REQUIRE_PROPAGATION -# define REP_WORKAROUND_REQUIRE_PROPAGATION !REP_HAS_PERL(5, 10, 1) -#endif - -/* ... Thread safety and multiplicity ...................................... */ - -#ifndef REP_MULTIPLICITY -# if defined(MULTIPLICITY) || defined(PERL_IMPLICIT_CONTEXT) -# define REP_MULTIPLICITY 1 -# else -# define REP_MULTIPLICITY 0 -# endif -#endif -#if REP_MULTIPLICITY && !defined(tTHX) -# define tTHX PerlInterpreter* -#endif +/* --- Helpers ------------------------------------------------------------- */ -#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)) -# define REP_THREADSAFE 1 -# ifndef MY_CXT_CLONE -# define MY_CXT_CLONE \ - dMY_CXT_SV; \ - my_cxt_t *my_cxtp = (my_cxt_t*)SvPVX(newSV(sizeof(my_cxt_t)-1)); \ - Copy(INT2PTR(my_cxt_t*, SvUV(my_cxt_sv)), my_cxtp, 1, my_cxt_t); \ - sv_setuv(my_cxt_sv, PTR2UV(my_cxtp)) -# endif -#else -# define REP_THREADSAFE 0 -# undef dMY_CXT -# define dMY_CXT dNOOP -# undef MY_CXT -# define MY_CXT rep_globaldata -# undef START_MY_CXT -# define START_MY_CXT STATIC my_cxt_t MY_CXT; -# undef MY_CXT_INIT -# define MY_CXT_INIT NOOP -# undef MY_CXT_CLONE -# define MY_CXT_CLONE NOOP -#endif +#define XSH_PACKAGE "re::engine::Plugin" -/* --- Helpers ------------------------------------------------------------- */ +#include "xsh/caps.h" +#include "xsh/util.h" -/* ... Thread-safe hints ................................................... */ +/* ... Lexical hints ....................................................... */ typedef struct { SV *comp; SV *exec; -#if REP_WORKAROUND_REQUIRE_PROPAGATION - IV cxreq; -#endif -} rep_hint_t; - -#if REP_THREADSAFE - -#define PTABLE_VAL_FREE(V) { \ - rep_hint_t *h = (V); \ - SvREFCNT_dec(h->comp); \ - SvREFCNT_dec(h->exec); \ - PerlMemShared_free(h); \ -} - -#define pPTBL pTHX -#define pPTBL_ pTHX_ -#define aPTBL aTHX -#define aPTBL_ aTHX_ - -#include "ptable.h" - -#define ptable_store(T, K, V) ptable_store(aTHX_ (T), (K), (V)) -#define ptable_free(T) ptable_free(aTHX_ (T)) +} xsh_hints_user_t; -#define MY_CXT_KEY __PACKAGE__ "::_guts" XS_VERSION - -typedef struct { - ptable *tbl; - tTHX owner; -} my_cxt_t; +static SV *rep_validate_callback(SV *code) { + if (!SvROK(code)) + return NULL; -START_MY_CXT + code = SvRV(code); + if (SvTYPE(code) < SVt_PVCV) + return NULL; -STATIC SV *rep_clone(pTHX_ SV *sv, tTHX owner) { -#define rep_clone(S, O) rep_clone(aTHX_ (S), (O)) - CLONE_PARAMS param; - AV *stashes = NULL; - SV *dupsv; + return SvREFCNT_inc_simple_NN(code); +} - if (SvTYPE(sv) == SVt_PVHV && HvNAME_get(sv)) - stashes = newAV(); +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); - param.stashes = stashes; - param.flags = 0; - param.proto_perl = owner; + return; +} - dupsv = sv_dup(sv, ¶m); +#if XSH_THREADSAFE - if (stashes) { - av_undef(stashes); - SvREFCNT_dec(stashes); - } +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); - return SvREFCNT_inc(dupsv); + return; } -STATIC void rep_ptable_clone(pTHX_ ptable_ent *ent, void *ud_) { - my_cxt_t *ud = ud_; - rep_hint_t *h1 = ent->val; - rep_hint_t *h2; - - if (ud->owner == aTHX) - return; - - h2 = PerlMemShared_malloc(sizeof *h2); - h2->comp = rep_clone(h1->comp, ud->owner); - SvREFCNT_inc(h2->comp); - h2->exec = rep_clone(h1->exec, ud->owner); - SvREFCNT_inc(h2->exec); -#if REP_WORKAROUND_REQUIRE_PROPAGATION - h2->cxreq = h1->cxreq; -#endif +#endif /* XSH_THREADSAFE */ - ptable_store(ud->tbl, ent->key, h2); +static void xsh_hints_user_deinit(pTHX_ xsh_hints_user_t *hv) { + SvREFCNT_dec(hv->comp); + SvREFCNT_dec(hv->exec); + + return; } -#include "reap.h" +#define rep_hint() xsh_hints_detag(xsh_hints_fetch()) -STATIC void rep_thread_cleanup(pTHX_ void *ud) { - dMY_CXT; +#define XSH_HINTS_TYPE_USER 1 +#define XSH_HINTS_ONLY_COMPILE_TIME 0 - ptable_free(MY_CXT.tbl); -} +#include "xsh/hints.h" -#endif /* REP_THREADSAFE */ +/* ... Thread-local storage ................................................ */ -STATIC SV *rep_validate_callback(SV *code) { - if (!SvROK(code)) - return NULL; +#define XSH_THREADS_USER_CONTEXT 0 +#define XSH_THREADS_USER_LOCAL_SETUP 0 +#define XSH_THREADS_USER_LOCAL_TEARDOWN 0 +#define XSH_THREADS_USER_GLOBAL_TEARDOWN 0 +#define XSH_THREADS_COMPILE_TIME_PROTECTION 0 - code = SvRV(code); - if (SvTYPE(code) < SVt_PVCV) - return NULL; +#include "xsh/threads.h" - return SvREFCNT_inc_simple_NN(code); -} - -#if REP_WORKAROUND_REQUIRE_PROPAGATION -STATIC IV rep_require_tag(pTHX) { -#define rep_require_tag() rep_require_tag(aTHX) - const PERL_SI *si; +/* --- Custom regexp engine ------------------------------------------------ */ - for (si = PL_curstackinfo; si; si = si->si_prev) { - I32 cxix; +#define GET_SELF_FROM_PPRIVATE(pprivate) \ + re__engine__Plugin self; \ + SELF_FROM_PPRIVATE(self,pprivate); - for (cxix = si->si_cxix; cxix >= 0; --cxix) { - const PERL_CONTEXT *cx = si->si_cxstack + cxix; +/* re__engine__Plugin self; SELF_FROM_PPRIVATE(self,rx->pprivate) */ +#define SELF_FROM_PPRIVATE(self, pprivate) \ + if (sv_isobject(pprivate)) { \ + SV * ref = SvRV((SV*)pprivate); \ + IV tmp = SvIV((SV*)ref); \ + self = INT2PTR(re__engine__Plugin,tmp); \ + } else { \ + Perl_croak(aTHX_ "Not an object"); \ + } - if (CxTYPE(cx) == CXt_EVAL && cx->blk_eval.old_op_type == OP_REQUIRE) - return PTR2IV(cx); - } - } +#if XSH_HAS_PERL(5, 19, 4) +# define REP_ENG_EXEC_MINEND_TYPE SSize_t +#else +# define REP_ENG_EXEC_MINEND_TYPE I32 +#endif - return PTR2IV(NULL); -} -#endif /* REP_WORKAROUND_REQUIRE_PROPAGATION */ - -STATIC SV *rep_tag(pTHX_ SV *comp, SV *exec) { -#define rep_tag(C, E) rep_tag(aTHX_ (C), (E)) - rep_hint_t *h; - dMY_CXT; - - h = PerlMemShared_malloc(sizeof *h); - h->comp = rep_validate_callback(comp); - h->exec = rep_validate_callback(exec); -#if REP_WORKAROUND_REQUIRE_PROPAGATION - h->cxreq = rep_require_tag(); -#endif /* REP_WORKAROUND_REQUIRE_PROPAGATION */ - -#if REP_THREADSAFE - /* We only need for the key to be an unique tag for looking up the value later. - * Allocated memory provides convenient unique identifiers, so that's why we - * use the hint as the key itself. */ - ptable_store(MY_CXT.tbl, h, h); -#endif /* REP_THREADSAFE */ - - return newSViv(PTR2IV(h)); -} +START_EXTERN_C +EXTERN_C const regexp_engine engine_plugin; +#if XSH_HAS_PERL(5, 11, 0) +EXTERN_C REGEXP * Plugin_comp(pTHX_ SV * const, U32); +#else +EXTERN_C REGEXP * Plugin_comp(pTHX_ const SV * const, const U32); +#endif +EXTERN_C I32 Plugin_exec(pTHX_ REGEXP * const, char *, char *, + char *, REP_ENG_EXEC_MINEND_TYPE, SV *, void *, U32); +#if XSH_HAS_PERL(5, 19, 1) +EXTERN_C char * Plugin_intuit(pTHX_ REGEXP * const, SV *, const char * const, + char *, char *, U32, re_scream_pos_data *); +#else +EXTERN_C char * Plugin_intuit(pTHX_ REGEXP * const, SV *, char *, + char *, U32, re_scream_pos_data *); +#endif +EXTERN_C SV * Plugin_checkstr(pTHX_ REGEXP * const); +EXTERN_C void Plugin_free(pTHX_ REGEXP * const); +EXTERN_C void * Plugin_dupe(pTHX_ REGEXP * const, CLONE_PARAMS *); +EXTERN_C void Plugin_numbered_buff_FETCH(pTHX_ REGEXP * const, + const I32, SV * const); +EXTERN_C void Plugin_numbered_buff_STORE(pTHX_ REGEXP * const, + const I32, SV const * const); +EXTERN_C I32 Plugin_numbered_buff_LENGTH(pTHX_ REGEXP * const, + const SV * const, const I32); +EXTERN_C SV * Plugin_named_buff (pTHX_ REGEXP * const, SV * const, + SV * const, const U32); +EXTERN_C SV * Plugin_named_buff_iter (pTHX_ REGEXP * const, const SV * const, + const U32); +EXTERN_C SV * Plugin_package(pTHX_ REGEXP * const); +#ifdef USE_ITHREADS +EXTERN_C void * Plugin_dupe(pTHX_ REGEXP * const, CLONE_PARAMS *); +#endif -STATIC const rep_hint_t *rep_detag(pTHX_ const SV *hint) { -#define rep_detag(H) rep_detag(aTHX_ (H)) - rep_hint_t *h; - dMY_CXT; +EXTERN_C const regexp_engine engine_plugin; +END_EXTERN_C + +#define RE_ENGINE_PLUGIN (&engine_plugin) +const regexp_engine engine_plugin = { + Plugin_comp, + Plugin_exec, + Plugin_intuit, + Plugin_checkstr, + Plugin_free, + Plugin_numbered_buff_FETCH, + Plugin_numbered_buff_STORE, + Plugin_numbered_buff_LENGTH, + Plugin_named_buff, + Plugin_named_buff_iter, + Plugin_package +#if defined(USE_ITHREADS) + , Plugin_dupe +#endif +#if XSH_HAS_PERL(5, 17, 0) + , 0 +#endif +}; - if (!(hint && SvIOK(hint))) - return NULL; +typedef struct replug { + /* Pointer back to the containing regexp struct so that accessors + * can modify nparens, gofs etc. */ + struct regexp * rx; - h = INT2PTR(rep_hint_t *, SvIVX(hint)); -#if REP_THREADSAFE - h = ptable_fetch(MY_CXT.tbl, h); -#endif /* REP_THREADSAFE */ + /* A copy of the pattern given to comp, for ->pattern */ + SV * pattern; -#if REP_WORKAROUND_REQUIRE_PROPAGATION - if (rep_require_tag() != h->cxreq) - return NULL; -#endif /* REP_WORKAROUND_REQUIRE_PROPAGATION */ + /* A copy of the string being matched against, for ->str */ + SV * str; - return h; -} + /* The ->stash */ + SV * stash; -STATIC U32 rep_hash = 0; + /* Callbacks */ + SV * cb_exec; + SV * cb_free; -STATIC const rep_hint_t *rep_hint(pTHX) { -#define rep_hint() rep_hint(aTHX) - SV *hint; + /* ->num_captures */ + SV * cb_num_capture_buff_FETCH; + SV * cb_num_capture_buff_STORE; + SV * cb_num_capture_buff_LENGTH; +} *re__engine__Plugin; -#ifdef cop_hints_fetch_pvn - hint = cop_hints_fetch_pvn(PL_curcop, - __PACKAGE__, __PACKAGE_LEN__, rep_hash, 0); +#if XSH_HAS_PERL(5, 11, 0) +# define rxREGEXP(RX) (SvANY(RX)) +# define newREGEXP(RX) ((RX) = ((REGEXP*) newSV_type(SVt_REGEXP))) #else - /* We already require 5.9.5 for the regexp engine API. */ - hint = Perl_refcounted_he_fetch(aTHX_ PL_curcop->cop_hints_hash, - NULL, - __PACKAGE__, __PACKAGE_LEN__, - 0, - rep_hash); +# define rxREGEXP(RX) (RX) +# define newREGEXP(RX) (Newxz((RX), 1, struct regexp)) #endif - return rep_detag(hint); -} - REGEXP * -#if PERL_VERSION <= 10 -Plugin_comp(pTHX_ const SV * const pattern, const U32 flags) -#else +#if XSH_HAS_PERL(5, 11, 0) Plugin_comp(pTHX_ SV * const pattern, U32 flags) +#else +Plugin_comp(pTHX_ const SV * const pattern, const U32 flags) #endif { dSP; struct regexp * rx; REGEXP *RX; - I32 buffers; + re__engine__Plugin re; - const rep_hint_t *h; + const xsh_hints_user_t *h; + + STRLEN plen; + char *pbuf; + + SV *obj; h = rep_hint(); if (!h) /* This looks like a pragma leak. Apply the default behaviour */ return re_compile(pattern, flags); /* exp/xend version of the pattern & length */ - STRLEN plen; - char* exp = SvPV((SV*)pattern, plen); + pbuf = SvPV((SV*)pattern, plen); /* Our blessed object */ - SV *obj = newSV(0); - SvREFCNT_inc(obj); + obj = newSV(0); + SvREFCNT_inc_simple_void_NN(obj); Newxz(re, 1, struct replug); sv_setref_pv(obj, "re::engine::Plugin", (void*)re); @@ -277,12 +225,12 @@ Plugin_comp(pTHX_ SV * const pattern, U32 flags) rx->extflags = flags; /* Flags for perl to use */ rx->engine = RE_ENGINE_PLUGIN; /* Compile to use this engine */ -#if PERL_VERSION <= 10 +#if !XSH_HAS_PERL(5, 11, 0) rx->refcnt = 1; /* Refcount so we won't be destroyed */ /* Precompiled pattern for pp_regcomp to use */ rx->prelen = plen; - rx->precomp = savepvn(exp, rx->prelen); + rx->precomp = savepvn(pbuf, rx->prelen); /* Set up qr// stringification to be equivalent to the supplied * pattern, this should be done via overload eventually. @@ -297,7 +245,7 @@ Plugin_comp(pTHX_ SV * const pattern, U32 flags) /* Store the pattern for ->pattern */ re->pattern = (SV*)pattern; - SvREFCNT_inc(re->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 @@ -315,9 +263,9 @@ Plugin_comp(pTHX_ SV * const pattern, U32 flags) * already set up all the stuff we're going to to need for * subsequent exec and other calls */ if (h->comp) { - ENTER; + ENTER; SAVETMPS; - + PUSHMARK(SP); XPUSHs(obj); PUTBACK; @@ -332,16 +280,15 @@ Plugin_comp(pTHX_ SV * const pattern, U32 flags) * update the regexp struct with the new info. */ - buffers = rx->nparens; - - Newxz(rx->offs, buffers + 1, regexp_paren_pair); + Newxz(rx->offs, rx->nparens + 1, regexp_paren_pair); return RX; } I32 Plugin_exec(pTHX_ REGEXP * const RX, char *stringarg, char *strend, - char *strbeg, I32 minend, SV *sv, void *data, U32 flags) + char *strbeg, REP_ENG_EXEC_MINEND_TYPE minend, + SV *sv, void *data, U32 flags) { dSP; I32 matched; @@ -349,24 +296,26 @@ Plugin_exec(pTHX_ REGEXP * const RX, char *stringarg, char *strend, GET_SELF_FROM_PPRIVATE(rx->pprivate); if (self->cb_exec) { + SV *ret; + /* Store the current str for ->str */ - self->str = (SV*)sv; - SvREFCNT_inc(self->str); + SvREFCNT_dec(self->str); + self->str = sv; + SvREFCNT_inc_simple_void(self->str); ENTER; SAVETMPS; - + PUSHMARK(SP); XPUSHs(rx->pprivate); XPUSHs(sv); PUTBACK; call_sv(self->cb_exec, G_SCALAR); - - SPAGAIN; - SV * ret = POPs; + SPAGAIN; + ret = POPs; if (SvTRUE(ret)) matched = 1; else @@ -383,11 +332,19 @@ Plugin_exec(pTHX_ REGEXP * const RX, char *stringarg, char *strend, } char * +#if XSH_HAS_PERL(5, 19, 1) +Plugin_intuit(pTHX_ REGEXP * const RX, SV *sv, const char * const strbeg, + char *strpos, char *strend, U32 flags, re_scream_pos_data *data) +#else Plugin_intuit(pTHX_ REGEXP * const RX, SV *sv, char *strpos, - char *strend, U32 flags, re_scream_pos_data *data) + char *strend, U32 flags, re_scream_pos_data *data) +#endif { PERL_UNUSED_ARG(RX); PERL_UNUSED_ARG(sv); +#if XSH_HAS_PERL(5, 19, 1) + PERL_UNUSED_ARG(strbeg); +#endif PERL_UNUSED_ARG(strpos); PERL_UNUSED_ARG(strend); PERL_UNUSED_ARG(flags); @@ -405,8 +362,14 @@ Plugin_checkstr(pTHX_ REGEXP * const RX) void Plugin_free(pTHX_ REGEXP * const RX) { - struct regexp *rx = rxREGEXP(RX); - GET_SELF_FROM_PPRIVATE(rx->pprivate); + struct regexp *rx; + re__engine__Plugin self; + + if (PL_dirty) + return; + + rx = rxREGEXP(RX); + SELF_FROM_PPRIVATE(self, rx->pprivate); SvREFCNT_dec(self->pattern); SvREFCNT_dec(self->str); @@ -429,7 +392,7 @@ Plugin_free(pTHX_ REGEXP * const RX) if (callback) { ENTER; SAVETMPS; - + PUSHMARK(SP); XPUSHs(rx->pprivate); PUTBACK; @@ -468,18 +431,19 @@ Plugin_numbered_buff_FETCH(pTHX_ REGEXP * const RX, const I32 paren, if (callback) { ENTER; SAVETMPS; - + PUSHMARK(SP); XPUSHs(rx->pprivate); XPUSHs(sv_2mortal(newSViv(paren))); PUTBACK; items = call_sv(callback, G_SCALAR); - + if (items == 1) { - SPAGAIN; + SV *ret; - SV * ret = POPs; + SPAGAIN; + ret = POPs; sv_setsv(sv, ret); } else { sv_setsv(sv, &PL_sv_undef); @@ -507,11 +471,11 @@ Plugin_numbered_buff_STORE(pTHX_ REGEXP * const RX, const I32 paren, if (callback) { ENTER; SAVETMPS; - + PUSHMARK(SP); XPUSHs(rx->pprivate); XPUSHs(sv_2mortal(newSViv(paren))); - XPUSHs(SvREFCNT_inc((SV *) value)); + XPUSHs((SV *) value); PUTBACK; call_sv(callback, G_DISCARD); @@ -534,9 +498,11 @@ Plugin_numbered_buff_LENGTH(pTHX_ REGEXP * const RX, const SV * const sv, callback = self->cb_num_capture_buff_LENGTH; if (callback) { + IV ret; + ENTER; SAVETMPS; - + PUSHMARK(SP); XPUSHs(rx->pprivate); XPUSHs(sv_2mortal(newSViv(paren))); @@ -546,7 +512,7 @@ Plugin_numbered_buff_LENGTH(pTHX_ REGEXP * const RX, const SV * const sv, SPAGAIN; - IV ret = POPi; + ret = POPi; PUTBACK; FREETMPS; @@ -581,43 +547,16 @@ Plugin_package(pTHX_ REGEXP * const RX) return newSVpvs("re::engine::Plugin"); } -#if REP_THREADSAFE +static void xsh_user_global_setup(pTHX) { + HV *stash; -STATIC U32 rep_initialized = 0; + stash = gv_stashpvn(XSH_PACKAGE, XSH_PACKAGE_LEN, 1); + newCONSTSUB(stash, "REP_THREADSAFE", newSVuv(XSH_THREADSAFE)); + newCONSTSUB(stash, "REP_FORKSAFE", newSVuv(XSH_FORKSAFE)); -STATIC void rep_teardown(pTHX_ void *root) { - dMY_CXT; - - if (!rep_initialized || aTHX != root) - return; - - ptable_free(MY_CXT.tbl); - - rep_initialized = 0; -} - -STATIC void rep_setup(pTHX) { -#define rep_setup() rep_setup(aTHX) - if (rep_initialized) - return; - - MY_CXT_INIT; - MY_CXT.tbl = ptable_new(); - MY_CXT.owner = aTHX; - - call_atexit(rep_teardown, aTHX); - - rep_initialized = 1; + return; } -#else /* REP_THREADSAFE */ - -#define rep_setup() - -#endif /* !REP_THREADSAFE */ - -STATIC U32 rep_booted = 0; - /* --- XS ------------------------------------------------------------------ */ MODULE = re::engine::Plugin PACKAGE = re::engine::Plugin @@ -626,36 +565,18 @@ PROTOTYPES: DISABLE BOOT: { - if (!rep_booted++) { - PERL_HASH(rep_hash, __PACKAGE__, __PACKAGE_LEN__); - } - - rep_setup(); + xsh_setup(); } -#if REP_THREADSAFE +#if XSH_THREADSAFE void CLONE(...) -PREINIT: - ptable *t; PPCODE: - { - my_cxt_t ud; - dMY_CXT; - ud.tbl = t = ptable_new(); - ud.owner = MY_CXT.owner; - ptable_walk(MY_CXT.tbl, rep_ptable_clone, &ud); - } - { - MY_CXT_CLONE; - MY_CXT.tbl = t; - MY_CXT.owner = aTHX; - } - reap(3, rep_thread_cleanup, NULL); + xsh_clone(); XSRETURN(0); -#endif /* REP_THREADSAFE */ +#endif /* XSH_THREADSAFE */ void pattern(re::engine::Plugin self, ...) @@ -667,45 +588,39 @@ str(re::engine::Plugin self, ...) PPCODE: XPUSHs(self->str); -char* -mod(re::engine::Plugin self, ...) +void +mod(re::engine::Plugin self) +PREINIT: + U32 flags; + char mods[5 + 1]; + int n = 0, i; PPCODE: - /* /i */ - if (self->rx->intflags & PMf_FOLD) { - XPUSHs(sv_2mortal(newSVpvs("i"))); - XPUSHs(&PL_sv_yes); - } - - /* /m */ - if (self->rx->intflags & PMf_MULTILINE) { - XPUSHs(sv_2mortal(newSVpvs("m"))); - XPUSHs(&PL_sv_yes); - } - - /* /s */ - if (self->rx->intflags & PMf_SINGLELINE) { - XPUSHs(sv_2mortal(newSVpvs("s"))); - XPUSHs(&PL_sv_yes); - } - - /* /x */ - if (self->rx->intflags & PMf_EXTENDED) { - XPUSHs(sv_2mortal(newSVpvs("x"))); - XPUSHs(&PL_sv_yes); - } - - /* /p */ - if (self->rx->intflags & RXf_PMf_KEEPCOPY) { - XPUSHs(sv_2mortal(newSVpvs("p"))); - XPUSHs(&PL_sv_yes); + flags = self->rx->intflags; + if (flags & PMf_FOLD) /* /i */ + mods[n++] = 'i'; + if (flags & PMf_MULTILINE) /* /m */ + mods[n++] = 'm'; + if (flags & PMf_SINGLELINE) /* /s */ + mods[n++] = 's'; + if (flags & PMf_EXTENDED) /* /x */ + mods[n++] = 'x'; + if (flags & RXf_PMf_KEEPCOPY) /* /p */ + mods[n++] = 'p'; + mods[n] = '\0'; + EXTEND(SP, 2 * n); + for (i = 0; i < n; ++i) { + mPUSHp(mods + i, 1); + PUSHs(&PL_sv_yes); } + XSRETURN(2 * n); void stash(re::engine::Plugin self, ...) PPCODE: if (items > 1) { + SvREFCNT_dec(self->stash); self->stash = ST(1); - SvREFCNT_inc(self->stash); + SvREFCNT_inc_simple_void(self->stash); XSRETURN_EMPTY; } else { XPUSHs(self->stash); @@ -759,7 +674,7 @@ PPCODE: if (items > 1) { SvREFCNT_dec(self->cb_exec); self->cb_exec = ST(1); - SvREFCNT_inc(self->cb_exec); + SvREFCNT_inc_simple_void(self->cb_exec); } void @@ -768,7 +683,7 @@ PPCODE: if (items > 1) { SvREFCNT_dec(self->cb_num_capture_buff_FETCH); self->cb_num_capture_buff_FETCH = ST(1); - SvREFCNT_inc(self->cb_num_capture_buff_FETCH); + SvREFCNT_inc_simple_void(self->cb_num_capture_buff_FETCH); } void @@ -777,7 +692,7 @@ PPCODE: if (items > 1) { SvREFCNT_dec(self->cb_num_capture_buff_STORE); self->cb_num_capture_buff_STORE = ST(1); - SvREFCNT_inc(self->cb_num_capture_buff_STORE); + SvREFCNT_inc_simple_void(self->cb_num_capture_buff_STORE); } void @@ -786,13 +701,17 @@ PPCODE: if (items > 1) { SvREFCNT_dec(self->cb_num_capture_buff_LENGTH); self->cb_num_capture_buff_LENGTH = ST(1); - SvREFCNT_inc(self->cb_num_capture_buff_LENGTH); + SvREFCNT_inc_simple_void(self->cb_num_capture_buff_LENGTH); } SV * _tag(SV *comp, SV *exec) +PREINIT: + xsh_hints_user_t arg; CODE: - RETVAL = rep_tag(comp, exec); + arg.comp = comp; + arg.exec = exec; + RETVAL = xsh_hints_tag(&arg); OUTPUT: RETVAL