# define SvPV_const(S, L) SvPV(S, L)
#endif
+/* ... Thread safety and multiplicity ...................................... */
+
+#ifndef REH_MULTIPLICITY
+# if defined(MULTIPLICITY) || defined(PERL_IMPLICIT_CONTEXT)
+# define REH_MULTIPLICITY 1
+# else
+# define REH_MULTIPLICITY 0
+# endif
+#endif
+
#ifdef USE_ITHREADS
# define REH_LOCK(M) MUTEX_LOCK(M)
# define REH_UNLOCK(M) MUTEX_UNLOCK(M)
return;
}
-/* --- Private API --------------------------------------------------------- */
-
-void reh_call_comp_hook(pTHX_ regexp *rx, regnode *node) {
- SV *hint = reh_hint();
-
- if (hint && SvPOK(hint)) {
- STRLEN len;
- const char *keys = SvPV_const(hint, len);
- reh_action *a;
-
- REH_LOCK(&reh_action_list_mutex);
- a = reh_action_list;
- REH_UNLOCK(&reh_action_list_mutex);
-
- for (; a; a = a->next) {
- if (a->cbs.comp) {
- char *p = strstr(keys, a->key);
-
- if (p && (p + a->klen <= keys + len) && p[a->klen] == ' ')
- a->cbs.comp(aTHX_ rx, node);
- }
- }
- }
-}
-
-void reh_call_exec_hook(pTHX_ regexp *rx, regnode *node, regmatch_info *reginfo, regmatch_state *st) {
- SV *hint = reh_hint();
-
- if (hint && SvPOK(hint)) {
- STRLEN len;
- const char *keys = SvPV_const(hint, len);
- reh_action *a;
-
- REH_LOCK(&reh_action_list_mutex);
- a = reh_action_list;
- REH_UNLOCK(&reh_action_list_mutex);
-
- for (; a; a = a->next) {
- if (a->cbs.exec) {
- char *p = strstr(keys, a->key);
-
- if (p && (p + a->klen <= keys + len) && p[a->klen] == ' ')
- a->cbs.exec(aTHX_ rx, node, reginfo, st);
- }
- }
- }
-}
-
/* --- Custom regexp engine ------------------------------------------------ */
#if PERL_VERSION <= 10
char *, U32, re_scream_pos_data *);
EXTERN_C SV * reh_re_intuit_string(pTHX_ REGEXP * const);
EXTERN_C void reh_regfree(pTHX_ REGEXP * const);
+EXTERN_C void reh_re_free(pTHX_ REGEXP * const);
EXTERN_C void reh_reg_numbered_buff_fetch(pTHX_ REGEXP * const,
const I32, SV * const);
EXTERN_C void reh_reg_numbered_buff_store(pTHX_ REGEXP * const,
EXTERN_C SV * reh_reg_qr_package(pTHX_ REGEXP * const);
#ifdef USE_ITHREADS
EXTERN_C void * reh_regdupe(pTHX_ REGEXP * const, CLONE_PARAMS *);
+EXTERN_C void * reh_re_dupe(pTHX_ REGEXP * const, CLONE_PARAMS *);
#endif
EXTERN_C const struct regexp_engine reh_regexp_engine;
-REGEXP *
-#if PERL_VERSION <= 10
-reh_re_compile(pTHX_ const SV * const pattern, const U32 flags)
-#else
-reh_re_compile(pTHX_ SV * const pattern, U32 flags)
-#endif
-{
- struct regexp *rx;
- REGEXP *RX;
-
- RX = reh_regcomp(aTHX_ pattern, flags);
- rx = rxREGEXP(RX);
-
- rx->engine = &reh_regexp_engine;
-
- return RX;
-}
-
const struct regexp_engine reh_regexp_engine = {
- reh_re_compile,
+ reh_regcomp,
reh_regexec,
reh_re_intuit_start,
reh_re_intuit_string,
- reh_regfree,
+ reh_re_free,
reh_reg_numbered_buff_fetch,
reh_reg_numbered_buff_store,
reh_reg_numbered_buff_length,
reh_reg_named_buff_iter,
reh_reg_qr_package,
#if defined(USE_ITHREADS)
- reh_regdupe
+ reh_re_dupe
#endif
};
+/* --- Private API --------------------------------------------------------- */
+
+typedef struct {
+ size_t count;
+ const reh_config *cbs;
+ U32 refcount;
+} reh_private;
+
+STATIC void reh_private_free(pTHX_ reh_private *priv) {
+#define reh_private_free(P) reh_private_free(aTHX_ (P))
+ if (priv->refcount <= 1) {
+ PerlMemShared_free((void *) priv->cbs);
+ PerlMemShared_free(priv);
+ } else {
+ --priv->refcount;
+ }
+}
+
+#define PTABLE_NAME ptable_private
+#define PTABLE_VAL_FREE(V) reh_private_free(V)
+
+#define pPTBL pTHX
+#define pPTBL_ pTHX_
+#define aPTBL aTHX
+#define aPTBL_ aTHX_
+
+#include "ptable.h"
+
+#define ptable_private_store(T, K, V) ptable_private_store(aTHX_ (T), (K), (V))
+#define ptable_private_delete(T, K) ptable_private_delete(aTHX_ (T), (K))
+#define ptable_private_clear(T) ptable_private_clear(aTHX_ (T))
+#define ptable_private_free(T) ptable_private_free(aTHX_ (T))
+
+STATIC ptable *reh_private_map;
+
+#ifdef USE_ITHREADS
+
+STATIC perl_mutex reh_private_map_mutex;
+
+#endif /* USE_ITHREADS */
+
+#define REH_PRIVATE_MAP_FOREACH(C) STMT_START { \
+ reh_private *priv; \
+ REH_LOCK(&reh_private_map_mutex); \
+ priv = ptable_fetch(reh_private_map, rx->pprivate); \
+ if (priv) { \
+ const reh_config *cbs = priv->cbs; \
+ if (cbs) { \
+ const reh_config *end = cbs + priv->count; \
+ for (; cbs < end; ++cbs) { \
+ (C); \
+ } \
+ } \
+ } \
+ REH_UNLOCK(&reh_private_map_mutex); \
+} STMT_END
+
+STATIC reh_private *reh_private_map_store(pTHX_ void *ri, reh_private *priv) {
+#define reh_private_map_store(R, P) reh_private_map_store(aTHX_ (R), (P))
+ REH_LOCK(&reh_private_map_mutex);
+ ptable_private_store(reh_private_map, ri, priv);
+ REH_UNLOCK(&reh_private_map_mutex);
+
+ return;
+}
+
+STATIC void reh_private_map_copy(pTHX_ void *ri_from, void *ri_to) {
+#define reh_private_map_copy(F, T) reh_private_map_copy(aTHX_ (F), (T))
+ reh_private *priv;
+
+ REH_LOCK(&reh_private_map_mutex);
+ priv = ptable_fetch(reh_private_map, ri_from);
+ if (priv) {
+ ++priv->refcount;
+ ptable_private_store(reh_private_map, ri_to, priv);
+ }
+ REH_UNLOCK(&reh_private_map_mutex);
+}
+
+STATIC void reh_private_map_delete(pTHX_ void *ri) {
+#define reh_private_map_delete(R) reh_private_map_delete(aTHX_ (R))
+ REH_LOCK(&reh_private_map_mutex);
+ ptable_private_delete(reh_private_map, ri);
+ REH_UNLOCK(&reh_private_map_mutex);
+
+ return;
+}
+
+void reh_call_comp_begin_hook(pTHX_ regexp *rx) {
+ SV *hint = reh_hint();
+
+ if (hint && SvPOK(hint)) {
+ STRLEN len;
+ const char *keys = SvPV_const(hint, len);
+ size_t count = 0;
+
+ reh_private *priv;
+ reh_config *cbs = NULL;
+ reh_action *a, *root;
+
+ REH_LOCK(&reh_action_list_mutex);
+ root = reh_action_list;
+ REH_UNLOCK(&reh_action_list_mutex);
+
+ for (a = root; a; a = a->next) {
+ char *p = strstr(keys, a->key);
+
+ if (p && (p + a->klen <= keys + len) && p[a->klen] == ' ')
+ ++count;
+ }
+
+ if (count) {
+ size_t i = 0;
+
+ cbs = PerlMemShared_malloc(count * sizeof *cbs);
+
+ for (a = root; a; a = a->next) {
+ char *p = strstr(keys, a->key);
+
+ if (p && (p + a->klen <= keys + len) && p[a->klen] == ' ')
+ cbs[i++] = a->cbs;
+ }
+ }
+
+ priv = PerlMemShared_malloc(sizeof *priv);
+ priv->count = count;
+ priv->cbs = cbs;
+ priv->refcount = 1;
+
+ rx->engine = &reh_regexp_engine;
+
+ reh_private_map_store(rx->pprivate, priv);
+ }
+}
+
+void reh_call_comp_hook(pTHX_ regexp *rx, regnode *node) {
+ REH_PRIVATE_MAP_FOREACH(cbs->comp(aTHX_ rx, node));
+}
+
+void reh_call_exec_hook(pTHX_ regexp *rx, regnode *node, regmatch_info *reginfo, regmatch_state *st) {
+ REH_PRIVATE_MAP_FOREACH(cbs->exec(aTHX_ rx, node, reginfo, st));
+}
+
+void reh_re_free(pTHX_ REGEXP * const RX) {
+ regexp *rx = rxREGEXP(RX);
+
+ reh_private_map_delete(rx->pprivate);
+
+ reh_regfree(aTHX_ RX);
+}
+
+#ifdef USE_ITHREADS
+
+void *reh_re_dupe(pTHX_ REGEXP * const RX, CLONE_PARAMS *param) {
+ regexp *rx = rxREGEXP(RX);
+ void *new_ri;
+
+ new_ri = reh_regdupe(aTHX_ RX, param);
+
+ reh_private_map_copy(rx->pprivate, new_ri);
+
+ return new_ri;
+}
+
+#endif
+
+STATIC void reh_teardown(pTHX_ void *root) {
+#if REH_MULTIPLICITY
+ if (aTHX != root)
+ return;
+#endif
+
+ ptable_private_free(reh_private_map);
+}
+
/* --- XS ------------------------------------------------------------------ */
MODULE = re::engine::Hooks PACKAGE = re::engine::Hooks
BOOT:
{
+ reh_private_map = ptable_new();
#ifdef USE_ITHREADS
MUTEX_INIT(&reh_action_list_mutex);
+ MUTEX_INIT(&reh_private_map_mutex);
#endif
-
PERL_HASH(reh_hash, __PACKAGE__, __PACKAGE_LEN__);
+#if REH_MULTIPLICITY
+ call_atexit(reh_teardown, aTHX);
+#else
+ call_atexit(reh_teardown, NULL);
+#endif
}
void
README
configure_test.pl
lib/re/engine/Hooks.pm
+ptable.h
re_defs.h
re_engine_hooks.h
re_top.h
--- /dev/null
+/* This file is part of the re::engine::Hooks Perl module.
+ * See http://search.cpan.org/dist/re-engine-Hooks/ */
+
+/* This is a pointer table implementation essentially copied from the ptr_table
+ * implementation in perl's sv.c, except that it has been modified to use memory
+ * shared across threads.
+ * Copyright goes to the original authors, bug reports to me. */
+
+/* This header is designed to be included several times with different
+ * definitions for PTABLE_NAME and PTABLE_VAL_FREE(). */
+
+#undef VOID2
+#ifdef __cplusplus
+# define VOID2(T, P) static_cast<T>(P)
+#else
+# define VOID2(T, P) (P)
+#endif
+
+#undef pPTBLMS
+#undef pPTBLMS_
+#undef aPTBLMS
+#undef aPTBLMS_
+
+/* Context for PerlMemShared_* functions */
+
+#ifdef PERL_IMPLICIT_SYS
+# define pPTBLMS pTHX
+# define pPTBLMS_ pTHX_
+# define aPTBLMS aTHX
+# define aPTBLMS_ aTHX_
+#else
+# define pPTBLMS void
+# define pPTBLMS_
+# define aPTBLMS
+# define aPTBLMS_
+#endif
+
+#ifndef pPTBL
+# define pPTBL pPTBLMS
+#endif
+#ifndef pPTBL_
+# define pPTBL_ pPTBLMS_
+#endif
+#ifndef aPTBL
+# define aPTBL aPTBLMS
+#endif
+#ifndef aPTBL_
+# define aPTBL_ aPTBLMS_
+#endif
+
+#ifndef PTABLE_NAME
+# define PTABLE_NAME ptable
+#endif
+
+#ifndef PTABLE_VAL_FREE
+# define PTABLE_VAL_FREE(V)
+#endif
+
+#ifndef PTABLE_JOIN
+# define PTABLE_PASTE(A, B) A ## B
+# define PTABLE_JOIN(A, B) PTABLE_PASTE(A, B)
+#endif
+
+#ifndef PTABLE_PREFIX
+# define PTABLE_PREFIX(X) PTABLE_JOIN(PTABLE_NAME, X)
+#endif
+
+#ifndef ptable_ent
+typedef struct ptable_ent {
+ struct ptable_ent *next;
+ const void * key;
+ void * val;
+} ptable_ent;
+#define ptable_ent ptable_ent
+#endif /* !ptable_ent */
+
+#ifndef ptable
+typedef struct ptable {
+ ptable_ent **ary;
+ size_t max;
+ size_t items;
+} ptable;
+#define ptable ptable
+#endif /* !ptable */
+
+#ifndef ptable_new
+STATIC ptable *ptable_new(pPTBLMS) {
+#define ptable_new() ptable_new(aPTBLMS)
+ ptable *t = VOID2(ptable *, PerlMemShared_malloc(sizeof *t));
+ t->max = 15;
+ t->items = 0;
+ t->ary = VOID2(ptable_ent **,
+ PerlMemShared_calloc(t->max + 1, sizeof *t->ary));
+ return t;
+}
+#endif /* !ptable_new */
+
+#ifndef PTABLE_HASH
+# define PTABLE_HASH(ptr) \
+ ((PTR2UV(ptr) >> 3) ^ (PTR2UV(ptr) >> (3 + 7)) ^ (PTR2UV(ptr) >> (3 + 17)))
+#endif
+
+#ifndef ptable_find
+STATIC ptable_ent *ptable_find(const ptable * const t, const void * const key) {
+#define ptable_find ptable_find
+ ptable_ent *ent;
+ const UV hash = PTABLE_HASH(key);
+
+ ent = t->ary[hash & t->max];
+ for (; ent; ent = ent->next) {
+ if (ent->key == key)
+ return ent;
+ }
+
+ return NULL;
+}
+#endif /* !ptable_find */
+
+#ifndef ptable_fetch
+STATIC void *ptable_fetch(const ptable * const t, const void * const key) {
+#define ptable_fetch ptable_fetch
+ const ptable_ent *const ent = ptable_find(t, key);
+
+ return ent ? ent->val : NULL;
+}
+#endif /* !ptable_fetch */
+
+#ifndef ptable_split
+STATIC void ptable_split(pPTBLMS_ ptable * const t) {
+#define ptable_split(T) ptable_split(aPTBLMS_ (T))
+ ptable_ent **ary = t->ary;
+ const size_t oldsize = t->max + 1;
+ size_t newsize = oldsize * 2;
+ size_t i;
+
+ ary = VOID2(ptable_ent **, PerlMemShared_realloc(ary, newsize * sizeof(*ary)));
+ Zero(&ary[oldsize], newsize - oldsize, sizeof(*ary));
+ t->max = --newsize;
+ t->ary = ary;
+
+ for (i = 0; i < oldsize; i++, ary++) {
+ ptable_ent **curentp, **entp, *ent;
+ if (!*ary)
+ continue;
+ curentp = ary + oldsize;
+ for (entp = ary, ent = *ary; ent; ent = *entp) {
+ if ((newsize & PTABLE_HASH(ent->key)) != i) {
+ *entp = ent->next;
+ ent->next = *curentp;
+ *curentp = ent;
+ continue;
+ } else
+ entp = &ent->next;
+ }
+ }
+}
+#endif /* !ptable_split */
+
+STATIC void PTABLE_PREFIX(_store)(pPTBL_ ptable * const t, const void * const key, void * const val) {
+ ptable_ent *ent = ptable_find(t, key);
+
+ if (ent) {
+ void *oldval = ent->val;
+ PTABLE_VAL_FREE(oldval);
+ ent->val = val;
+ } else if (val) {
+ const size_t i = PTABLE_HASH(key) & t->max;
+ ent = VOID2(ptable_ent *, PerlMemShared_malloc(sizeof *ent));
+ ent->key = key;
+ ent->val = val;
+ ent->next = t->ary[i];
+ t->ary[i] = ent;
+ t->items++;
+ if (ent->next && t->items > t->max)
+ ptable_split(t);
+ }
+}
+
+STATIC void PTABLE_PREFIX(_delete)(pPTBL_ ptable * const t, const void * const key) {
+ ptable_ent *prev, *ent;
+ const size_t i = PTABLE_HASH(key) & t->max;
+
+ prev = NULL;
+ ent = t->ary[i];
+ for (; ent; prev = ent, ent = ent->next) {
+ if (ent->key == key)
+ break;
+ }
+
+ if (ent) {
+ if (prev)
+ prev->next = ent->next;
+ else
+ t->ary[i] = ent->next;
+ PTABLE_VAL_FREE(ent->val);
+ PerlMemShared_free(ent);
+ }
+}
+
+#ifndef ptable_walk
+STATIC void ptable_walk(pTHX_ ptable * const t, void (*cb)(pTHX_ ptable_ent *ent, void *userdata), void *userdata) {
+#define ptable_walk(T, CB, UD) ptable_walk(aTHX_ (T), (CB), (UD))
+ if (t && t->items) {
+ register ptable_ent ** const array = t->ary;
+ size_t i = t->max;
+ do {
+ ptable_ent *entry;
+ for (entry = array[i]; entry; entry = entry->next)
+ if (entry->val)
+ cb(aTHX_ entry, userdata);
+ } while (i--);
+ }
+}
+#endif /* !ptable_walk */
+
+STATIC void PTABLE_PREFIX(_clear)(pPTBL_ ptable * const t) {
+ if (t && t->items) {
+ register ptable_ent ** const array = t->ary;
+ size_t i = t->max;
+
+ do {
+ ptable_ent *entry = array[i];
+ while (entry) {
+ ptable_ent * const oentry = entry;
+ void *val = oentry->val;
+ entry = entry->next;
+ PTABLE_VAL_FREE(val);
+ PerlMemShared_free(oentry);
+ }
+ array[i] = NULL;
+ } while (i--);
+
+ t->items = 0;
+ }
+}
+
+STATIC void PTABLE_PREFIX(_free)(pPTBL_ ptable * const t) {
+ if (!t)
+ return;
+ PTABLE_PREFIX(_clear)(aPTBL_ t);
+ PerlMemShared_free(t->ary);
+ PerlMemShared_free(t);
+}
+
+#undef pPTBL
+#undef pPTBL_
+#undef aPTBL
+#undef aPTBL_
+
+#undef PTABLE_NAME
+#undef PTABLE_VAL_FREE
+EXTERN_C void reh_call_comp_begin_hook(pTHX_ regexp *);
EXTERN_C void reh_call_comp_hook(pTHX_ regexp *, regnode *);
EXTERN_C void reh_call_exec_hook(pTHX_ regexp *, regnode *, regmatch_info *, regmatch_state *);
+#define REH_CALL_COMP_BEGIN_HOOK(a) reh_call_comp_begin_hook(aTHX_ (a))
#define REH_CALL_REGCOMP_HOOK(a, b) reh_call_comp_hook(aTHX_ (a), (b))
#define REH_CALL_REGEXEC_HOOK(a, b, c, d) reh_call_exec_hook(aTHX_ (a), (b), (c), (d))
SetProgLen(ri,RExC_size);
RExC_rx = r;
RExC_rxi = ri;
+ REH_CALL_COMP_BEGIN_HOOK(pRExC_state->rx);
/* Second pass: emit code. */
RExC_flags = pm_flags; /* don't let top level (?i) bleed */
RExC_rx_sv = rx;
RExC_rx = r;
RExC_rxi = ri;
+ REH_CALL_COMP_BEGIN_HOOK(pRExC_state->rx);
/* Second pass: emit code. */
RExC_flags = pm_flags; /* don't let top level (?i) bleed */
RExC_rx_sv = rx;
RExC_rx = r;
RExC_rxi = ri;
+ REH_CALL_COMP_BEGIN_HOOK(pRExC_state->rx);
/* Second pass: emit code. */
RExC_flags = pm_flags; /* don't let top level (?i) bleed */
RExC_rx_sv = rx;
RExC_rx = r;
RExC_rxi = ri;
+ REH_CALL_COMP_BEGIN_HOOK(pRExC_state->rx);
/* Second pass: emit code. */
RExC_flags = pm_flags; /* don't let top level (?i) bleed */
RExC_rx_sv = rx;
RExC_rx = r;
RExC_rxi = ri;
+ REH_CALL_COMP_BEGIN_HOOK(pRExC_state->rx);
/* Second pass: emit code. */
RExC_flags = pm_flags; /* don't let top level (?i) bleed */
RExC_rx_sv = rx;
RExC_rx = r;
RExC_rxi = ri;
+ REH_CALL_COMP_BEGIN_HOOK(pRExC_state->rx);
/* Second pass: emit code. */
RExC_flags = pm_flags; /* don't let top level (?i) bleed */
RExC_rx_sv = rx;
RExC_rx = r;
RExC_rxi = ri;
+ REH_CALL_COMP_BEGIN_HOOK(pRExC_state->rx);
/* Second pass: emit code. */
RExC_flags = pm_flags; /* don't let top level (?i) bleed */
RExC_rx_sv = rx;
RExC_rx = r;
RExC_rxi = ri;
+ REH_CALL_COMP_BEGIN_HOOK(pRExC_state->rx);
/* Second pass: emit code. */
RExC_flags = pm_flags; /* don't let top level (?i) bleed */
RExC_rx_sv = rx;
RExC_rx = r;
RExC_rxi = ri;
+ REH_CALL_COMP_BEGIN_HOOK(pRExC_state->rx);
/* Second pass: emit code. */
RExC_flags = pm_flags; /* don't let top level (?i) bleed */
RExC_rx_sv = rx;
RExC_rx = r;
RExC_rxi = ri;
+ REH_CALL_COMP_BEGIN_HOOK(pRExC_state->rx);
/* Second pass: emit code. */
RExC_flags = pm_flags; /* don't let top level (?i) bleed */
RExC_rx_sv = rx;
RExC_rx = r;
RExC_rxi = ri;
+ REH_CALL_COMP_BEGIN_HOOK(pRExC_state->rx);
/* Second pass: emit code. */
RExC_flags = pm_flags; /* don't let top level (?i) bleed */
RExC_rx_sv = rx;
RExC_rx = r;
RExC_rxi = ri;
+ REH_CALL_COMP_BEGIN_HOOK(pRExC_state->rx);
/* Second pass: emit code. */
RExC_flags = pm_flags; /* don't let top level (?i) bleed */
RExC_rx_sv = rx;
RExC_rx = r;
RExC_rxi = ri;
+ REH_CALL_COMP_BEGIN_HOOK(pRExC_state->rx);
/* Second pass: emit code. */
RExC_flags = pm_flags; /* don't let top level (?i) bleed */
RExC_rx_sv = rx;
RExC_rx = r;
RExC_rxi = ri;
+ REH_CALL_COMP_BEGIN_HOOK(pRExC_state->rx);
/* Second pass: emit code. */
RExC_flags = pm_flags; /* don't let top level (?i) bleed */
RExC_rx_sv = rx;
RExC_rx = r;
RExC_rxi = ri;
+ REH_CALL_COMP_BEGIN_HOOK(pRExC_state->rx);
/* Second pass: emit code. */
RExC_flags = pm_flags; /* don't let top level (?i) bleed */
RExC_rx_sv = rx;
RExC_rx = r;
RExC_rxi = ri;
+ REH_CALL_COMP_BEGIN_HOOK(pRExC_state->rx);
/* Second pass: emit code. */
RExC_flags = pm_flags; /* don't let top level (?i) bleed */
RExC_rx_sv = rx;
RExC_rx = r;
RExC_rxi = ri;
+ REH_CALL_COMP_BEGIN_HOOK(pRExC_state->rx);
/* Second pass: emit code. */
RExC_flags = pm_flags; /* don't let top level (?i) bleed */
RExC_rx_sv = rx;
RExC_rx = r;
RExC_rxi = ri;
+ REH_CALL_COMP_BEGIN_HOOK(pRExC_state->rx);
/* Second pass: emit code. */
RExC_flags = pm_flags; /* don't let top level (?i) bleed */
RExC_rx_sv = rx;
RExC_rx = r;
RExC_rxi = ri;
+ REH_CALL_COMP_BEGIN_HOOK(pRExC_state->rx);
/* Second pass: emit code. */
RExC_flags = pm_flags; /* don't let top level (?i) bleed */
RExC_rx_sv = rx;
RExC_rx = r;
RExC_rxi = ri;
+ REH_CALL_COMP_BEGIN_HOOK(pRExC_state->rx);
/* Second pass: emit code. */
RExC_flags = pm_flags; /* don't let top level (?i) bleed */
RExC_rx_sv = rx;
RExC_rx = r;
RExC_rxi = ri;
+ REH_CALL_COMP_BEGIN_HOOK(pRExC_state->rx);
/* Second pass: emit code. */
RExC_flags = pm_flags; /* don't let top level (?i) bleed */
RExC_rx_sv = rx;
RExC_rx = r;
RExC_rxi = ri;
+ REH_CALL_COMP_BEGIN_HOOK(pRExC_state->rx);
/* Second pass: emit code. */
RExC_flags = pm_flags; /* don't let top level (?i) bleed */
RExC_rx_sv = rx;
RExC_rx = r;
RExC_rxi = ri;
+ REH_CALL_COMP_BEGIN_HOOK(pRExC_state->rx);
/* Second pass: emit code. */
RExC_flags = pm_flags; /* don't let top level (?i) bleed */
RExC_rx_sv = rx;
RExC_rx = r;
RExC_rxi = ri;
+ REH_CALL_COMP_BEGIN_HOOK(pRExC_state->rx);
/* Second pass: emit code. */
RExC_flags = pm_flags; /* don't let top level (?i) bleed */
RExC_rx_sv = rx;
RExC_rx = r;
RExC_rxi = ri;
+ REH_CALL_COMP_BEGIN_HOOK(pRExC_state->rx);
/* Second pass: emit code. */
RExC_flags = pm_flags; /* don't let top level (?i) bleed */
RExC_rx_sv = rx;
RExC_rx = r;
RExC_rxi = ri;
+ REH_CALL_COMP_BEGIN_HOOK(pRExC_state->rx);
/* Second pass: emit code. */
RExC_flags = pm_flags; /* don't let top level (?i) bleed */
RExC_rx_sv = rx;
RExC_rx = r;
RExC_rxi = ri;
+ REH_CALL_COMP_BEGIN_HOOK(pRExC_state->rx);
/* Second pass: emit code. */
RExC_flags = pm_flags; /* don't let top level (?i) bleed */
RExC_rx_sv = rx;
RExC_rx = r;
RExC_rxi = ri;
+ REH_CALL_COMP_BEGIN_HOOK(pRExC_state->rx);
/* Second pass: emit code. */
RExC_flags = pm_flags; /* don't let top level (?i) bleed */
RExC_rx_sv = rx;
RExC_rx = r;
RExC_rxi = ri;
+ REH_CALL_COMP_BEGIN_HOOK(pRExC_state->rx);
/* Second pass: emit code. */
RExC_flags = pm_flags; /* don't let top level (?i) bleed */
RExC_rx_sv = rx;
RExC_rx = r;
RExC_rxi = ri;
+ REH_CALL_COMP_BEGIN_HOOK(pRExC_state->rx);
/* Second pass: emit code. */
RExC_flags = pm_flags; /* don't let top level (?i) bleed */
RExC_rx_sv = rx;
RExC_rx = r;
RExC_rxi = ri;
+ REH_CALL_COMP_BEGIN_HOOK(pRExC_state->rx);
/* Second pass: emit code. */
RExC_flags = pm_flags; /* don't let top level (?i) bleed */
RExC_rx_sv = rx;
RExC_rx = r;
RExC_rxi = ri;
+ REH_CALL_COMP_BEGIN_HOOK(pRExC_state->rx);
/* Second pass: emit code. */
RExC_flags = pm_flags; /* don't let top level (?i) bleed */
RExC_rx_sv = rx;
RExC_rx = r;
RExC_rxi = ri;
+ REH_CALL_COMP_BEGIN_HOOK(pRExC_state->rx);
/* Second pass: emit code. */
RExC_flags = pm_flags; /* don't let top level (?i) bleed */
RExC_rx_sv = rx;
RExC_rx = r;
RExC_rxi = ri;
+ REH_CALL_COMP_BEGIN_HOOK(pRExC_state->rx);
/* Second pass: emit code. */
RExC_flags = pm_flags; /* don't let top level (?i) bleed */
RExC_rx_sv = rx;
RExC_rx = r;
RExC_rxi = ri;
+ REH_CALL_COMP_BEGIN_HOOK(pRExC_state->rx);
/* Second pass: emit code. */
RExC_flags = pm_flags; /* don't let top level (?i) bleed */
RExC_rx_sv = rx;
RExC_rx = r;
RExC_rxi = ri;
+ REH_CALL_COMP_BEGIN_HOOK(pRExC_state->rx);
/* Second pass: emit code. */
RExC_flags = pm_flags; /* don't let top level (?i) bleed */
RExC_rx_sv = rx;
RExC_rx = r;
RExC_rxi = ri;
+ REH_CALL_COMP_BEGIN_HOOK(pRExC_state->rx);
/* Second pass: emit code. */
RExC_flags = pm_flags; /* don't let top level (?i) bleed */
if ($line =~ /#\s*include\s+"INTERN\.h"/) {
return "#include \"re_defs.h\"\n";
+ } elsif ($line =~ /^(\s*)RExC_rxi\s*=\s*ri\s*;\s*$/) {
+ return $line, "$1REH_CALL_COMP_BEGIN_HOOK(pRExC_state->rx);\n";
} elsif ($line =~ /FILL_ADVANCE_NODE(_ARG)?\(\s*([^\s,\)]+)/) {
my $shift = $1 ? 2 : 1;
return $line, " REH_CALL_REGCOMP_HOOK(pRExC_state->rx, ($2) - $shift);\n"