Commit e3fe0f80af for perl
commit e3fe0f80af4226b6bddf3cc08237ccf08d7b7195
Author: Yves Orton <demerphq@gmail.com>
Date: Tue Oct 27 21:36:33 2026 +0100
regcomp: name regex verb (ACCEPT, etc) fields
Name the verb argument slot and argument-present flag, along with
ACCEPT's close-to-capture value. These properties distinguish fields
that share node storage and keep their use clear in compilation, debug
output, and execution.
diff --git a/regcomp.c b/regcomp.c
index 2a14d11017..6f112a92fd 100644
--- a/regcomp.c
+++ b/regcomp.c
@@ -3677,15 +3677,15 @@ S_reg(pTHX_ RExC_state_t *pRExC_state, I32 paren, I32 *flagp, U32 depth)
RExC_seen |= REG_VERBARG_SEEN;
if (start_arg) {
SV *sv = newSVpvn( start_arg, RExC_parse - start_arg);
- ARG1u(REGNODE_p(ret)) = reg_add_data( pRExC_state,
- STR_WITH_LEN("S"));
- RExC_rxi->data->data[ARG1u(REGNODE_p(ret))]=(void*)sv;
- FLAGS(REGNODE_p(ret)) = 1;
+ VERB_ARG_DATA_SLOT_SET(REGNODE_p(ret), reg_add_data( pRExC_state,
+ STR_WITH_LEN("S")));
+ RExC_rxi->data->data[VERB_ARG_DATA_SLOT(REGNODE_p(ret))]=(void*)sv;
+ VERB_HAS_ARG_SET(REGNODE_p(ret), TRUE);
} else {
- FLAGS(REGNODE_p(ret)) = 0;
+ VERB_HAS_ARG_SET(REGNODE_p(ret), FALSE);
}
if ( internal_argval != -1 )
- ARG2i_SET(REGNODE_p(ret), internal_argval);
+ ACCEPT_CLOSE_TO_CAPTURE_SET(REGNODE_p(ret), internal_argval);
nextchar(pRExC_state);
return ret;
}
diff --git a/regcomp.h b/regcomp.h
index 2797e57a66..1839d70910 100644
--- a/regcomp.h
+++ b/regcomp.h
@@ -597,6 +597,21 @@ struct regnode_ssc {
ARG2i_SET((p), (val)); \
} STMT_END
+#define VERB_ARG_DATA_SLOT(p) \
+ (assert(REGNODE_TYPE(OP(p)) == VERB || OP(p) == ACCEPT || OP(p) == \
+ OPFAIL), PREVENT_LVALUE(ARG1u(p)))
+#define VERB_ARG_DATA_SLOT_SET(p, val) STMT_START { \
+ assert(REGNODE_TYPE(OP(p)) == VERB || OP(p) == ACCEPT || OP(p) == OPFAIL);\
+ ARG1u_SET((p), (val)); \
+} STMT_END
+
+#define ACCEPT_CLOSE_TO_CAPTURE(p) \
+ (assert(OP(p) == ACCEPT), PREVENT_LVALUE(ARG2u(p)))
+#define ACCEPT_CLOSE_TO_CAPTURE_SET(p, val) STMT_START { \
+ assert(OP(p) == ACCEPT); \
+ ARG2u_SET((p), (val)); \
+} STMT_END
+
#define LOGICAL_MODE(p) \
(assert(OP(p) == LOGICAL), PREVENT_LVALUE(FLAGS(p) & EVAL_FLAGS_MASK))
#define LOGICAL_MODE_SET(p, val) STMT_START { \
@@ -612,6 +627,14 @@ struct regnode_ssc {
FLAGS(p) = (val) ? VOLATILE_REF : 0; \
} STMT_END
+#define VERB_HAS_ARG(p) \
+ (assert(REGNODE_TYPE(OP(p)) == VERB || OP(p) == ACCEPT || OP(p) == \
+ OPFAIL), PREVENT_LVALUE(FLAGS(p) != 0))
+#define VERB_HAS_ARG_SET(p, val) STMT_START { \
+ assert(REGNODE_TYPE(OP(p)) == VERB || OP(p) == ACCEPT || OP(p) == OPFAIL);\
+ FLAGS(p) = cBOOL(val); \
+} STMT_END
+
#define EVAL_NODE_FLAGS(p) \
(assert(OP(p) == EVAL), PREVENT_LVALUE(FLAGS(p)))
#define EVAL_NODE_FLAGS_SET(p, val) STMT_START { \
diff --git a/regcomp_debug.c b/regcomp_debug.c
index a1a9cc6d65..9a36e9bcfd 100644
--- a/regcomp_debug.c
+++ b/regcomp_debug.c
@@ -650,7 +650,7 @@ Perl_regprop(pTHX_ const regexp *prog, SV *sv, const regnode *o, const regmatch_
|| k == GROUPP || op == ACCEPT)
{
AV *name_list= NULL;
- U32 parno = (op == ACCEPT) ? ARG2u(o) :
+ U32 parno = (op == ACCEPT) ? ACCEPT_CLOSE_TO_CAPTURE(o) :
(op == OPEN || op == CLOSE) ? PARNO(o) :
(k == GROUPP) ? GROUPP_CAPTURE(o) :
(op >= REFN) ? NAMED_CAPTURE_LIST_SLOT(o) : REF_CAPTURE(o);
@@ -1063,10 +1063,10 @@ Perl_regprop(pTHX_ const regexp *prog, SV *sv, const regnode *o, const regmatch_
}
/* add on the verb argument if there is one */
- if ( ( k == VERB || op == ACCEPT || op == OPFAIL ) && FLAGS(o)) {
- if ( ARG1u(o) )
+ if ( ( k == VERB || op == ACCEPT || op == OPFAIL ) && VERB_HAS_ARG(o)) {
+ if ( VERB_ARG_DATA_SLOT(o) )
sv_catpvf(sv, ":%" SVf,
- SVfARG((MUTABLE_SV(progi->data->data[ ARG1u( o ) ]))));
+ SVfARG((MUTABLE_SV(progi->data->data[ VERB_ARG_DATA_SLOT( o ) ]))));
else
sv_catpvs(sv, ":NULL");
}
diff --git a/regexec.c b/regexec.c
index 2259b6140f..ab7f1484ee 100644
--- a/regexec.c
+++ b/regexec.c
@@ -9426,9 +9426,9 @@ S_regmatch(pTHX_ regmatch_info *reginfo, char *startpos, regnode *prog)
case ACCEPT: /* (*ACCEPT) */
is_accepted = true;
- if (FLAGS(scan))
- sv_yes_mark = MUTABLE_SV(rexi->data->data[ ARG1u( scan ) ]);
- utmp = ARG2u(scan);
+ if (VERB_HAS_ARG(scan))
+ sv_yes_mark = MUTABLE_SV(rexi->data->data[ VERB_ARG_DATA_SLOT( scan ) ]);
+ utmp = ACCEPT_CLOSE_TO_CAPTURE(scan);
if ( utmp ) {
regnode *cursor;
@@ -9948,8 +9948,8 @@ NULL
NOT_REACHED; /* NOTREACHED */
case CUTGROUP: /* /(*THEN)/ */
- sv_yes_mark = st->u.mark.mark_name = FLAGS(scan)
- ? MUTABLE_SV(rexi->data->data[ ARG1u( scan ) ])
+ sv_yes_mark = st->u.mark.mark_name = VERB_HAS_ARG(scan)
+ ? MUTABLE_SV(rexi->data->data[ VERB_ARG_DATA_SLOT( scan ) ])
: NULL;
PUSH_STATE_GOTO(CUTGROUP_next, next, locinput, loceol,
script_run_begin);
@@ -10724,8 +10724,8 @@ NULL
/* FALLTHROUGH */
case PRUNE: /* (*PRUNE) */
- if (FLAGS(scan))
- sv_yes_mark = sv_commit = MUTABLE_SV(rexi->data->data[ ARG1u( scan ) ]);
+ if (VERB_HAS_ARG(scan))
+ sv_yes_mark = sv_commit = MUTABLE_SV(rexi->data->data[ VERB_ARG_DATA_SLOT( scan ) ]);
PUSH_STATE_GOTO(COMMIT_next, next, locinput, loceol,
script_run_begin);
NOT_REACHED; /* NOTREACHED */
@@ -10737,8 +10737,8 @@ NULL
NOT_REACHED; /* NOTREACHED */
case OPFAIL: /* (*FAIL) */
- if (FLAGS(scan))
- sv_commit = MUTABLE_SV(rexi->data->data[ ARG1u( scan ) ]);
+ if (VERB_HAS_ARG(scan))
+ sv_commit = MUTABLE_SV(rexi->data->data[ VERB_ARG_DATA_SLOT( scan ) ]);
if (logical) {
/* deal with (?(?!)X|Y) properly,
* make sure we trigger the no branch
@@ -10754,7 +10754,7 @@ NULL
case MARKPOINT: /* (*MARK:foo) */
ST.prev_mark = mark_state;
ST.mark_name = sv_commit = sv_yes_mark
- = MUTABLE_SV(rexi->data->data[ ARG1u( scan ) ]);
+ = MUTABLE_SV(rexi->data->data[ VERB_ARG_DATA_SLOT( scan ) ]);
mark_state = st;
ST.mark_loc = locinput;
PUSH_YES_STATE_GOTO(MARKPOINT_next, next, locinput, loceol,
@@ -10787,7 +10787,7 @@ NULL
NOT_REACHED; /* NOTREACHED */
case SKIP: /* (*SKIP) */
- if (!FLAGS(scan)) {
+ if (!VERB_HAS_ARG(scan)) {
/* (*SKIP) : if we fail we cut here*/
ST.mark_name = NULL;
ST.mark_loc = locinput;
@@ -10798,7 +10798,7 @@ NULL
otherwise do nothing. Meaning we need to scan
*/
regmatch_state *cur = mark_state;
- SV *find = MUTABLE_SV(rexi->data->data[ ARG1u( scan ) ]);
+ SV *find = MUTABLE_SV(rexi->data->data[ VERB_ARG_DATA_SLOT( scan ) ]);
while (cur) {
if ( sv_eq( cur->u.mark.mark_name,