DEBUG_STUDYDATA("commit: ",data,0);
}
+/* These macros set, clear and test whether the synthetic start class ('ssc',
+ * given by the parameter) matches an empty string (EOS). This uses the
+ * 'next_off' field in the node, to save a bit in the flags field. The ssc
+ * stands alone, so there is never a next_off, so this field is otherwise
+ * unused. The EOS information is used only for compilation, but theoretically
+ * it could be passed on to the execution code. This could be used to store
+ * more than one bit of information, but only this one is currently used. */
+#define SET_SSC_EOS(node) STMT_START { (node)->next_off = TRUE; } STMT_END
+#define CLEAR_SSC_EOS(node) STMT_START { (node)->next_off = FALSE; } STMT_END
+#define TEST_SSC_EOS(node) cBOOL((node)->next_off)
+
/* Can match anything (initialization) */
STATIC void
S_cl_anything(const RExC_state_t *pRExC_state, struct regnode_charclass_class *cl)
PERL_ARGS_ASSERT_CL_ANYTHING;
ANYOF_BITMAP_SETALL(cl);
- cl->flags = ANYOF_CLASS|ANYOF_EOS|ANYOF_UNICODE_ALL
- |ANYOF_NON_UTF8_LATIN1_ALL;
+ cl->flags = ANYOF_UNICODE_ALL;
+ SET_SSC_EOS(cl);
/* If any portion of the regex is to operate under locale rules,
* initialization includes it. The reason this isn't done for all regexes
* necessary. */
if (RExC_contains_locale) {
ANYOF_CLASS_SETALL(cl); /* /l uses class */
- cl->flags |= ANYOF_LOCALE|ANYOF_LOC_FOLD;
+ cl->flags |= ANYOF_LOCALE|ANYOF_CLASS|ANYOF_LOC_FOLD;
}
else {
ANYOF_CLASS_ZERO(cl); /* Only /l uses class now */
{
PERL_ARGS_ASSERT_CL_AND;
- assert(and_with->type == ANYOF);
+ assert(PL_regkind[and_with->type] == ANYOF);
/* I (khw) am not sure all these restrictions are necessary XXX */
if (!(ANYOF_CLASS_TEST_ANY_SET(and_with))
RExC_rxi->data->data[ data_slot + TRIE_WORDS_OFFSET ] = (void*)trie_words;
RExC_rxi->data->data[ data_slot + 3 ] = (void*)revcharmap;
#else
- SvREFCNT_dec(revcharmap);
+ SvREFCNT_dec_NN(revcharmap);
#endif
return trie->jump
? MADE_JUMP_TRIE
#define SCAN_COMMIT(s, data, m) scan_commit(s, data, m, is_inf)
-#define CASE_SYNST_FNC(nAmE) \
-case nAmE: \
- if (flags & SCF_DO_STCLASS_AND) { \
- for (value = 0; value < 256; value++) \
- if (!is_ ## nAmE ## _cp(value)) \
- ANYOF_BITMAP_CLEAR(data->start_class, value); \
- } \
- else { \
- for (value = 0; value < 256; value++) \
- if (is_ ## nAmE ## _cp(value)) \
- ANYOF_BITMAP_SET(data->start_class, value); \
- } \
- break; \
-case N ## nAmE: \
- if (flags & SCF_DO_STCLASS_AND) { \
- for (value = 0; value < 256; value++) \
- if (is_ ## nAmE ## _cp(value)) \
- ANYOF_BITMAP_CLEAR(data->start_class, value); \
- } \
- else { \
- for (value = 0; value < 256; value++) \
- if (!is_ ## nAmE ## _cp(value)) \
- ANYOF_BITMAP_SET(data->start_class, value); \
- } \
- break
-
-
-
STATIC I32
S_study_chunk(pTHX_ RExC_state_t *pRExC_state, regnode **scanp,
I32 *minlenp, I32 *deltap,
StructCopy(&accum, data->start_class,
struct regnode_charclass_class);
flags |= SCF_DO_STCLASS_OR;
- data->start_class->flags |= ANYOF_EOS;
+ SET_SSC_EOS(data->start_class);
}
}
* utf8 string, so accept a possible false positive for
* latin1-range folds */
if (uc >= 0x100 ||
- (!(data->start_class->flags & (ANYOF_CLASS | ANYOF_LOCALE))
+ (!(data->start_class->flags & ANYOF_LOCALE)
&& !ANYOF_BITMAP_TEST(data->start_class, uc)
&& (!(data->start_class->flags & ANYOF_LOC_FOLD)
|| !ANYOF_BITMAP_TEST(data->start_class, PL_fold_latin1[uc])))
}
}
}
- data->start_class->flags &= ~ANYOF_EOS;
+ CLEAR_SSC_EOS(data->start_class);
if (uc < 0x100)
data->start_class->flags &= ~ANYOF_UNICODE_ALL;
}
ANYOF_BITMAP_SET(data->start_class, uc);
else
data->start_class->flags |= ANYOF_UNICODE_ALL;
- data->start_class->flags &= ~ANYOF_EOS;
+ CLEAR_SSC_EOS(data->start_class);
cl_and(data->start_class, and_withp);
}
flags &= ~SCF_DO_STCLASS;
/* Check whether it is compatible with what we know already! */
int compat = 1;
if (uc >= 0x100 ||
- (!(data->start_class->flags & (ANYOF_CLASS | ANYOF_LOCALE))
+ (!(data->start_class->flags & ANYOF_LOCALE)
&& !ANYOF_BITMAP_TEST(data->start_class, uc)
&& !ANYOF_BITMAP_TEST(data->start_class, PL_fold_latin1[uc])))
{
ANYOF_BITMAP_ZERO(data->start_class);
if (compat) {
ANYOF_BITMAP_SET(data->start_class, uc);
- data->start_class->flags &= ~ANYOF_EOS;
+ CLEAR_SSC_EOS(data->start_class);
if (OP(scan) == EXACTFL) {
/* XXX This set is probably no longer necessary, and
* probably wrong as LOCALE now is on in the initial
}
}
}
- data->start_class->flags &= ~ANYOF_EOS;
+ CLEAR_SSC_EOS(data->start_class);
}
cl_and(data->start_class, and_withp);
}
StructCopy(&this_class, data->start_class,
struct regnode_charclass_class);
flags |= SCF_DO_STCLASS_OR;
- data->start_class->flags |= ANYOF_EOS;
+ SET_SSC_EOS(data->start_class);
}
} else { /* Non-zero len */
if (flags & SCF_DO_STCLASS_OR) {
else if (OP(scan) == LNBREAK) {
if (flags & SCF_DO_STCLASS) {
int value = 0;
- data->start_class->flags &= ~ANYOF_EOS; /* No match on empty */
+ CLEAR_SSC_EOS(data->start_class); /* No match on empty */
if (flags & SCF_DO_STCLASS_AND) {
for (value = 0; value < 256; value++)
if (!is_VERTWS_cp(value))
}
min++;
if (flags & SCF_DO_STCLASS) {
- data->start_class->flags &= ~ANYOF_EOS; /* No match on empty */
+ int loop_max = 256;
+ CLEAR_SSC_EOS(data->start_class); /* No match on empty */
/* Some of the logic below assumes that switching
locale on will only add false positives. */
switch (PL_regkind[OP(scan)]) {
+ U8 classnum;
+
case SANY:
default:
do_default:
goto do_default;
if (flags & SCF_DO_STCLASS_OR) { /* Everything but \n */
value = (ANYOF_BITMAP_TEST(data->start_class,'\n')
- || ANYOF_CLASS_TEST_ANY_SET(data->start_class));
+ || ANYOF_CLASS_TEST_ANY_SET(data->start_class));
cl_anything(pRExC_state, data->start_class);
}
if (flags & SCF_DO_STCLASS_AND || !value)
cl_or(pRExC_state, data->start_class,
(struct regnode_charclass_class*)scan);
break;
- case ALNUM:
+ case POSIXA:
+ loop_max = 128;
+ case POSIXL:
+ case POSIXD:
+ case POSIXU:
+ classnum = FLAGS(scan);
if (flags & SCF_DO_STCLASS_AND) {
if (!(data->start_class->flags & ANYOF_LOCALE)) {
- ANYOF_CLASS_CLEAR(data->start_class,ANYOF_NWORDCHAR);
- if (OP(scan) == ALNUMU) {
- for (value = 0; value < 256; value++) {
- if (!isWORDCHAR_L1(value)) {
- ANYOF_BITMAP_CLEAR(data->start_class, value);
- }
- }
- } else {
- for (value = 0; value < 256; value++) {
- if (!isALNUM(value)) {
- ANYOF_BITMAP_CLEAR(data->start_class, value);
- }
+ ANYOF_CLASS_CLEAR(data->start_class, classnum_to_namedclass(classnum) + 1);
+ for (value = 0; value < loop_max; value++) {
+ if (! _generic_isCC(UNI_TO_NATIVE(value), classnum)) {
+ ANYOF_BITMAP_CLEAR(data->start_class, UNI_TO_NATIVE(value));
}
}
}
}
else {
- if (data->start_class->flags & ANYOF_LOCALE)
- ANYOF_CLASS_SET(data->start_class,ANYOF_WORDCHAR);
+ if (data->start_class->flags & ANYOF_LOCALE) {
+ ANYOF_CLASS_SET(data->start_class, classnum_to_namedclass(classnum));
+ }
+ else {
/* Even if under locale, set the bits for non-locale
* in case it isn't a true locale-node. This will
* create false positives if it truly is locale */
- if (OP(scan) == ALNUMU) {
- for (value = 0; value < 256; value++) {
- if (isWORDCHAR_L1(value)) {
- ANYOF_BITMAP_SET(data->start_class, value);
- }
- }
- } else {
- for (value = 0; value < 256; value++) {
- if (isALNUM(value)) {
- ANYOF_BITMAP_SET(data->start_class, value);
- }
+ for (value = 0; value < loop_max; value++) {
+ if (_generic_isCC(UNI_TO_NATIVE(value), classnum)) {
+ ANYOF_BITMAP_SET(data->start_class, UNI_TO_NATIVE(value));
}
}
+ }
}
break;
- case NALNUM:
+ case NPOSIXA:
+ loop_max = 128;
+ case NPOSIXL:
+ case NPOSIXU:
+ case NPOSIXD:
+ classnum = FLAGS(scan);
if (flags & SCF_DO_STCLASS_AND) {
if (!(data->start_class->flags & ANYOF_LOCALE)) {
- ANYOF_CLASS_CLEAR(data->start_class,ANYOF_WORDCHAR);
- if (OP(scan) == NALNUMU) {
- for (value = 0; value < 256; value++) {
- if (isWORDCHAR_L1(value)) {
- ANYOF_BITMAP_CLEAR(data->start_class, value);
- }
- }
- } else {
- for (value = 0; value < 256; value++) {
- if (isALNUM(value)) {
- ANYOF_BITMAP_CLEAR(data->start_class, value);
- }
+ ANYOF_CLASS_CLEAR(data->start_class, classnum_to_namedclass(classnum));
+ for (value = 0; value < loop_max; value++) {
+ if (_generic_isCC(UNI_TO_NATIVE(value), classnum)) {
+ ANYOF_BITMAP_CLEAR(data->start_class, UNI_TO_NATIVE(value));
}
- }
+ }
}
}
else {
- if (data->start_class->flags & ANYOF_LOCALE)
- ANYOF_CLASS_SET(data->start_class,ANYOF_NWORDCHAR);
+ if (data->start_class->flags & ANYOF_LOCALE) {
+ ANYOF_CLASS_SET(data->start_class, classnum_to_namedclass(classnum) + 1);
+ }
+ else {
/* Even if under locale, set the bits for non-locale in
* case it isn't a true locale-node. This will create
* false positives if it truly is locale */
- if (OP(scan) == NALNUMU) {
- for (value = 0; value < 256; value++) {
- if (! isWORDCHAR_L1(value)) {
- ANYOF_BITMAP_SET(data->start_class, value);
- }
- }
- } else {
- for (value = 0; value < 256; value++) {
- if (! isALNUM(value)) {
- ANYOF_BITMAP_SET(data->start_class, value);
- }
- }
- }
- }
- break;
- case SPACE:
- if (flags & SCF_DO_STCLASS_AND) {
- if (!(data->start_class->flags & ANYOF_LOCALE)) {
- ANYOF_CLASS_CLEAR(data->start_class,ANYOF_NSPACE);
- if (OP(scan) == SPACEU) {
- for (value = 0; value < 256; value++) {
- if (!isSPACE_L1(value)) {
- ANYOF_BITMAP_CLEAR(data->start_class, value);
- }
- }
- } else {
- for (value = 0; value < 256; value++) {
- if (!isSPACE(value)) {
- ANYOF_BITMAP_CLEAR(data->start_class, value);
- }
- }
+ for (value = 0; value < loop_max; value++) {
+ if (! _generic_isCC(UNI_TO_NATIVE(value), classnum)) {
+ ANYOF_BITMAP_SET(data->start_class, UNI_TO_NATIVE(value));
}
- }
- }
- else {
- if (data->start_class->flags & ANYOF_LOCALE) {
- ANYOF_CLASS_SET(data->start_class,ANYOF_SPACE);
}
- if (OP(scan) == SPACEU) {
- for (value = 0; value < 256; value++) {
- if (isSPACE_L1(value)) {
- ANYOF_BITMAP_SET(data->start_class, value);
- }
- }
- } else {
- for (value = 0; value < 256; value++) {
- if (isSPACE(value)) {
- ANYOF_BITMAP_SET(data->start_class, value);
- }
- }
- }
- }
- break;
- case NSPACE:
- if (flags & SCF_DO_STCLASS_AND) {
- if (!(data->start_class->flags & ANYOF_LOCALE)) {
- ANYOF_CLASS_CLEAR(data->start_class,ANYOF_SPACE);
- if (OP(scan) == NSPACEU) {
- for (value = 0; value < 256; value++) {
- if (isSPACE_L1(value)) {
- ANYOF_BITMAP_CLEAR(data->start_class, value);
- }
- }
- } else {
- for (value = 0; value < 256; value++) {
- if (isSPACE(value)) {
- ANYOF_BITMAP_CLEAR(data->start_class, value);
- }
- }
- }
- }
- }
- else {
- if (data->start_class->flags & ANYOF_LOCALE)
- ANYOF_CLASS_SET(data->start_class,ANYOF_NSPACE);
- if (OP(scan) == NSPACEU) {
- for (value = 0; value < 256; value++) {
- if (!isSPACE_L1(value)) {
- ANYOF_BITMAP_SET(data->start_class, value);
- }
- }
+ if (PL_regkind[OP(scan)] == NPOSIXD) {
+ data->start_class->flags |= ANYOF_NON_UTF8_LATIN1_ALL;
}
- else {
- for (value = 0; value < 256; value++) {
- if (!isSPACE(value)) {
- ANYOF_BITMAP_SET(data->start_class, value);
- }
- }
}
}
break;
- case DIGIT:
- if (flags & SCF_DO_STCLASS_AND) {
- if (!(data->start_class->flags & ANYOF_LOCALE)) {
- ANYOF_CLASS_CLEAR(data->start_class,ANYOF_NDIGIT);
- for (value = 0; value < 256; value++)
- if (!isDIGIT(value))
- ANYOF_BITMAP_CLEAR(data->start_class, value);
- }
- }
- else {
- if (data->start_class->flags & ANYOF_LOCALE)
- ANYOF_CLASS_SET(data->start_class,ANYOF_DIGIT);
- for (value = 0; value < 256; value++)
- if (isDIGIT(value))
- ANYOF_BITMAP_SET(data->start_class, value);
- }
- break;
- case NDIGIT:
- if (flags & SCF_DO_STCLASS_AND) {
- if (!(data->start_class->flags & ANYOF_LOCALE))
- ANYOF_CLASS_CLEAR(data->start_class,ANYOF_DIGIT);
- for (value = 0; value < 256; value++)
- if (isDIGIT(value))
- ANYOF_BITMAP_CLEAR(data->start_class, value);
- }
- else {
- if (data->start_class->flags & ANYOF_LOCALE)
- ANYOF_CLASS_SET(data->start_class,ANYOF_NDIGIT);
- for (value = 0; value < 256; value++)
- if (!isDIGIT(value))
- ANYOF_BITMAP_SET(data->start_class, value);
- }
- break;
- CASE_SYNST_FNC(VERTWS);
- CASE_SYNST_FNC(HORIZWS);
-
}
if (flags & SCF_DO_STCLASS_OR)
cl_and(data->start_class, and_withp);
cl_init(pRExC_state, data->start_class);
} else {
/* AND before and after: combine and continue */
- const int was = (data->start_class->flags & ANYOF_EOS);
+ const int was = TEST_SSC_EOS(data->start_class);
cl_and(data->start_class, &intrnl);
if (was)
- data->start_class->flags |= ANYOF_EOS;
+ SET_SSC_EOS(data->start_class);
}
}
}
*minnextp += min;
if (f & SCF_DO_STCLASS_AND) {
- const int was = (data->start_class->flags & ANYOF_EOS);
+ const int was = TEST_SSC_EOS(data.start_class);
cl_and(data->start_class, &intrnl);
if (was)
- data->start_class->flags |= ANYOF_EOS;
+ SET_SSC_EOS(data->start_class);
}
if (data) {
if (data_fake.flags & (SF_HAS_PAR|SF_IN_PAR))
if (RExC_rx->minlen<*minnextp)
RExC_rx->minlen=*minnextp;
SCAN_COMMIT(pRExC_state, &data_fake, minnextp);
- SvREFCNT_dec(data_fake.last_found);
+ SvREFCNT_dec_NN(data_fake.last_found);
if ( data_fake.minlen_fixed != minlenp )
{
StructCopy(&accum, data->start_class,
struct regnode_charclass_class);
flags |= SCF_DO_STCLASS_OR;
- data->start_class->flags |= ANYOF_EOS;
+ SET_SSC_EOS(data->start_class);
}
}
scan= tail;
* handling */
PL_reg_state.re_reparsing = TRUE;
eval_sv(sv, G_SCALAR);
- SvREFCNT_dec(sv);
+ SvREFCNT_dec_NN(sv);
SPAGAIN;
qr_ref = POPs;
PUTBACK;
if (!r2->num_code_blocks) /* we guessed wrong */
{
- SvREFCNT_dec(qr);
+ SvREFCNT_dec_NN(qr);
return 1;
}
r1->code_blocks = new_block;
}
- SvREFCNT_dec(qr);
+ SvREFCNT_dec_NN(qr);
return 1;
}
if ((!(r->anchored_substr || r->anchored_utf8) || r->anchored_offset)
&& stclass_flag
- && !(data.start_class->flags & ANYOF_EOS)
+ && ! TEST_SSC_EOS(data.start_class)
&& !cl_is_anything(data.start_class))
{
const U32 n = add_data(pRExC_state, 1, "f");
- data.start_class->flags |= ANYOF_IS_SYNTHETIC;
+ OP(data.start_class) = ANYOF_SYNTHETIC;
Newx(RExC_rxi->data->data[n], 1,
struct regnode_charclass_class);
r->check_substr = r->check_utf8 = r->anchored_substr = r->anchored_utf8
= r->float_substr = r->float_utf8 = NULL;
- if (!(data.start_class->flags & ANYOF_EOS)
+ if (! TEST_SSC_EOS(data.start_class)
&& !cl_is_anything(data.start_class))
{
const U32 n = add_data(pRExC_state, 1, "f");
- data.start_class->flags |= ANYOF_IS_SYNTHETIC;
+ OP(data.start_class) = ANYOF_SYNTHETIC;
Newx(RExC_rxi->data->data[n], 1,
struct regnode_charclass_class);
r->extflags |= RXf_NULL;
else if (PL_regkind[fop] == BOL && OP(NEXTOPER(first)) == END)
r->extflags |= RXf_START_ONLY;
- else if (fop == PLUS && OP(NEXTOPER(first)) == SPACE
+ else if (fop == PLUS && PL_regkind[OP(NEXTOPER(first))] == POSIXD && FLAGS(NEXTOPER(first)) == _CC_SPACE
&& OP(regnext(first)) == END)
r->extflags |= RXf_WHITE;
}
} else {
SV *sv = CALLREG_NAMED_BUFF_FETCH(r, key, flags);
if (sv) {
- SvREFCNT_dec(sv);
+ SvREFCNT_dec_NN(sv);
return TRUE;
} else {
return FALSE;
ret = CALLREG_NAMED_BUFF_ALL(r, (flags | RXapif_REGNAMES));
av = MUTABLE_AV(SvRV(ret));
length = av_len(av);
- SvREFCNT_dec(ret);
+ SvREFCNT_dec_NN(ret);
return newSViv(length + 1);
} else {
Perl_croak(aTHX_ "panic: Unknown flags %d in named_buff_scalar", (int)flags);
* should eventually be made public */
/* The header definitions are in F<inline_invlist.c> */
-
#define TO_INTERNAL_SIZE(x) ((x + HEADER_LENGTH) * sizeof(UV))
#define FROM_INTERNAL_SIZE(x) ((x / sizeof(UV)) - HEADER_LENGTH)
PERL_ARGS_ASSERT_INVLIST_MAX;
- return FROM_INTERNAL_SIZE(SvLEN(invlist));
+ return SvLEN(invlist) == 0 /* This happens under _new_invlist_C_array */
+ ? _invlist_len(invlist)
+ : FROM_INTERNAL_SIZE(SvLEN(invlist));
}
PERL_STATIC_INLINE UV*
Perl_croak(aTHX_ "panic: Incorrect version for previously generated inversion list");
}
+ /* Initialize the iteration pointer.
+ * XXX This could be done at compile time in charclass_invlists.h, but I
+ * (khw) am not confident that the suffixes for specifying the C constant
+ * UV_MAX are portable, e.g. 'ull' on a 32 bit machine that is configured
+ * to use 64 bits; might need a Configure probe */
+ invlist_iterfinish(invlist);
+
return invlist;
}
return -1;
}
- /* If the code point is before the first element, return failure. (We
- * can't combine this with the test above, because we can't get the array
- * unless we know the list is non-empty) */
+ /* (We can't get the array unless we know the list is non-empty) */
array = invlist_array(invlist);
mid = invlist_previous_index(invlist);
if (a == NULL || ((len_a = _invlist_len(a)) == 0)) {
if (*output == a) {
if (a != NULL) {
- SvREFCNT_dec(a);
+ SvREFCNT_dec_NN(a);
}
}
if (*output != b) {
}
else if ((len_b = _invlist_len(b)) == 0) {
if (*output == b) {
- SvREFCNT_dec(b);
+ SvREFCNT_dec_NN(b);
}
/* The complement of an empty list is a list that has everything in it,
* so the union with <a> includes everything too */
if (complement_b) {
if (a == *output) {
- SvREFCNT_dec(a);
+ SvREFCNT_dec_NN(a);
}
*output = _new_invlist(1);
_append_range_to_invlist(*output, 0, UV_MAX);
/* We may be removing a reference to one of the inputs */
if (a == *output || b == *output) {
- SvREFCNT_dec(*output);
+ assert(! invlist_is_iterating(*output));
+ SvREFCNT_dec_NN(*output);
}
/* If we've changed b, restore it */
*i = invlist_clone(a);
if (*i == b) {
- SvREFCNT_dec(b);
+ SvREFCNT_dec_NN(b);
}
}
/* else *i is already 'a' */
/* Here, 'a' or 'b' is empty and not using the complement of 'b'. The
* intersection must be empty */
if (*i == a) {
- SvREFCNT_dec(a);
+ SvREFCNT_dec_NN(a);
}
else if (*i == b) {
- SvREFCNT_dec(b);
+ SvREFCNT_dec_NN(b);
}
*i = _new_invlist(0);
return;
/* We may be removing a reference to one of the inputs */
if (a == *i || b == *i) {
- SvREFCNT_dec(*i);
+ assert(! invlist_is_iterating(*i));
+ SvREFCNT_dec_NN(*i);
}
/* If we've changed b, restore it */
_invlist_union(invlist, range_invlist, &invlist);
/* The temporary can be freed */
- SvREFCNT_dec(range_invlist);
+ SvREFCNT_dec_NN(range_invlist);
return invlist;
}
PERL_ARGS_ASSERT__INVLIST_INVERT;
+ assert(! invlist_is_iterating(invlist));
+
/* The inverse of matching nothing is matching everything */
if (*len_pos == 0) {
_append_range_to_invlist(invlist, 0, UV_MAX);
*get_invlist_iter_addr(invlist) = 0;
}
+PERL_STATIC_INLINE void
+S_invlist_iterfinish(pTHX_ SV* invlist)
+{
+ /* Terminate iterator for invlist. This is to catch development errors.
+ * Any iteration that is interrupted before completed should call this
+ * function. Functions that add code points anywhere else but to the end
+ * of an inversion list assert that they are not in the middle of an
+ * iteration. If they were, the addition would make the iteration
+ * problematical: if the iteration hadn't reached the place where things
+ * were being added, it would be ok */
+
+ PERL_ARGS_ASSERT_INVLIST_ITERFINISH;
+
+ *get_invlist_iter_addr(invlist) = UV_MAX;
+}
+
STATIC bool
S_invlist_iternext(pTHX_ SV* invlist, UV* start, UV* end)
{
PERL_ARGS_ASSERT_INVLIST_ITERNEXT;
if (*pos >= len) {
- *pos = UV_MAX; /* Force iternit() to be required next time */
+ *pos = UV_MAX; /* Force iterinit() to be required next time */
return FALSE;
}
return TRUE;
}
+PERL_STATIC_INLINE bool
+S_invlist_is_iterating(pTHX_ SV* const invlist)
+{
+ PERL_ARGS_ASSERT_INVLIST_IS_ITERATING;
+
+ return *(get_invlist_iter_addr(invlist)) < UV_MAX;
+}
+
PERL_STATIC_INLINE UV
S_invlist_highest(pTHX_ SV* const invlist)
{
PERL_ARGS_ASSERT__INVLIST_CONTENTS;
+ assert(! invlist_is_iterating(invlist));
+
invlist_iterinit(invlist);
while (invlist_iternext(invlist, &start, &end)) {
if (end == UV_MAX) {
if (header && strlen(header)) {
PerlIO_printf(Perl_debug_log, "%s\n", header);
}
+ if (invlist_is_iterating(invlist)) {
+ PerlIO_printf(Perl_debug_log, "Can't dump because is in middle of iterating\n");
+ return;
+ }
+
invlist_iterinit(invlist);
while (invlist_iternext(invlist, &start, &end)) {
if (end == UV_MAX) {
#undef INVLIST_ZERO_OFFSET
#undef INVLIST_ITER_OFFSET
#undef INVLIST_VERSION_ID
+#undef INVLIST_PREVIOUS_INDEX_OFFSET
/* End of inversion list object */
#ifdef DEBUGGING
/* Yes this does cause a memory leak in debugging Perls */
if (!av_store(RExC_paren_name_list, RExC_npar, SvREFCNT_inc(svname)))
- SvREFCNT_dec(svname);
+ SvREFCNT_dec_NN(svname);
#endif
/*sv_dump(sv_dat);*/
ret = reg_node(pRExC_state, OPFAIL);
return ret;
}
+ else if (max == 0) { /* replace {0} with a nothing node */
+ if (SIZE_ONLY) {
+ RExC_size = PREVOPER(RExC_size) - regarglen[(U8)NOTHING];
+ }
+ else {
+ RExC_emit = orig_emit;
+ }
+ ret = reg_node(pRExC_state, NOTHING);
+ return ret;
+ }
do_curly:
if ((flags&SIMPLE)) {
I32 flags;
char *parse_start = RExC_parse;
U8 op;
+ int invert = 0;
+
GET_RE_DEBUG_FLAGS_DECL;
- DEBUG_PARSE("atom");
+
*flagp = WORST; /* Tentatively. */
+ DEBUG_PARSE("atom");
+
PERL_ARGS_ASSERT_REGATOM;
tryagain:
literal text handling code.
*/
switch ((U8)*++RExC_parse) {
+ U8 arg;
/* Special Escapes */
case 'A':
RExC_seen_zerolen++;
ret = reg_node(pRExC_state, CLUMP);
*flagp |= HASWIDTH;
goto finish_meta_pat;
- case 'w':
- op = ALNUM + get_regex_charset(RExC_flags);
- if (op > ALNUMA) { /* /aa is same as /a */
- op = ALNUMA;
- }
- ret = reg_node(pRExC_state, op);
- *flagp |= HASWIDTH|SIMPLE;
- goto finish_meta_pat;
+
case 'W':
- op = NALNUM + get_regex_charset(RExC_flags);
- if (op > NALNUMA) { /* /aa is same as /a */
- op = NALNUMA;
- }
- ret = reg_node(pRExC_state, op);
- *flagp |= HASWIDTH|SIMPLE;
- goto finish_meta_pat;
+ invert = 1;
+ /* FALLTHROUGH */
+ case 'w':
+ arg = ANYOF_WORDCHAR;
+ goto join_posix;
+
case 'b':
RExC_seen_zerolen++;
RExC_seen |= REG_SEEN_LOOKBEHIND;
FLAGS(ret) = get_regex_charset(RExC_flags);
*flagp |= SIMPLE;
goto finish_meta_pat;
- case 's':
- op = SPACE + get_regex_charset(RExC_flags);
- if (op > SPACEA) { /* /aa is same as /a */
- op = SPACEA;
- }
- ret = reg_node(pRExC_state, op);
- *flagp |= HASWIDTH|SIMPLE;
- goto finish_meta_pat;
- case 'S':
- op = NSPACE + get_regex_charset(RExC_flags);
- if (op > NSPACEA) { /* /aa is same as /a */
- op = NSPACEA;
- }
- ret = reg_node(pRExC_state, op);
- *flagp |= HASWIDTH|SIMPLE;
- goto finish_meta_pat;
+
case 'D':
- op = NDIGIT;
- goto join_D_and_d;
+ invert = 1;
+ /* FALLTHROUGH */
case 'd':
- op = DIGIT;
- join_D_and_d:
- {
- U8 offset = get_regex_charset(RExC_flags);
- if (offset == REGEX_UNICODE_CHARSET) {
- offset = REGEX_DEPENDS_CHARSET;
- }
- else if (offset == REGEX_ASCII_MORE_RESTRICTED_CHARSET) {
- offset = REGEX_ASCII_RESTRICTED_CHARSET;
- }
- op += offset;
- }
- ret = reg_node(pRExC_state, op);
- *flagp |= HASWIDTH|SIMPLE;
- goto finish_meta_pat;
+ arg = ANYOF_DIGIT;
+ goto join_posix;
+
case 'R':
ret = reg_node(pRExC_state, LNBREAK);
*flagp |= HASWIDTH|SIMPLE;
goto finish_meta_pat;
- case 'h':
- ret = reg_node(pRExC_state, HORIZWS);
- *flagp |= HASWIDTH|SIMPLE;
- goto finish_meta_pat;
+
case 'H':
- ret = reg_node(pRExC_state, NHORIZWS);
- *flagp |= HASWIDTH|SIMPLE;
- goto finish_meta_pat;
- case 'v':
- ret = reg_node(pRExC_state, VERTWS);
- *flagp |= HASWIDTH|SIMPLE;
- goto finish_meta_pat;
+ invert = 1;
+ /* FALLTHROUGH */
+ case 'h':
+ arg = ANYOF_BLANK;
+ op = POSIXU;
+ goto join_posix_op_known;
+
case 'V':
- ret = reg_node(pRExC_state, NVERTWS);
+ invert = 1;
+ /* FALLTHROUGH */
+ case 'v':
+ arg = ANYOF_VERTWS;
+ op = POSIXU;
+ goto join_posix_op_known;
+
+ case 'S':
+ invert = 1;
+ /* FALLTHROUGH */
+ case 's':
+ arg = ANYOF_SPACE;
+
+ join_posix:
+
+ op = POSIXD + get_regex_charset(RExC_flags);
+ if (op > POSIXA) { /* /aa is same as /a */
+ op = POSIXA;
+ }
+
+ join_posix_op_known:
+
+ if (invert) {
+ op += NPOSIXD - POSIXD;
+ }
+
+ ret = reg_node(pRExC_state, op);
+ if (! SIZE_ONLY) {
+ FLAGS(ret) = namedclass_to_classnum(arg);
+ }
+
*flagp |= HASWIDTH|SIMPLE;
+ /* FALL THROUGH */
+
finish_meta_pat:
nextchar(pRExC_state);
Set_Node_Length(ret, 2); /* MJD */
&PL_sv_undef, 1, 0);
PL_utf8_foldable =
_get_swash_invlist(swash);
- SvREFCNT_dec(swash);
+ SvREFCNT_dec_NN(swash);
}
if (_invlist_contains_cp(PL_utf8_foldable,
ender))
return namedclass;
}
-/* Generate the code to add a posix character <class> to the bracketed
- * character class given by <node>. (<node> is needed only under locale rules)
- * destlist is the inversion list for non-locale rules that this class is
- * to be added to
- * sourcelist is the ASCII-range inversion list to add under /a rules
- * Xpropertyname is the name to add to <run_time_list> of the property to
- * specify the code points above Latin1 that will have to be
- * determined at run-time
- * run_time_list is a SV* that contains text names of properties that are to
- * be computed at run time. This concatenates <Xpropertyname>
- * to it, appropriately */
-#define DO_POSIX_LATIN1_ONLY_KNOWN_L1_RESOLVED(node, class, destlist, sourcelist, \
- Xpropertyname, run_time_list) \
- /* If not /a matching, there are going to be code points we will have \
- * to defer to runtime to look-up */ \
- if (! AT_LEAST_ASCII_RESTRICTED) { \
- Perl_sv_catpvf(aTHX_ run_time_list, "+utf8::%s\n", Xpropertyname); \
- } \
- if (LOC) { \
- ANYOF_CLASS_SET(node, class); \
- } \
- else { \
- _invlist_union(destlist, sourcelist, &destlist); \
- } \
-
-/* Like DO_POSIX_LATIN1_ONLY_KNOWN, but for the complement. A combination of
- * this and DO_N_POSIX. Sets <matches_above_unicode> only if it can; unchanged
- * otherwise */
-#define DO_N_POSIX_LATIN1_ONLY_KNOWN(node, class, destlist, sourcelist, \
- l1_sourcelist, Xpropertyname, run_time_list, matches_above_unicode) \
- if (AT_LEAST_ASCII_RESTRICTED) { \
- _invlist_union_complement_2nd(destlist, sourcelist, &destlist); \
- } \
- else { \
- Perl_sv_catpvf(aTHX_ run_time_list, "!utf8::%s\n", Xpropertyname); \
- matches_above_unicode = TRUE; \
- if (LOC) { \
- ANYOF_CLASS_SET(node, namedclass); \
- } \
- else { \
- SV* scratch_list = NULL; \
- _invlist_subtract(PL_Latin1, l1_sourcelist, &scratch_list); \
- if (! destlist) { \
- destlist = scratch_list; \
- } \
- else { \
- _invlist_union(destlist, scratch_list, &destlist); \
- SvREFCNT_dec(scratch_list); \
- } \
- if (DEPENDS_SEMANTICS) { \
- ANYOF_FLAGS(node) |= ANYOF_NON_UTF8_LATIN1_ALL; \
- } \
- } \
- }
/* The names of properties whose definitions are not known at compile time are
* stored in this SV, after a constant heading. So if the length has been
if (UCHARAT(RExC_parse) == '^') {
RExC_parse++;
n--;
- value = value == 'p' ? 'P' : 'p'; /* toggle */
+ /* toggle. (The rhs xor gets the single bit that
+ * differs between P and p; the other xor inverts just
+ * that bit) */
+ value ^= 'P' ^ 'p';
+
while (isSPACE(UCHARAT(RExC_parse))) {
RExC_parse++;
n--;
/* Look up the property name, and get its swash and
* inversion list, if the property is found */
if (swash) {
- SvREFCNT_dec(swash);
+ SvREFCNT_dec_NN(swash);
}
swash = _core_swash_init("utf8", name, &PL_sv_undef,
1, /* binary */
);
if (! swash || ! (invlist = _get_swash_invlist(swash))) {
if (swash) {
- SvREFCNT_dec(swash);
+ SvREFCNT_dec_NN(swash);
swash = NULL;
}
/* The swash can't be used as-is, because we've
* inverted things; delay removing it to here after
* have copied its invlist above */
- SvREFCNT_dec(swash);
+ SvREFCNT_dec_NN(swash);
swash = NULL;
}
else {
switch ((I32)namedclass) {
+ case ANYOF_DIGIT:
+ l1_source = ascii_source;
+ /* FALL THROUGH */
+
case ANYOF_ALPHANUMERIC: /* C's alnum, in contrast to \w */
case ANYOF_ALPHA:
case ANYOF_GRAPH:
case ANYOF_UPPER:
case ANYOF_WORDCHAR:
if ( ! PL_utf8_swash_ptrs[classnum]) {
- /* First, resolve whether to use the ASCII-only list or
- * the L1 list */
- DO_POSIX_LATIN1_ONLY_KNOWN_L1_RESOLVED(ret, namedclass, posixes,
- ((AT_LEAST_ASCII_RESTRICTED) ? ascii_source : l1_source),
- Xname, listsv);
- break;
+
+ /* If not /a matching, there are code points we don't
+ * know at compile time. Arrange for the unknown
+ * matches to be loaded at run-time, if needed */
+ if (! AT_LEAST_ASCII_RESTRICTED) {
+ Perl_sv_catpvf(aTHX_ listsv, "+utf8::%s\n", Xname);
+ }
+ if (LOC) { /* Under locale, set run-time lookup */
+ ANYOF_CLASS_SET(ret, namedclass);
+ }
+ else {
+ /* Add the current class's code points to the
+ * running total */
+ _invlist_union(posixes,
+ (AT_LEAST_ASCII_RESTRICTED)
+ ? ascii_source
+ : l1_source,
+ &posixes);
+ }
+ break;
}
if (! PL_XPosix_ptrs[classnum]) {
PL_XPosix_ptrs[classnum]
case ANYOF_PSXSPC:
case ANYOF_SPACE:
case ANYOF_XDIGIT:
- if (LOC) {
+ if (! LOC) {
+ /* For non-locale, just add it to any existing list */
+ _invlist_union(posixes,
+ (AT_LEAST_ASCII_RESTRICTED)
+ ? ascii_source
+ : PL_XPosix_ptrs[classnum],
+ &posixes);
+ }
+ else { /* Locale */
SV* scratch_list = NULL;
/* For above Latin1 code points, we use the full
}
else {
_invlist_union(posixes, scratch_list, &posixes);
- SvREFCNT_dec(scratch_list);
+ SvREFCNT_dec_NN(scratch_list);
}
#ifndef HAS_ISBLANK
}
#endif
}
- else {
- /* For non-locale, just add it to any existing list */
- _invlist_union(posixes,
- (AT_LEAST_ASCII_RESTRICTED)
- ? ascii_source
- : PL_XPosix_ptrs[classnum],
- &posixes);
- }
break;
case ANYOF_NDIGIT:
case ANYOF_NUPPER:
case ANYOF_NWORDCHAR:
if ( ! PL_utf8_swash_ptrs[classnum]) {
- DO_N_POSIX_LATIN1_ONLY_KNOWN(ret, namedclass, posixes,
- ascii_source, l1_source, Xname, listsv,
- runtime_posix_matches_above_Unicode);
- break;
+ if (AT_LEAST_ASCII_RESTRICTED) {
+ /* Under /a should match everything above ASCII,
+ * and the complement of the set's ASCII matches */
+ _invlist_union_complement_2nd(posixes, ascii_source,
+ &posixes);
+ }
+ else {
+ /* Arrange for the unknown matches to be loaded at
+ * run-time, if needed */
+ Perl_sv_catpvf(aTHX_ listsv, "!utf8::%s\n", Xname);
+ runtime_posix_matches_above_Unicode = TRUE;
+ if (LOC) {
+ ANYOF_CLASS_SET(ret, namedclass);
+ }
+ else {
+
+ /* We want to match everything in Latin1,
+ * except those things that l1_source matches
+ * */
+ SV* scratch_list = NULL;
+ _invlist_subtract(PL_Latin1, l1_source,
+ &scratch_list);
+
+ /* Add the list from this class to the running
+ * total */
+ if (! posixes) {
+ posixes = scratch_list;
+ }
+ else {
+ _invlist_union(posixes, scratch_list,
+ &posixes);
+ SvREFCNT_dec_NN(scratch_list);
+ }
+ if (DEPENDS_SEMANTICS) {
+ ANYOF_FLAGS(ret)
+ |= ANYOF_NON_UTF8_LATIN1_ALL;
+ }
+ }
+ }
+ break;
}
if (! PL_XPosix_ptrs[classnum]) {
PL_XPosix_ptrs[classnum]
case ANYOF_NPSXSPC:
case ANYOF_NSPACE:
case ANYOF_NXDIGIT:
- if (LOC) {
+ if (! LOC) {
+ _invlist_union_complement_2nd(
+ posixes,
+ (AT_LEAST_ASCII_RESTRICTED)
+ ? ascii_source
+ : PL_XPosix_ptrs[classnum],
+ &posixes);
+ /* Under /d, everything in the upper half of the Latin1
+ * range matches this complement */
+ if (DEPENDS_SEMANTICS) {
+ ANYOF_FLAGS(ret) |= ANYOF_NON_UTF8_LATIN1_ALL;
+ }
+ }
+ else { /* Locale */
SV* scratch_list = NULL;
_invlist_subtract(PL_AboveLatin1,
PL_XPosix_ptrs[classnum],
}
else {
_invlist_union(posixes, scratch_list, &posixes);
- SvREFCNT_dec(scratch_list);
+ SvREFCNT_dec_NN(scratch_list);
}
#ifndef HAS_ISBLANK
if (namedclass != ANYOF_NBLANK) {
_invlist_subtract(PL_Latin1, ascii_source,
&scratch_list);
_invlist_union(posixes, scratch_list, &posixes);
- SvREFCNT_dec(scratch_list);
+ SvREFCNT_dec_NN(scratch_list);
}
#endif
}
- else {
- _invlist_union_complement_2nd(
- posixes,
- (AT_LEAST_ASCII_RESTRICTED)
- ? ascii_source
- : PL_XPosix_ptrs[classnum],
- &posixes);
- /* Under /d, everything in the upper half of the Latin1
- * range matches this complement */
- if (DEPENDS_SEMANTICS) {
- ANYOF_FLAGS(ret) |= ANYOF_NON_UTF8_LATIN1_ALL;
- }
- }
break;
case ANYOF_ASCII:
#endif
break;
- case ANYOF_DIGIT:
- /* There are no digits in the Latin1 range outside of
- * ASCII, so call the macro that doesn't have to resolve
- * them */
- DO_POSIX_LATIN1_ONLY_KNOWN_L1_RESOLVED(ret, namedclass, posixes,
- ascii_source, Xname, listsv);
- break;
-
case ANYOF_HORIZWS:
/* For these, we use the cp_list, as neither /d nor /l make
* a difference in what these match. There would be
RExC_parse = save_parse;
RExC_end = save_end;
RExC_in_multi_char_class = 0;
- SvREFCNT_dec(multi_char_matches);
- SvREFCNT_dec(listsv);
+ SvREFCNT_dec_NN(multi_char_matches);
+ SvREFCNT_dec_NN(listsv);
return ret;
}
if (namedclass > OOB_NAMEDCLASS) { /* this is a named class, like \w or
[:digit:] or \p{foo} */
- /* Certain named classes have equivalents that can appear outside a
- * character class, e.g. \w, \H. We use these instead of a
- * character class. */
+ /* All named classes are mapped into POSIXish nodes, with its FLAG
+ * argument giving which class it is */
switch ((I32)namedclass) {
- U8 offset;
-
- /* The first group is for node types that depend on the charset
- * modifier to the regex. We first calculate the base node
- * type, and if it should be inverted */
-
- case ANYOF_NWORDCHAR:
- invert = ! invert;
- /* FALLTHROUGH */
- case ANYOF_WORDCHAR:
- op = ALNUM;
- goto join_charset_classes;
-
- case ANYOF_NSPACE:
- invert = ! invert;
- /* FALLTHROUGH */
- case ANYOF_SPACE:
- op = SPACE;
- goto join_charset_classes;
-
- case ANYOF_NDIGIT:
- invert = ! invert;
- /* FALLTHROUGH */
- case ANYOF_DIGIT:
- op = DIGIT;
-
- join_charset_classes:
-
- /* Now that we have the base node type, we take advantage
- * of the enum ordering of the charset modifiers to get the
- * exact node type, For example the base SPACE also has
- * SPACEL, SPACEU, and SPACEA */
-
- offset = get_regex_charset(RExC_flags);
-
- /* /aa is the same as /a for these */
- if (offset == REGEX_ASCII_MORE_RESTRICTED_CHARSET) {
- offset = REGEX_ASCII_RESTRICTED_CHARSET;
- }
- else if (op == DIGIT && offset == REGEX_UNICODE_CHARSET) {
- offset = REGEX_DEPENDS_CHARSET; /* There is no DIGITU */
- }
-
- op += offset;
-
- /* The number of varieties of each of these is the same,
- * hence, so is the delta between the normal and
- * complemented nodes */
- if (invert) {
- op += NALNUM - ALNUM;
- }
- *flagp |= HASWIDTH|SIMPLE;
+ case ANYOF_UNIPROP:
break;
- /* The second group doesn't depend of the charset modifiers.
- * We just have normal and complemented */
+ /* These don't depend on the charset modifiers. They always
+ * match under /u rules */
case ANYOF_NHORIZWS:
- invert = ! invert;
- /* FALLTHROUGH */
case ANYOF_HORIZWS:
- is_horizws:
- op = (invert) ? NHORIZWS : HORIZWS;
- *flagp |= HASWIDTH|SIMPLE;
- break;
+ namedclass = ANYOF_BLANK + namedclass - ANYOF_HORIZWS;
+ /* FALLTHROUGH */
case ANYOF_NVERTWS:
- invert = ! invert;
- /* FALLTHROUGH */
case ANYOF_VERTWS:
- op = (invert) ? NVERTWS : VERTWS;
- *flagp |= HASWIDTH|SIMPLE;
- break;
-
- case ANYOF_UNIPROP:
- break;
-
- case ANYOF_NBLANK:
- invert = ! invert;
- /* FALLTHROUGH */
- case ANYOF_BLANK:
- if (AT_LEAST_UNI_SEMANTICS && ! AT_LEAST_ASCII_RESTRICTED) {
- goto is_horizws;
+ op = POSIXU;
+ goto join_posix;
+
+ /* The actual POSIXish node for all the rest depends on the
+ * charset modifier. The ones in the first set depend only on
+ * ASCII or, if available on this platform, locale */
+ case ANYOF_ASCII:
+ case ANYOF_NASCII:
+#ifdef HAS_ISASCII
+ op = (LOC) ? POSIXL : POSIXA;
+#else
+ op = POSIXA;
+#endif
+ goto join_posix;
+
+ case ANYOF_LOWER:
+ case ANYOF_NLOWER:
+ case ANYOF_UPPER:
+ case ANYOF_NUPPER:
+ /* under /a could be alpha */
+ if (FOLD) {
+ if (ASCII_RESTRICTED) {
+ namedclass = ANYOF_ALPHA + (namedclass % 2);
+ }
+ else if (! LOC) {
+ break;
+ }
}
/* FALLTHROUGH */
+
+ /* The rest have more possibilities depending on the charset. We
+ * take advantage of the enum ordering of the charset modifiers to
+ * get the exact node type, */
default:
- /* A generic posix class. All the /a ones can be handled
- * by the POSIXA opcode. And all are closed under folding
- * in the ASCII range, so FOLD doesn't matter */
- if (AT_LEAST_ASCII_RESTRICTED
- || (! LOC && namedclass == ANYOF_ASCII))
+ op = POSIXD + get_regex_charset(RExC_flags);
+ if (op > POSIXA) { /* /aa is same as /a */
+ op = POSIXA;
+ }
+#ifndef HAS_ISBLANK
+ if (op == POSIXL
+ && (namedclass == ANYOF_BLANK
+ || namedclass == ANYOF_NBLANK))
{
- /* The odd numbered ones are the complements of the
- * next-lower even number one */
- if (namedclass % 2 == 1) {
- invert = ! invert;
- namedclass--;
- }
- arg = namedclass_to_classnum(namedclass);
- op = (invert) ? NPOSIXA : POSIXA;
+ op = POSIXA;
}
+#endif
+
+ join_posix:
+ /* The odd numbered ones are the complements of the
+ * next-lower even number one */
+ if (namedclass % 2 == 1) {
+ invert = ! invert;
+ namedclass--;
+ }
+ arg = namedclass_to_classnum(namedclass);
break;
}
}
else if (! LOC) { /* locale could vary these */
if (prevvalue == '0') {
if (value == '9') {
- op = (invert) ? NDIGITA : DIGITA;
- *flagp |= HASWIDTH|SIMPLE;
+ arg = _CC_DIGIT;
+ op = POSIXA;
}
}
}
}
else {
RExC_emit = (regnode *)orig_emit;
+ if (PL_regkind[op] == POSIXD) {
+ if (invert) {
+ op += NPOSIXD - POSIXD;
+ }
+ }
}
ret = reg_node(pRExC_state, op);
RExC_parse = (char *) cur_parse;
SvREFCNT_dec(posixes);
- SvREFCNT_dec(listsv);
+ SvREFCNT_dec_NN(listsv);
SvREFCNT_dec(cp_list);
return ret;
}
SV* swash = swash_init("utf8", "_Perl_Any_Folds",
&PL_sv_undef, 1, 0);
PL_utf8_foldable = _get_swash_invlist(swash);
- SvREFCNT_dec(swash);
+ SvREFCNT_dec_NN(swash);
}
/* This is a hash that for a particular fold gives all characters
}
}
}
- SvREFCNT_dec(fold_intersection);
+ SvREFCNT_dec_NN(fold_intersection);
}
/* And combine the result (if any) with any inversion list from posix
if (! DEPENDS_SEMANTICS) {
if (cp_list) {
_invlist_union(cp_list, posixes, &cp_list);
- SvREFCNT_dec(posixes);
+ SvREFCNT_dec_NN(posixes);
}
else {
cp_list = posixes;
&posixes);
if (cp_list) {
_invlist_union(cp_list, posixes, &cp_list);
- SvREFCNT_dec(posixes);
+ SvREFCNT_dec_NN(posixes);
}
else {
cp_list = posixes;
if (depends_list) {
_invlist_union(depends_list, nonascii_but_latin1_properties,
&depends_list);
- SvREFCNT_dec(nonascii_but_latin1_properties);
+ SvREFCNT_dec_NN(nonascii_but_latin1_properties);
}
else {
depends_list = nonascii_but_latin1_properties;
}
_invlist_union(properties, cp_list, &cp_list);
- SvREFCNT_dec(properties);
+ SvREFCNT_dec_NN(properties);
}
else {
cp_list = properties;
}
if (warn_super) {
- ANYOF_FLAGS(ret) |= ANYOF_WARN_SUPER;
+ OP(ret) = ANYOF_WARN_SUPER;
}
}
/* Any swash can't be used as-is, because we've inverted things */
if (swash) {
- SvREFCNT_dec(swash);
+ SvREFCNT_dec_NN(swash);
swash = NULL;
}
&& ! (ANYOF_FLAGS(ret) & ANYOF_CLASS)
&& ! HAS_NONLOCALE_RUNTIME_PROPERTY_DEFINITION)
{
- UV start, end;
- U8 op = END; /* The optimzation node-type */
+ UV start, end;
+ U8 op = END; /* The optimzation node-type */
const char * cur_parse= RExC_parse;
- invlist_iterinit(cp_list);
- if (! invlist_iternext(cp_list, &start, &end)) {
+ invlist_iterinit(cp_list);
+ if (! invlist_iternext(cp_list, &start, &end)) {
/* Here, the list is empty. This happens, for example, when a
* Unicode property is the only thing in the character class, and
SV* swash = swash_init("utf8", "_Perl_Any_Folds",
&PL_sv_undef, 1, 0);
PL_utf8_foldable = _get_swash_invlist(swash);
- SvREFCNT_dec(swash);
+ SvREFCNT_dec_NN(swash);
}
if (_invlist_contains_cp(PL_utf8_foldable, value)) {
op = EXACT;
RExC_naughty++;
}
}
+ invlist_iterfinish(cp_list);
if (op != END) {
RExC_parse = (char *)orig_parse;
alloc_maybe_populate_EXACT(pRExC_state, ret, flagp, 0, value);
}
- SvREFCNT_dec(cp_list);
- SvREFCNT_dec(listsv);
+ SvREFCNT_dec_NN(cp_list);
+ SvREFCNT_dec_NN(listsv);
return ret;
}
}
}
}
}
+ invlist_iterfinish(cp_list);
/* Done with loop; remove any code points that are in the bitmap from
* <cp_list> */
/* If have completely emptied it, remove it completely */
if (_invlist_len(cp_list) == 0) {
- SvREFCNT_dec(cp_list);
+ SvREFCNT_dec_NN(cp_list);
cp_list = NULL;
}
}
if (depends_list) {
if (cp_list) {
_invlist_union(cp_list, depends_list, &cp_list);
- SvREFCNT_dec(depends_list);
+ SvREFCNT_dec_NN(depends_list);
}
else {
cp_list = depends_list;
/* If there is a swash and more than one element, we can't use the swash in
* the optimization below. */
if (swash && element_count > 1) {
- SvREFCNT_dec(swash);
+ SvREFCNT_dec_NN(swash);
swash = NULL;
}
&& ! HAS_NONLOCALE_RUNTIME_PROPERTY_DEFINITION)
{
ARG_SET(ret, ANYOF_NONBITMAP_EMPTY);
- SvREFCNT_dec(listsv);
+ SvREFCNT_dec_NN(listsv);
}
else {
/* av[0] stores the character class description in its textual form:
av_store(av, 0, (HAS_NONLOCALE_RUNTIME_PROPERTY_DEFINITION)
? listsv
- : (SvREFCNT_dec(listsv), &PL_sv_undef));
+ : (SvREFCNT_dec_NN(listsv), &PL_sv_undef));
if (swash) {
av_store(av, 1, swash);
- SvREFCNT_dec(cp_list);
+ SvREFCNT_dec_NN(cp_list);
}
else {
av_store(av, 1, NULL);
Safefree(origs);
}
- SvREFCNT_dec(lv);
+ SvREFCNT_dec_NN(lv);
}
}
ret_x->sv_u.svu_rx = temp->sv_any;
temp->sv_any = NULL;
SvFLAGS(temp) = (SvFLAGS(temp) & ~SVTYPEMASK) | SVt_NULL;
- SvREFCNT_dec(temp);
+ SvREFCNT_dec_NN(temp);
/* SvCUR still resides in the xpvlv struct, so the regexp copy-
ing below will not set it. */
SvCUR_set(ret_x, SvCUR(rx));