Commit f553cc2db2 for perl
commit f553cc2db21c4db18c006e20854be745bca85175
Author: Yves Orton <demerphq@gmail.com>
Date: Tue Oct 27 21:37:23 2026 +0100
regcomp: name ANYOF properties
Name the auxiliary data, outside-bitmap flags, regex-set inversion list,
excluded byte, first byte, and UTF-8 string length stored by ANYOF
nodes. This separates the meanings of shared node storage without
changing their layout or matching behavior.
diff --git a/regcomp.c b/regcomp.c
index a385ee6fb2..28c4471675 100644
--- a/regcomp.c
+++ b/regcomp.c
@@ -8964,7 +8964,7 @@ redo_curchar:
{
vFAIL("Expecting interpolated extended charclass");
}
- resultant_invlist = (SV *) ARGp(REGNODE_p(node));
+ resultant_invlist = REGEX_SET_INVLIST(REGNODE_p(node));
current = invlist_clone(resultant_invlist, NULL);
SvREFCNT_dec(resultant_invlist);
@@ -12637,7 +12637,7 @@ Perl_set_ANYOF_arg(pTHX_ RExC_state_t* const pRExC_state,
* 1) there is no list of code points matched outside the bitmap
*/
if (! cp_list) {
- ARG1u_SET(node, ANYOF_MATCHES_NONE_OUTSIDE_BITMAP_VALUE);
+ ANYOF_MATCHES_NONE_OUTSIDE_BITMAP_SET(node);
return;
}
@@ -12646,7 +12646,7 @@ Perl_set_ANYOF_arg(pTHX_ RExC_state_t* const pRExC_state,
&& invlist_highest_range_start(cp_list)
<= NUM_ANYOF_CODE_POINTS)
{
- ARG1u_SET(node, ANYOF_MATCHES_ALL_OUTSIDE_BITMAP_VALUE);
+ ANYOF_MATCHES_ALL_OUTSIDE_BITMAP_SET(node);
return;
}
@@ -12719,7 +12719,7 @@ Perl_set_ANYOF_arg(pTHX_ RExC_state_t* const pRExC_state,
/* Here, the existence and contents of both compile-time lists
* are identical between the new and existing data. Re-use the
* existing one */
- ARG1u_SET(node, i);
+ ANYOF_AUX_DATA_SLOT_SET(node, i);
return;
} /* end of loop through existing classes */
}
@@ -12751,7 +12751,7 @@ Perl_set_ANYOF_arg(pTHX_ RExC_state_t* const pRExC_state,
rv = newRV_noinc(MUTABLE_SV(av));
n = reg_add_data(pRExC_state, STR_WITH_LEN("s"));
RExC_rxi->data->data[n] = (void*)rv;
- ARG1u_SET(node, n);
+ ANYOF_AUX_DATA_SLOT_SET(node, n);
}
#endif /* PERL_RE_BUILD_AUX */
@@ -12809,7 +12809,7 @@ Perl_get_re_gclass_aux_data(pTHX_ const regexp *prog, const regnode* node, bool
const struct reg_data * const data = prog ? progi->data : NULL;
if (data && data->count) {
- const U32 n = ARG1u(node);
+ const U32 n = ANYOF_AUX_DATA_SLOT(node);
if (data->what[n] == 's') {
SV * const rv = MUTABLE_SV(data->data[n]);
diff --git a/regcomp.h b/regcomp.h
index 2cb0d6a35c..acdb828550 100644
--- a/regcomp.h
+++ b/regcomp.h
@@ -612,6 +612,28 @@ struct regnode_ssc {
ARG2u_SET((p), (val)); \
} STMT_END
+#define ANYOF_AUX_DATA_SLOT(p) \
+ (assert(ANYOF_HAS_AUX(p)), PREVENT_LVALUE(ARG1u(p)))
+#define ANYOF_AUX_DATA_SLOT_SET(p, val) STMT_START { \
+ assert(((val) & ANYOF_ONLY_HAS_BITMAP_MASK) != \
+ ANYOF_ONLY_HAS_BITMAP_MASK); \
+ ARG1u_SET((p), (val)); \
+} STMT_END
+
+#define NEXACTb_BYTE(p) \
+ (assert(OP(p) == NEXACTb), PREVENT_LVALUE(ARG1u(p)))
+#define NEXACTb_BYTE_SET(p, val) STMT_START { \
+ assert(OP(p) == NEXACTb); \
+ ARG1u_SET((p), (val)); \
+} STMT_END
+
+#define REGEX_SET_INVLIST(p) \
+ (assert(OP(p) == REGEX_SET), ARGp(p))
+#define REGEX_SET_INVLIST_SET(p, val) STMT_START { \
+ assert(OP(p) == REGEX_SET); \
+ ARGp_SET((p), (val)); \
+} STMT_END
+
#define REGNODE_NEXT_OFFSET(p) \
(PREVENT_LVALUE((REGNODE_OFF_BY_ARG(OP(p)) ? ARG1u(p) : NEXT_OFF(p))))
#define REGNODE_NEXT_OFFSET_SET(p, val) STMT_START { \
@@ -717,6 +739,10 @@ struct regnode_ssc {
} STMT_END
#define IS_LOOKBEHIND(p) (LOOKBEHIND_MAX_CHARS(p) != 0)
+#define ANYOF_MATCHES_ALL_OUTSIDE_BITMAP_SET(p) \
+ ARG1u_SET((p), ANYOF_MATCHES_ALL_OUTSIDE_BITMAP_VALUE)
+#define ANYOF_MATCHES_NONE_OUTSIDE_BITMAP_SET(p) \
+ ARG1u_SET((p), ANYOF_MATCHES_NONE_OUTSIDE_BITMAP_VALUE)
/* the following define was set to 0xde in 075abff3
* as part of some linting logic. I have set it to 0
diff --git a/regcomp_debug.c b/regcomp_debug.c
index f0ebf0da9b..04db7354c3 100644
--- a/regcomp_debug.c
+++ b/regcomp_debug.c
@@ -970,14 +970,16 @@ Perl_regprop(pTHX_ const regexp *prog, SV *sv, const regnode *o, const regmatch_
if (op == ANYOFHs) {
sv_catpvf(sv, " (Leading UTF-8 bytes = %s",
byte_dump_string_((U8 *) ((struct regnode_anyofhs *) o)->string,
- FLAGS(o), 1));
+ STR_LEN_U8(o), 1));
}
else if (REGNODE_TYPE(op) != ANYOF) {
- U8 lowest = (op != ANYOFHr)
- ? FLAGS(o)
- : LOWEST_ANYOF_HRx_BYTE(FLAGS(o));
+ U8 lowest = op == ANYOFHr
+ ? LOWEST_ANYOF_HRx_BYTE(ANYOF_FLAGS(o))
+ : (op == ANYOFH || op == ANYOFR)
+ ? ANYOF_FLAGS(o)
+ : FIRST_BYTE(o);
U8 highest = (op == ANYOFHr)
- ? HIGHEST_ANYOF_HRx_BYTE(FLAGS(o))
+ ? HIGHEST_ANYOF_HRx_BYTE(ANYOF_FLAGS(o))
: (op == ANYOFH || op == ANYOFR)
? 0xFF
: lowest;
@@ -1010,7 +1012,7 @@ Perl_regprop(pTHX_ const regexp *prog, SV *sv, const regnode *o, const regmatch_
}
else if (op == NEXACTb) {
sv_catpvf(sv, "[%s%c%s]",
- PL_colors[0], (int) ARG1u(o), PL_colors[1]);
+ PL_colors[0], (int) NEXACTb_BYTE(o), PL_colors[1]);
}
else if (k == ANYOFHbbm) {
SV * cp_list = get_ANYOFHbbm_contents(o);
diff --git a/regcomp_study.c b/regcomp_study.c
index e525048e1e..6706d67547 100644
--- a/regcomp_study.c
+++ b/regcomp_study.c
@@ -379,7 +379,7 @@ Perl_ssc_init(pTHX_ const RExC_state_t *pRExC_state, regnode_ssc *ssc)
Zero(ssc, 1, regnode_ssc);
set_ANYOF_SYNTHETIC(ssc);
- ARG1u_SET(ssc, ANYOF_MATCHES_ALL_OUTSIDE_BITMAP_VALUE);
+ ANYOF_MATCHES_ALL_OUTSIDE_BITMAP_SET(ssc);
ssc_anything(ssc);
/* If any portion of the regex is to operate under locale rules that aren't
@@ -456,7 +456,7 @@ S_get_ANYOF_cp_list_for_ssc(pTHX_ const RExC_state_t *pRExC_state,
invlist = add_range_to_invlist_(invlist, NUM_ANYOF_CODE_POINTS, UV_MAX);
}
else if (ANYOF_HAS_AUX(node)) {
- const U32 n = ARG1u(node);
+ const U32 n = ANYOF_AUX_DATA_SLOT(node);
SV * const rv = MUTABLE_SV(RExC_rxi->data->data[n]);
AV * const av = AV_FROM_REF(rv);
SV **const ary = AvARRAY(av);
@@ -3156,7 +3156,7 @@ Perl_study_chunk(pTHX_
{
SV* Nb_invlist = new_invlist_(2);
Nb_invlist = add_cp_to_invlist(Nb_invlist,
- (U8) ARG1u(scan));
+ (U8) NEXACTb_BYTE(scan));
if (flags & SCF_DO_STCLASS_OR) {
ssc_union(data->start_class, Nb_invlist, true);
}
diff --git a/regexec.c b/regexec.c
index a02c653278..116021a9be 100644
--- a/regexec.c
+++ b/regexec.c
@@ -2669,13 +2669,13 @@ S_find_byclass(pTHX_ regexp * prog, const regnode *c, char *s,
case NEXACTb_tb_pb:
case NEXACTb_tb_p8:
REXEC_FBC_NON_UTF8_FIND_NEXT_SCAN(
- find_span_end((U8 *) s, (U8 *) strend, (U8) ARG1u(c)));
+ find_span_end((U8 *) s, (U8 *) strend, (U8) NEXACTb_BYTE(c)));
break;
case NEXACTb_t8_pb:
case NEXACTb_t8_p8:
REXEC_FBC_UTF8_CLASS_SCAN(
- ! (UTF8SKIP(s) == 1 && (U8) *s == (U8) ARG1u(c)));
+ ! (UTF8SKIP(s) == 1 && (U8) *s == (U8) NEXACTb_BYTE(c)));
break;
/* These nodes all require at least one code point to be in UTF-8 to
@@ -2711,7 +2711,7 @@ S_find_byclass(pTHX_ regexp * prog, const regnode *c, char *s,
case ANYOFHb_t8_p8:
{
/* We know what the first byte of any matched string should be. */
- U8 first_byte = FLAGS(c);
+ U8 first_byte = FIRST_BYTE(c);
anyofh_list = GET_ANYOFH_INVLIST(prog, c);
REXEC_FBC_FIND_NEXT_UTF8_BYTE_SCAN(first_byte,
@@ -2726,7 +2726,7 @@ S_find_byclass(pTHX_ regexp * prog, const regnode *c, char *s,
case ANYOFHbbm_t8_p8:
{
/* We know what the first byte of any matched string should be. */
- U8 first_byte = FLAGS(c);
+ U8 first_byte = FIRST_BYTE(c);
/* And a bitmap defines all the legal 2nd byte matches */
REXEC_FBC_FIND_NEXT_UTF8_BYTE_SCAN(first_byte,
@@ -2755,7 +2755,7 @@ S_find_byclass(pTHX_ regexp * prog, const regnode *c, char *s,
REXEC_FBC_FIND_NEXT_UTF8_STRING_SCAN(
((struct regnode_anyofhs *) c)->string,
/* Note FLAGS is the string length in this regnode */
- ((struct regnode_anyofhs *) c)->string + FLAGS(c),
+ ((struct regnode_anyofhs *) c)->string + STR_LEN_U8(c),
invlist_contains_cp_(anyofh_list,
utf8_to_uv_or_die((U8 *) s,
(U8 *) strend,
@@ -2787,7 +2787,7 @@ S_find_byclass(pTHX_ regexp * prog, const regnode *c, char *s,
case ANYOFRb_t8_pb:
case ANYOFRb_t8_p8:
{ /* We know what the first byte of any matched string should be */
- U8 first_byte = FLAGS(c);
+ U8 first_byte = FIRST_BYTE(c);
REXEC_FBC_FIND_NEXT_UTF8_BYTE_SCAN(first_byte,
withinCOUNT(utf8_to_uv_or_die((U8 *) s,
@@ -8369,7 +8369,7 @@ S_regmatch(pTHX_ regmatch_info *reginfo, char *startpos, regnode *prog)
case NEXACTb: /* /[^x]/ : single excluded byte */
if ( NEXTCHR_IS_EOS
- || (U8) ARG1u(scan) == UCHARAT(locinput)
+ || (U8) NEXACTb_BYTE(scan) == UCHARAT(locinput)
|| locinput >= loceol)
{
sayNO;
@@ -8440,8 +8440,8 @@ S_regmatch(pTHX_ regmatch_info *reginfo, char *startpos, regnode *prog)
case ANYOFHs:
if ( ! utf8_target
|| NEXTCHR_IS_EOS
- || loceol - locinput < FLAGS(scan)
- || memNE(locinput, ((struct regnode_anyofhs *) scan)->string, FLAGS(scan))
+ || loceol - locinput < STR_LEN_U8(scan)
+ || memNE(locinput, ((struct regnode_anyofhs *) scan)->string, STR_LEN_U8(scan))
|| ! (anyofh_list = GET_ANYOFH_INVLIST(rex, scan))
|| ! invlist_contains_cp_(anyofh_list,
utf8_to_uv_or_die((U8 *) locinput,
@@ -11419,7 +11419,7 @@ S_regrepeat(pTHX_ regexp *prog, char **startposp, const regnode *p,
case NEXACTb_t8:
{
- const U8 nchar = (U8) ARG1u(p);
+ const U8 nchar = (U8) NEXACTb_BYTE(p);
while ( hardcount < max
&& scan < this_eol
&& (UTF8SKIP(scan) != 1 || (U8) *scan != nchar))
@@ -11432,7 +11432,7 @@ S_regrepeat(pTHX_ regexp *prog, char **startposp, const regnode *p,
case NEXACTb_tb:
{
- char * found = (char *) memchr(scan, (U8) ARG1u(p),
+ char * found = (char *) memchr(scan, (U8) NEXACTb_BYTE(p),
this_eol - scan);
scan = found ? found : this_eol;
}
@@ -11509,8 +11509,8 @@ S_regrepeat(pTHX_ regexp *prog, char **startposp, const regnode *p,
case ANYOFHs_t8:
anyofh_list = GET_ANYOFH_INVLIST(prog, p);
while ( hardcount < max
- && scan + FLAGS(p) < this_eol
- && memEQ(scan, ((struct regnode_anyofhs *) p)->string, FLAGS(p))
+ && scan + STR_LEN_U8(p) < this_eol
+ && memEQ(scan, ((struct regnode_anyofhs *) p)->string, STR_LEN_U8(p))
&& invlist_contains_cp_(anyofh_list,
utf8_to_uv_or_die((U8 *) scan,
(U8 *) this_eol,
@@ -11884,7 +11884,7 @@ S_reginclass(pTHX_ regexp * const prog, const regnode * const n, const U8* const
{
/* In this case, the ARG is set up so that the final bit indicates
* whether it matches or not */
- match = ARG1u(n) & 1;
+ match = ANYOF_MATCHES_ALL_OUTSIDE_BITMAP(n);
}
else
/* Here, the main way it could match is if the code point is