Commit bbf35a5118 for perl
commit bbf35a5118762c3ee3c08b2753bfbb372f67bf6b
Author: Yves Orton <demerphq@gmail.com>
Date: Sun Oct 11 21:55:02 2026 +0200
regcomp: let non-folding literals join folded nodes and tries
Add EXACT_NF and EXACT_NF_REQ8 to identify text which participates in no
Unicode case fold (NF means "Non Folding"). These nodes execute like EXACT
and EXACT_REQ8, but the optimizer can safely join their text to a folded
exact type, for instance EXACT_FU safely, just as it can join their text
to an old-style EXACT node.
We have long split non-folding text out of folded literals so the
fixed-substring optimizer can use it. However, that split has also prevented
otherwise compatible alternatives from forming a complete trie. It also
interacts with an optimization we do that turns a folded single character into
a character class, which can prevent more powerful TRIE style optimizations
from happening. For example, /foo|bar|a_word|_qux/i should compile into one
TRIE-EXACTFU containing all four words.
Part of the problem is that we were splitting the nodes out as EXACT,
which is actually subtly not ideal. The problem is that EXACT nodes
created normally may (and very often do) contain content that would fold
if it were merged into an EXACTFU for instance. EXACT_NF however are
EXACTish nodes (from the point of view of fixed string extraction) but which
contain content that behaves the same folded or not, and which can be safely
merged together with (more or less) any other EXACT type. By splitting
EXACT into "exact stuff you can NOT merge with any folding types" and
"exact stuff you CAN merge with folding types", we can undo the split
later on, merging the EXACT_NF nodes together with whatever they are next to.
Thus during study we leave non-folding pieces separate until the substring and
length logic has seen them. Then we join each piece to its compatible
predecessor, carring a merge-left flag forward after a successful join so that
the join cascades, meaning that
EXACTFU "foo"
EXACT_NF "_"
EXACTFU "bar"
EXACT_NF "_"
EXACTFU "baz"
becomes one folded EXACTFU containing "foo_bar_baz".
Only globally non-foldable characters get the new types, eg "." or such characters.
In particular, a ligature whose fold is excluded under /aa stays EXACT_REQ8. Marking
it non-folding would let a neighboring /u literal absorb it and change its
matching rules.
Includes regression tests for the reported trie, cascading joins before and after a
nested alternation, single-letter continuations, sharp-S class alternatives,
scoped /aa folding, and mixed narrow and wide non-folding characters.
Fixes #19953.
diff --git a/embed.fnc b/embed.fnc
index 61a2deefe1..43018e486b 100644
--- a/embed.fnc
+++ b/embed.fnc
@@ -5711,7 +5711,9 @@ Ep |U32 |join_exact |NN RExC_state_t *pRExC_state \
|NN bool *unfolded_multi_char \
|U32 flags \
|NULLOK regnode *val \
- |U32 depth
+ |U32 depth \
+ |bool allow_non_folding \
+ |bool merge_first_two_only
Ep |I32 |make_trie |NN RExC_state_t *pRExC_state \
|NN regnode *startbranch \
|NN regnode *first \
diff --git a/embed.h b/embed.h
index 8b5ab841db..e460b54469 100644
--- a/embed.h
+++ b/embed.h
@@ -2059,7 +2059,7 @@
# define invlist_highest_range_start S_invlist_highest_range_start
# define invlist_is_iterating S_invlist_is_iterating
# define invlist_lowest S_invlist_lowest
-# define join_exact(a,b,c,d,e,f,g) Perl_join_exact(aTHX_ a,b,c,d,e,f,g)
+# define join_exact(a,b,c,d,e,f,g,h,i) Perl_join_exact(aTHX_ a,b,c,d,e,f,g,h,i)
# define make_trie(a,b,c,d,e,f,g,h,i) Perl_make_trie(aTHX_ a,b,c,d,e,f,g,h,i)
# define populate_anyof_bitmap_from_invlist(a,b) Perl_populate_anyof_bitmap_from_invlist(aTHX_ a,b)
# define reg_add_data Perl_reg_add_data
diff --git a/ext/re/t/regop.pl b/ext/re/t/regop.pl
index c725b73a9e..9201dfea47 100644
--- a/ext/re/t/regop.pl
+++ b/ext/re/t/regop.pl
@@ -1,4 +1,5 @@
use re Debug=>qw(DUMP EXECUTE TRIEC TEST);
+require '../../t/charset_tools.pl';
my @tests=(
XY => 'X(A|[B]Q||C|D)Y' ,
foobar => '[f][o][o][b][a][r]',
@@ -9,6 +10,12 @@ my @tests=(
'q'=>'[q]',
"path_sep:\t8490" => '^(\\S{1,9}):\\s*(\\d+)$',
'' => '(?(DEFINE)(?<foo>foo))(?(DEFINE)(?<bar>(?&foo)bar))(?(DEFINE)(?<baz>(?&bar)baz))(?(DEFINE)(?<bop>(?&baz)bop))',
+ 'xfoo_bar_bazfoo_bar_baz' => '/x(?:foo_bar_baz|bloop_er)foo_bar_baz/i',
+ 'xfoo_bar_bazfoo_bar_baz' => 'x(?:foo_bar_baz|bloop_er)foo_bar_baz',
+ 'a_word' => '/foo|bar|a_word|_qux/i',
+ '_' => '/_|#/i',
+ uni_to_native("\x{00DF}") . '_' => '/(?a:[\x{1E9E}_]_)/i',
+ '_a' => '/_a|_b/i',
);
while (@tests) {
my ($str,$pat)=splice @tests,0,2;
diff --git a/ext/re/t/regop.t b/ext/re/t/regop.t
index 3040a45154..4957de6ff1 100644
--- a/ext/re/t/regop.t
+++ b/ext/re/t/regop.t
@@ -55,7 +55,7 @@ foreach my $testout ( @tests ) {
# that the tests for this result set are finished.
# If you add a test make sure you update $NUM_SECTS
# the commented output is just for legacy/debugging purposes
-BEGIN{ $NUM_SECTS= 8 }
+BEGIN{ $NUM_SECTS= 14 }
__END__
#Compiling REx "X(A|[B]Q||C|D)Y"
@@ -314,3 +314,46 @@ minlen 0
#Match successful!
%MATCHED%
#Freeing REx: "(?(DEFINE)(?<foo>foo))(?(DEFINE)(?<bar>(?&foo)bar))(?(DEFINE"...
+---
+#Compiling REx "x(?:foo_bar_baz|bloop_er)foo_bar_baz"
+TRIE-EXACTFU
+<foo_bar_baz>
+<bloop_er>
+EXACTFU <foo_bar_baz>
+%MATCHED%
+---
+#Compiling REx "x(?:foo_bar_baz|bloop_er)foo_bar_baz"
+EXACT <x>
+TRIE-EXACT
+<foo_bar_baz>
+<bloop_er>
+EXACT <foo_bar_baz>
+%MATCHED%
+---
+#Compiling REx "foo|bar|a_word|_qux"
+TRIE-EXACTFU
+<foo>
+<bar>
+<a_word>
+<_qux>
+stclass AHOCORASICK-EXACTFU
+%MATCHED%
+---
+#Compiling REx "_|#"
+TRIE-EXACT
+<_>
+<#>
+%MATCHED%
+---
+#Compiling REx "(?a:[\x{1E9E}_]_)"
+TRIE-EXACTFU
+<ss>
+<_>
+EXACT_NF <_>
+%MATCHED%
+---
+#Compiling REx "_a|_b"
+TRIE-EXACTFU
+<_a>
+<_b>
+%MATCHED%
diff --git a/pod/perldelta.pod b/pod/perldelta.pod
index 95e8203f7c..0974ecb292 100644
--- a/pod/perldelta.pod
+++ b/pod/perldelta.pod
@@ -89,7 +89,11 @@ There may well be none in a stable release.
=item *
-XXX
+Case-insensitive literal alternatives such as C<foo|bar|a_word|_qux> can
+compile into a single trie again. Characters that do not participate in
+Unicode case folding can join neighboring folded literals after the
+optimizer records their fixed substrings.
+L<[GH #19953]|https://github.com/Perl/perl5/issues/19953>
=back
diff --git a/pod/perlreguts.pod b/pod/perlreguts.pod
index ddb315456c..45339d2883 100644
--- a/pod/perlreguts.pod
+++ b/pod/perlreguts.pod
@@ -332,7 +332,11 @@ BRANCH node 1 Match this alternative, or the next...
# Literals
EXACT str Match this string (flags field is the
- length).
+ length). The text is matched exactly as
+ is, without folding. Nodes of this type
+ can only be safely merged with other EXACT
+ nodes or with EXACT_NF, but not with any
+ folding types like EXACTFU.
# In a long string node, the U32 argument is the length, and is immediately
# followed by the string.
@@ -340,6 +344,20 @@ LEXACT len:str 1 Match this long string (preceded by length;
flags unused).
EXACTL str Like EXACT, but /l is in effect (used so
locale-related warnings can be checked for)
+EXACT_NF str Match this string of non-folding
+ codepoints, meaning codepoints which do not
+ change under any folding function (flags
+ field is the length). For example, the '.'
+ character is non-folding. This node type
+ is for the most part handled just like
+ EXACT nodes, but EXACT_NF nodes have the
+ additional special property that they may
+ be safely merged with any other node type,
+ and provided the result ends up with the
+ other node's type then it will still match
+ correctly.
+EXACT_NF_REQ8 str Like EXACT_NF, but only UTF-8 encoded
+ targets can match
EXACTF str Like EXACT, but match using /id rules;
(string not UTF-8, ASCII folded; non-ASCII
not)
diff --git a/proto.h b/proto.h
index bdb3905473..126abcc36a 100644
--- a/proto.h
+++ b/proto.h
@@ -15006,7 +15006,7 @@ Perl_get_ANYOFM_contents(pTHX_ const regnode *n)
__attribute__warn_unused_result__
__attribute__visibility__("hidden");
PERL_CALLCONV U32
-Perl_join_exact(pTHX_ RExC_state_t *pRExC_state, regnode *scan, UV *min_subtract, bool *unfolded_multi_char, U32 flags, regnode *val, U32 depth)
+Perl_join_exact(pTHX_ RExC_state_t *pRExC_state, regnode *scan, UV *min_subtract, bool *unfolded_multi_char, U32 flags, regnode *val, U32 depth, bool allow_non_folding, bool merge_first_two_only)
Perl_attribute_nonnull_aTHX
Perl_attribute_nonnull(pTHX_1)
Perl_attribute_nonnull(pTHX_2)
diff --git a/regcomp.c b/regcomp.c
index 3ce3153e08..7cf52ff9f9 100644
--- a/regcomp.c
+++ b/regcomp.c
@@ -6515,11 +6515,11 @@ S_regatom(pTHX_ RExC_state_t *pRExC_state, I32 *flagp, U32 depth)
* place first time through; otherwise it would stop too early */
U32 upper_fill = max_string_len + 1;
- /* We start out as an EXACT node, even if under /i, until we find a
- * character which is in a fold. The algorithm now segregates into
- * separate nodes, characters that fold from those that don't under
- * /i. (This hopefully will create nodes that are fixed strings
- * even under /i, giving the optimizer something to grab on to.)
+ /* We start out as an EXACT node, even if under /i, until we
+ * classify the first character. The algorithm now segregates
+ * into separate nodes, characters that fold from those that don't
+ * under /i. Non-folding text is marked EXACT_NF, giving the
+ * optimizer something to grab on to.
* So, if a node has something in it and the next character is in
* the opposite category, that node is closed up, and the function
* returns. Then regatom is called again, and a new node is
@@ -7056,13 +7056,16 @@ S_regatom(pTHX_ RExC_state_t *pRExC_state, I32 *flagp, U32 depth)
*
* Start a new node if previous characters in the node were
* folded */
- if (len && node_type != EXACT) {
+ if (len && ! IS_EXACT_OR_NF(node_type)) {
p = oldp;
goto loopdone;
}
/* Here, continuing a node with non-folded characters. Add
* this one */
+ if (! LOC && ! len) {
+ node_type = EXACT_NF;
+ }
goto not_fold_common;
}
else { /* Here, does participate in some fold */
@@ -7074,7 +7077,7 @@ S_regatom(pTHX_ RExC_state_t *pRExC_state, I32 *flagp, U32 depth)
if (! len) {
node_type = compute_EXACTish(pRExC_state);
}
- else if (node_type == EXACT) {
+ else if (IS_EXACT_OR_NF(node_type)) {
p = oldp;
goto loopdone;
}
@@ -7728,14 +7731,16 @@ S_regatom(pTHX_ RExC_state_t *pRExC_state, I32 *flagp, U32 depth)
}
else {
- /* If the node type is EXACT here, check to see if it
- * should be EXACTL, or EXACT_REQ8. */
- if (node_type == EXACT) {
+ /* If the node type is EXACT or EXACT_NF here, check whether
+ * it requires a UTF-8 target. */
+ if (IS_EXACT_OR_NF(node_type)) {
if (LOC) {
node_type = EXACTL;
}
else if (requires_utf8_target) {
- node_type = EXACT_REQ8;
+ node_type = node_type == EXACT_NF
+ ? EXACT_NF_REQ8
+ : EXACT_REQ8;
}
}
else if (node_type == LEXACT) {
@@ -11838,10 +11843,10 @@ S_optimize_regclass(pTHX_
* LATIN SMALL LETTER N PRECEDED BY APOSTROPHE. And so even though there
* is no simple fold that includes \X{02BC}, there is a multi-char fold
* that does, and so the node generated for it must be an EXACTFish one.
- * On the other hand qr/:/i should generate a plain EXACT node since the
- * colon participates in no fold whatsoever, and having it be EXACT tells
- * the optimizer the target string cannot match unless it has a colon in
- * it. */
+ * On the other hand qr/:/i should generate an EXACT_NF node since the
+ * colon participates in no fold whatsoever, and marking it EXACT_NF
+ * tells the optimizer the target string cannot match unless it has a
+ * colon in it. */
if ( ! posixl
&& ! *invert
@@ -11875,11 +11880,11 @@ S_optimize_regclass(pTHX_
small */
/* Under /i, it gets a little tricky. A code point that
- * doesn't participate in a fold should be an EXACT node. We
- * know this one isn't the result of a simple fold, or there'd
+ * doesn't participate in a fold should be an EXACT_NF node.
+ * We know this one isn't the result of a simple fold, or there'd
* be more than one code point in the list, but it could be
* part of a multi-character fold. In that case we better not
- * create an EXACT node, as we would wrongly be telling the
+ * create an EXACT_NF node, as we would wrongly be telling the
* optimizer that this code point must be in the target string,
* and that is wrong. This is because if the sequence around
* this code point forms a multi-char fold, what needs to be in
@@ -11891,14 +11896,19 @@ S_optimize_regclass(pTHX_
* above-256 one */
op = IS_IN_SOME_FOLD_L1(lowest_cp)
? EXACTFU
- : EXACT;
+ : EXACT_NF;
}
else { /* /i, larger code point. Since we are under /i, and have
just this code point, we know that it can't fold to
something else, so PL_InMultiCharFold applies to it */
op = (invlist_contains_cp_(PL_InMultiCharFold, lowest_cp))
? EXACTFU_REQ8
- : EXACT_REQ8;
+ : invlist_contains_cp_(PL_in_some_fold, lowest_cp)
+ ? EXACT_REQ8
+ : EXACT_NF_REQ8;
+ /* A fold excluded by /aa does not make the character
+ * globally non-folding. Keep EXACT_REQ8 so a join with a
+ * neighboring /u node cannot change its matching rules. */
}
value = lowest_cp;
@@ -13544,7 +13554,8 @@ S_regtail_study(pTHX_ RExC_state_t *pRExC_state, regnode_offset p,
if (REGNODE_TYPE(OP(REGNODE_p(scan))) == EXACT) {
bool unfolded_multi_char; /* Unexamined in this routine */
if (join_exact(pRExC_state, scan, &min,
- &unfolded_multi_char, 1, REGNODE_p(val), depth+1))
+ &unfolded_multi_char, 1, REGNODE_p(val), depth+1,
+ false, false))
return true; /* Was return EXACT */
}
#endif
diff --git a/regcomp.h b/regcomp.h
index d1171ac9ce..6e7c648d2c 100644
--- a/regcomp.h
+++ b/regcomp.h
@@ -1150,6 +1150,58 @@ START_EXTERN_C
#include "regnodes.h"
#endif
+/* Predicates for the plain and UTF-8-required exact opcode pairs. */
+#define IS_EXACT_OR_NF(op) ((op) == EXACT || (op) == EXACT_NF)
+#define IS_EXACT_REQ8_OR_NF_REQ8(op) \
+ ((op) == EXACT_REQ8 || (op) == EXACT_NF_REQ8)
+#define ANY_EXACT_NF(op) ((op) == EXACT_NF || (op) == EXACT_NF_REQ8)
+
+#define TRIE_TYPE(op) ( ( NOTHING == (op) || ANY_EXACT_NF(op) ) \
+ ? (op) \
+ : ( (op) == EXACT || (op) == EXACT_REQ8 ) \
+ ? EXACT \
+ : ( EXACTFU == (op) \
+ || EXACTFU_REQ8 == (op) \
+ || EXACTFUP == (op) ) \
+ ? EXACTFU \
+ : ( EXACTFAA == (op) ) \
+ ? EXACTFAA \
+ : ( EXACTL == (op) ) \
+ ? EXACTL \
+ : ( EXACTFLU8 == (op) ) \
+ ? EXACTFLU8 \
+ : 0 )
+
+/* Finalize an accumulator of non-folding text as the ordinary exact trie
+ * family. A wide word must not make a shared ASCII prefix require UTF-8. */
+#define TRIE_FINAL_TYPE(type) \
+ ( ANY_EXACT_NF(type) ? EXACT : (type) )
+
+/* Combine normalized trie types, or return 0 when they are incompatible.
+ * NOTHING and non-folding exact types impose no matching family. Keep the
+ * non-folding marker until a folded or ordinary exact type supplies one.
+ * Unlike joining strings, combining alternatives does not require every
+ * word to be UTF-8 just because one word is. make_trie() handles each word's
+ * source encoding separately.
+ */
+#define TRIE_COMPATIBLE_TYPE(type_a, type_b) \
+ ( (type_a) == NOTHING \
+ ? (type_b) \
+ : (type_b) == NOTHING \
+ ? (type_a) \
+ : ANY_EXACT_NF(type_a) \
+ ? ANY_EXACT_NF(type_b) \
+ ? ((type_a) == EXACT_NF_REQ8 \
+ || (type_b) == EXACT_NF_REQ8) \
+ ? EXACT_NF_REQ8 \
+ : EXACT_NF \
+ : (type_b) \
+ : ANY_EXACT_NF(type_b) \
+ ? (type_a) \
+ : (type_a) == (type_b) \
+ ? (type_a) \
+ : 0 )
+
#ifndef PLUGGABLE_RE_EXTENSION
#ifndef DOINIT
EXTCONST regexp_engine PL_core_reg_engine;
diff --git a/regcomp.sym b/regcomp.sym
index b468700c82..d9afe77b7e 100644
--- a/regcomp.sym
+++ b/regcomp.sym
@@ -770,7 +770,11 @@ return {
"arg_spec" => "str",
"str_arg" => 1,
},
- "desc" => "Match this string (flags field is the length).",
+ "desc" => "Match this string (flags field is the length). The " .
+ "text is matched exactly as is, without folding. Nodes " .
+ "of this type can only be safely merged with other EXACT " .
+ "nodes or with EXACT_NF, but not with any folding types " .
+ "like EXACTFU.",
"line" => __LINE__,
},
{
@@ -803,6 +807,35 @@ return {
"locale-related warnings can be checked for)",
"line" => __LINE__,
},
+ {
+ "NAME" => "EXACT_NF",
+ "TYPE" => "EXACT",
+ "attr" => {
+ "arg_spec" => "str",
+ "str_arg" => 1,
+ },
+ "desc" =>
+ "Match this string of non-folding codepoints, " .
+ "meaning codepoints which do not change under any folding " .
+ "function (flags field is the length). ".
+ "For example, the '.' character is non-folding. This node type is for " .
+ "the most part handled just like EXACT nodes, but EXACT_NF nodes have " .
+ "the additional special property that they may be safely merged " .
+ "with any other node type, and provided the result ends up with the other " .
+ "node's type then it will still match correctly.",
+ "line" => __LINE__,
+ },
+ {
+ "NAME" => "EXACT_NF_REQ8",
+ "TYPE" => "EXACT",
+ "attr" => {
+ "arg_spec" => "str",
+ "str_arg" => 1,
+ },
+ "desc" =>
+ "Like EXACT_NF, but only UTF-8 encoded targets can match",
+ "line" => __LINE__,
+ },
{
"NAME" => "EXACTF",
"TYPE" => "EXACT",
diff --git a/regcomp_study.c b/regcomp_study.c
index 40eb2f95ae..264c46095f 100644
--- a/regcomp_study.c
+++ b/regcomp_study.c
@@ -1069,19 +1069,22 @@ S_ssc_clear_locale(regnode_ssc *ssc)
U32
Perl_join_exact(pTHX_ RExC_state_t *pRExC_state, regnode *scan,
UV *min_subtract, bool *unfolded_multi_char,
- U32 flags, regnode *val, U32 depth)
+ U32 flags, regnode *val, U32 depth,
+ bool allow_non_folding, bool merge_first_two_only)
{
PERL_ARGS_ASSERT_JOIN_EXACT;
- /* Merge several consecutive EXACTish nodes into one. */
+ /* Merge consecutive EXACTish nodes into one. The initial study joins
+ * non-folding pieces only to each other so substring analysis sees them.
+ * The later cleanup allows them to join, one pair per study iteration. */
regnode *n = regnext(scan);
- U32 stringok = 1;
+ bool stringok = true;
regnode *next = REGNODE_AFTER_varies(scan);
U32 stopnow = 0;
+ regnode *stop = scan;
#ifdef DEBUGGING
U32 merged = 0;
- regnode *stop = scan;
DECLARE_AND_GET_RE_DEBUG_FLAGS;
#else
PERL_UNUSED_ARG(depth);
@@ -1099,13 +1102,27 @@ Perl_join_exact(pTHX_ RExC_state_t *pRExC_state, regnode *scan,
* EXACT ones that are mergeable to the current one. */
while ( n
&& ( REGNODE_TYPE(OP(n)) == NOTHING
- || (stringok && REGNODE_TYPE(OP(n)) == EXACT))
+ || (stringok && REGNODE_TYPE(OP(n)) == EXACT
+ && (allow_non_folding
+ || (ANY_EXACT_NF(OP(scan)) == ANY_EXACT_NF(OP(n))))))
&& NEXT_OFF(n)
&& NEXT_OFF(scan) + NEXT_OFF(n) < I16_MAX)
{
- if (OP(n) == TAIL || n > next)
- stringok = 0;
+ if (OP(n) == TAIL)
+ stringok = false;
+ else if (n > next) {
+ regnode *gap = next;
+
+ /* A previous merge can leave unused regnode units between scan
+ * and n. Only cross them if the join marked each as OPTIMIZED. */
+ while (gap < n && OP(gap) == OPTIMIZED)
+ {
+ gap = REGNODE_AFTER_varies(gap);
+ }
+ if (gap != n)
+ stringok = false;
+ }
if (REGNODE_TYPE(OP(n)) == NOTHING) {
DEBUG_PEEP("skip:", n, depth, 0);
NEXT_OFF_set(scan, NEXT_OFF(scan) + NEXT_OFF(n));
@@ -1127,13 +1144,35 @@ Perl_join_exact(pTHX_ RExC_state_t *pRExC_state, regnode *scan,
if (oldl + STR_LEN(n) > U8_MAX)
break;
- /* Joining something that requires UTF-8 with something that
- * doesn't, means the result requires UTF-8. */
- if (OP(scan) == EXACT && (OP(n) == EXACT_REQ8)) {
- OP(scan) = EXACT_REQ8;
- }
- else if (OP(scan) == EXACT_REQ8 && (OP(n) == EXACT)) {
- ; /* join is compatible, no need to change OP */
+ /* Preserve the non-folding marker only if both pieces have it, and
+ * preserve the UTF-8 requirement if either piece has it. */
+ if ((IS_EXACT_OR_NF(OP(scan))
+ || IS_EXACT_REQ8_OR_NF_REQ8(OP(scan)))
+ && (IS_EXACT_OR_NF(OP(n))
+ || IS_EXACT_REQ8_OR_NF_REQ8(OP(n))))
+ {
+ const bool requires_utf8 =
+ IS_EXACT_REQ8_OR_NF_REQ8(OP(scan))
+ || IS_EXACT_REQ8_OR_NF_REQ8(OP(n));
+ const bool both_non_folding =
+ ANY_EXACT_NF(OP(scan)) && ANY_EXACT_NF(OP(n));
+
+ OP(scan) = both_non_folding
+ ? (requires_utf8 ? EXACT_NF_REQ8 : EXACT_NF)
+ : (requires_utf8 ? EXACT_REQ8 : EXACT);
+ }
+ /* Non-folding text can join a folded node in either direction.
+ * Use the folded node's semantics and retain any UTF-8
+ * requirement. Only globally non-folding text gets this marker. */
+ else if (ANY_EXACT_NF(OP(scan))) {
+ const bool requires_utf8 = OP(scan) == EXACT_NF_REQ8;
+ OP(scan) = OP(n);
+ if (requires_utf8 && OP(scan) == EXACTFU)
+ OP(scan) = EXACTFU_REQ8;
+ }
+ else if (ANY_EXACT_NF(OP(n))) {
+ if (OP(n) == EXACT_NF_REQ8 && OP(scan) == EXACTFU)
+ OP(scan) = EXACTFU_REQ8;
}
else if ((OP(scan) == EXACTFU) && (OP(n) == EXACTFU_REQ8)) {
OP(scan) = EXACTFU_REQ8;
@@ -1237,11 +1276,9 @@ Perl_join_exact(pTHX_ RExC_state_t *pRExC_state, regnode *scan,
setSTR_LEN(scan, (U8)(STR_LEN(scan) + STR_LEN(n)));
/* Now we can overwrite *n : */
Move(STRING(n), STRING(scan) + oldl, STR_LEN(n), char);
-#ifdef DEBUGGING
stop = next - 1;
-#endif
n = nnext;
- if (stopnow) break;
+ if (stopnow || merge_first_two_only) break;
}
#ifdef EXPERIMENTAL_INPLACESCAN
@@ -1272,7 +1309,10 @@ Perl_join_exact(pTHX_ RExC_state_t *pRExC_state, regnode *scan,
* this final joining, sequences could have been split over boundaries, and
* hence missed). The sequences only happen in folding, hence for any
* non-EXACT EXACTish node */
- if (OP(scan) != EXACT && OP(scan) != EXACT_REQ8 && OP(scan) != EXACTL) {
+ if (! IS_EXACT_OR_NF(OP(scan))
+ && ! IS_EXACT_REQ8_OR_NF_REQ8(OP(scan))
+ && OP(scan) != EXACTL)
+ {
U8* s0 = (U8*) STRING(scan);
U8* s = s0;
U8* s_end = s0 + STR_LEN(scan);
@@ -1460,9 +1500,9 @@ Perl_join_exact(pTHX_ RExC_state_t *pRExC_state, regnode *scan,
}
}
-#ifdef DEBUGGING
- /* Allow dumping but overwriting the collection of skipped
- * ops and/or strings with fake optimized ops */
+ /* Mark consumed storage in all builds. Later pairwise joins must be
+ * able to cross this padding without interpreting old string bytes as
+ * node headers. This also makes the program safe to dump. */
n = REGNODE_AFTER_varies(scan);
while (n <= stop) {
OP(n) = OPTIMIZED;
@@ -1470,7 +1510,6 @@ Perl_join_exact(pTHX_ RExC_state_t *pRExC_state, regnode *scan,
NEXT_OFF_set(n, 0);
n++;
}
-#endif
DEBUG_OPTIMISE_r(if (merged){DEBUG_PEEP("finl", scan, depth, 0);});
return stopnow;
}
@@ -1507,6 +1546,8 @@ Perl_study_chunk(pTHX_
/* vars about the regnodes we are working with */
regnode *scan = *scanp; /* the current opcode we are inspecting */
regnode *next = NULL; /* the next opcode beyond scan, tmp var */
+ regnode *prev_exact = NULL; /* Previous EXACTish node in this scan */
+ bool merge_left = false;
regnode *first_non_open = scan; /* FIXME: should this init to NULL?
the first non open regop, if the init
val IS an OPEN then we will skip past
@@ -1551,6 +1592,8 @@ Perl_study_chunk(pTHX_
}
fake_study_recurse:
+ prev_exact = NULL;
+ merge_left = false;
DEBUG_r(
RExC_study_chunk_recursed_count++;
);
@@ -1590,23 +1633,24 @@ Perl_study_chunk(pTHX_
* enframed handling for a GOSUB: the outermost level will handle it.
*/
bool mutate_ok = was_mutate_ok && !(frame && frame->in_gosub);
+ if (REGNODE_TYPE(OP(scan)) != EXACT) {
+ prev_exact = NULL;
+ merge_left = false;
+ }
/* Peephole optimizer: */
DEBUG_STUDYDATA("Peep", data, depth, is_inf, min, stopmin, delta);
DEBUG_PEEP("Peep", scan, depth, flags);
-
- /* The reason we do this here is that we need to deal with things like
- * /(?:f)(?:o)(?:o)/ which cant be dealt with by the normal EXACT
- * parsing code, as each (?:..) is handled by a different invocation of
- * reg() -- Yves
- */
+ /* Folded EXACT nodes need joining before their length is analyzed.
+ * Non-folding nodes are left for the pairwise join below. */
if (REGNODE_TYPE(OP(scan)) == EXACT
&& OP(scan) != LEXACT
&& OP(scan) != LEXACT_REQ8
- && mutate_ok
- ) {
- join_exact(pRExC_state, scan, &min_subtract, &unfolded_multi_char,
- 0, NULL, depth + 1);
+ && mutate_ok)
+ {
+ join_exact(pRExC_state, scan, &min_subtract,
+ &unfolded_multi_char, 0, NULL, depth + 1,
+ false, false);
}
/* Follow the next-chain of the current node and optimize
@@ -1908,14 +1952,15 @@ Perl_study_chunk(pTHX_
necessarily mean the first node is the start of the
alternation).
- TRIE_TYPE(X) is a define which maps the optype to a
- trietype.
+ TRIE_TYPE(X) maps an opcode to a trie type.
optype | trietype
----------------+-----------
NOTHING | NOTHING
EXACT | EXACT
EXACT_REQ8 | EXACT
+ EXACT_NF | EXACT_NF
+ EXACT_NF_REQ8 | EXACT_NF_REQ8
EXACTFU | EXACTFU
EXACTFU_REQ8 | EXACTFU
EXACTFUP | EXACTFU
@@ -1925,22 +1970,6 @@ Perl_study_chunk(pTHX_
*/
-#define TRIE_TYPE(X) ( ( NOTHING == (X) ) \
- ? NOTHING \
- : ( EXACT == (X) || EXACT_REQ8 == (X) ) \
- ? EXACT \
- : ( EXACTFU == (X) \
- || EXACTFU_REQ8 == (X) \
- || EXACTFUP == (X) ) \
- ? EXACTFU \
- : ( EXACTFAA == (X) ) \
- ? EXACTFAA \
- : ( EXACTL == (X) ) \
- ? EXACTL \
- : ( EXACTFLU8 == (X) ) \
- ? EXACTFLU8 \
- : 0 )
-
/* dont use tail as the end marker for this traverse */
for ( cur = startbranch ; cur != scan ; cur = regnext( cur ) ) {
regnode * const noper = REGNODE_AFTER( cur );
@@ -1949,6 +1978,17 @@ Perl_study_chunk(pTHX_
regnode * const noper_next = regnext( noper );
U8 noper_next_type = (noper_next && noper_next < tail) ? OP(noper_next) : 0;
U8 noper_next_trietype = (noper_next && noper_next < tail) ? TRIE_TYPE( noper_next_type ) :0;
+ U8 noper_branch_trietype = noper_trietype == NOTHING
+ ? noper_next_type
+ ? TRIE_COMPATIBLE_TYPE(noper_trietype,
+ noper_next_trietype)
+ : NOTHING
+ : noper_trietype;
+ U8 compatible_trietype = trietype
+ ? TRIE_COMPATIBLE_TYPE(trietype, noper_trietype)
+ : noper_trietype == NOTHING
+ ? NOTHING
+ : noper_branch_trietype;
const bool noper_next_is_trie =
noper_next && noper_next < tail
&& REGNODE_TYPE(noper_next_type) == TRIE;
@@ -1973,19 +2013,15 @@ Perl_study_chunk(pTHX_
}
re_printf("(First == %d,Last == %d,Cur == %d,tt == %s,ntt == %s,nntt == %s)\n",
REG_NODE_NUM(first), REG_NODE_NUM(prev), REG_NODE_NUM(cur),
- REGNODE_NAME(trietype), REGNODE_NAME(noper_trietype), REGNODE_NAME(noper_next_trietype)
+ REGNODE_NAME(trietype), REGNODE_NAME(noper_trietype),
+ REGNODE_NAME(noper_next_trietype)
);
});
/* Is noper a trieable nodetype that can be merged
* with the current trie (if there is one)? */
if ( noper_trietype
- &&
- (
- ( noper_trietype == NOTHING )
- || ( trietype == NOTHING )
- || ( trietype == noper_trietype )
- )
+ && compatible_trietype
/* Do not replace a common first node when
* its branches continue with a different
* trie type. The octet-trie construction
@@ -1996,7 +2032,9 @@ Perl_study_chunk(pTHX_
* attached to that trie. */
&& !noper_next_is_trie
&& ( !noper_next_trietype
- || noper_next_trietype == noper_trietype
+ || TRIE_COMPATIBLE_TYPE(
+ noper_trietype,
+ noper_next_trietype)
|| noper_trietype == NOTHING )
#ifdef NOJUMPTRIE
&& noper_next >= tail
@@ -2017,7 +2055,9 @@ Perl_study_chunk(pTHX_
#endif
if ( noper_next_trietype ) {
- trietype = noper_next_trietype;
+ trietype = TRIE_COMPATIBLE_TYPE(
+ noper_trietype,
+ noper_next_trietype);
} else if (noper_next_type) {
/* a NOTHING regop is 1 regop wide.
* We need at least two for a trie
@@ -2028,8 +2068,7 @@ Perl_study_chunk(pTHX_
trietype = noper_trietype;
}
} else {
- if ( trietype == NOTHING )
- trietype = noper_trietype;
+ trietype = compatible_trietype;
prev = cur;
}
if (first) {
@@ -2055,7 +2094,8 @@ Perl_study_chunk(pTHX_
make_trie( pRExC_state,
startbranch, first, cur, tail,
word_count, octet_count,
- trietype, depth+1 );
+ TRIE_FINAL_TYPE(trietype),
+ depth+1 );
prev = NULL; /* note: we clear/update
first, trietype etc below,
so we dont do it here */
@@ -2073,7 +2113,7 @@ Perl_study_chunk(pTHX_
word_count = 1;
octet_count = noper_octets;
first = cur;
- trietype = noper_trietype;
+ trietype = noper_branch_trietype;
} else if (first) {
/* if we already saw a first but the
* current node is not triable then we have
@@ -2101,7 +2141,8 @@ Perl_study_chunk(pTHX_
* outside of the loop */
made = make_trie( pRExC_state, startbranch,
first, scan, tail, word_count,
- octet_count, trietype,
+ octet_count,
+ TRIE_FINAL_TYPE(trietype),
depth+1 );
#ifdef TRIE_STUDY_OPT
if ( ((made == MADE_EXACT_TRIE)
@@ -2345,11 +2386,16 @@ Perl_study_chunk(pTHX_
* with the mask set to the complement of the bit that differs
* between upper and lower case, and the lowest code point of the
* pair (which the '&' forces) */
+ /* Keep the folded node intact when cleanup can join it to the
+ * preceding literal or the following non-folding node. */
if ( bytelen == 1
&& isALPHA_A(*s)
&& ( OP(scan) == EXACTFAA
|| ( OP(scan) == EXACTFU
&& ! HAS_NONLATIN1_SIMPLE_FOLD_CLOSURE(*s)))
+ && !(regnext(scan)
+ && ANY_EXACT_NF(OP(regnext(scan))))
+ && !merge_left
&& mutate_ok
) {
U8 mask = ~ ('A' ^ 'a'); /* These differ in just one bit */
@@ -3687,6 +3733,40 @@ Perl_study_chunk(pTHX_
" before optimization", REGNODE_NAME(REGEX_SET));
}
+ /* Record fixed substrings and lengths before absorbing this node.
+ * Once a non-folding piece has joined its predecessor, keep trying to
+ * join left on later iterations. Its opcode may now be folded, but
+ * the next compatible piece belongs in the same literal. */
+ if (REGNODE_TYPE(OP(scan)) == EXACT) {
+ const bool scan_is_non_folding = ANY_EXACT_NF(OP(scan));
+ if (mutate_ok && prev_exact
+ && (merge_left || scan_is_non_folding)
+ && OP(prev_exact) != LEXACT
+ && OP(prev_exact) != LEXACT_REQ8
+ && OP(scan) != LEXACT
+ && OP(scan) != LEXACT_REQ8)
+ {
+ regnode * const prev = prev_exact;
+ regnode * const scan_next = regnext(scan);
+ join_exact(pRExC_state, prev, &min_subtract,
+ &unfolded_multi_char, 0, NULL, depth + 1,
+ true, true);
+ if (regnext(prev) == scan_next) {
+ scan = prev;
+ prev_exact = prev;
+ merge_left = merge_left || scan_is_non_folding;
+ }
+ else {
+ prev_exact = scan;
+ merge_left = scan_is_non_folding;
+ }
+ }
+ else {
+ prev_exact = scan;
+ merge_left = scan_is_non_folding;
+ }
+ }
+
/* Else: zero-length, ignore. */
scan = regnext(scan);
}
diff --git a/regcomp_trie.c b/regcomp_trie.c
index f1ddafab40..6be0dd14af 100644
--- a/regcomp_trie.c
+++ b/regcomp_trie.c
@@ -433,8 +433,9 @@ is the recommended Unicode-aware way of saying
* must not be identified as UTF-8 merely because their octets happen to form
* a valid UTF-8 sequence. */
#define TRIE_SOURCE_UTF8(noper) \
- (UTF || OP(noper) == EXACT_REQ8 || OP(noper) == EXACTFU_REQ8 \
- || OP(noper) == EXACTL || OP(noper) == EXACTFLU8)
+ (UTF || OP(noper) == EXACT_REQ8 || OP(noper) == EXACT_NF_REQ8 \
+ || OP(noper) == EXACTFU_REQ8 || OP(noper) == EXACTL \
+ || OP(noper) == EXACTFLU8)
PERL_STATIC_INLINE void
S_trie_list_push(reg_trie_data *trie, const U32 state, const U32 octet,
@@ -601,7 +602,8 @@ Perl_make_trie(pTHX_ RExC_state_t *pRExC_state, regnode *startbranch,
PERL_UNUSED_ARG(depth);
#endif
switch (flags) {
- case EXACT: case EXACT_REQ8: case EXACTL: break;
+ case EXACT: case EXACT_REQ8: case EXACT_NF: case EXACT_NF_REQ8:
+ case EXACTL: break;
case EXACTFAA:
case EXACTFUP:
case EXACTFU:
@@ -734,10 +736,10 @@ Perl_make_trie(pTHX_ RExC_state_t *pRExC_state, regnode *startbranch,
}
if ( noper < tail
- && ( OP(noper) == flags
- || (flags == EXACT && OP(noper) == EXACT_REQ8)
- || (flags == EXACTFU && ( OP(noper) == EXACTFU_REQ8
- || OP(noper) == EXACTFUP))))
+ && TRIE_TYPE(flags)
+ && TRIE_COMPATIBLE_TYPE(TRIE_TYPE(flags),
+ TRIE_TYPE(OP(noper)))
+ == TRIE_TYPE(flags))
{
const U8 *uc= (U8*)STRING(noper);
const U8 *e= uc + STR_LEN(noper);
diff --git a/regexec.c b/regexec.c
index a4499f9fca..e40fb59362 100644
--- a/regexec.c
+++ b/regexec.c
@@ -1888,7 +1888,8 @@ Perl_re_intuit_start(pTHX_
trie_latin_utf8_fold, trie_utf8_exactfa_fold, \
trie_latin_utf8_exactfa_fold, \
trie_utf8l, trie_flu8, trie_flu8_latin } \
- trie_type = ((FLAGS(scan) == EXACT) \
+ trie_type = ((IS_EXACT_OR_NF(FLAGS(scan)) \
+ || IS_EXACT_REQ8_OR_NF_REQ8(FLAGS(scan))) \
? (utf8_target ? trie_utf8 : trie_plain) \
: (FLAGS(scan) == EXACTL) \
? (utf8_target ? trie_utf8l : trie_plain)\
@@ -7438,12 +7439,14 @@ S_regmatch(pTHX_ regmatch_info *reginfo, char *startpos, regnode *prog)
CHECK_AND_OUTPUT_WIDE_LOCALE_UTF8_MSG_(locinput, reginfo->strend);
}
goto do_exact;
+ case EXACT_NF_REQ8:
case EXACT_REQ8:
if (! utf8_target) {
sayNO;
}
/* FALLTHROUGH */
+ case EXACT_NF: /* non-folding text */
case EXACT: /* /abc/ */
do_exact:
s = STRINGs(scan);
@@ -10772,6 +10775,7 @@ S_regrepeat(pTHX_ regexp *prog, char **startposp, const regnode *p,
break;
case EXACT_REQ8_tb:
+ case EXACT_NF_REQ8_tb:
case LEXACT_REQ8_tb:
case EXACTFU_REQ8_tb:
break;
@@ -10791,12 +10795,15 @@ S_regrepeat(pTHX_ regexp *prog, char **startposp, const regnode *p,
/* FALLTHROUGH */
case EXACT_REQ8_t8:
+ case EXACT_NF_REQ8_t8:
case LEXACT_REQ8_t8:
case EXACTFU_REQ8_t8:
case LEXACT_t8:
case LEXACT_tb:
case EXACT_t8:
case EXACT_tb:
+ case EXACT_NF_t8:
+ case EXACT_NF_tb:
case EXACTF_t8:
case EXACTF_tb:
case EXACTFAA_NO_TRIE_t8:
diff --git a/regnodes.h b/regnodes.h
index 741b0924a2..b0af15fe8b 100644
--- a/regnodes.h
+++ b/regnodes.h
@@ -54,6 +54,8 @@ typedef struct regnode tregnode_EXACTFUP;
typedef struct regnode tregnode_EXACTFU_REQ8;
typedef struct regnode tregnode_EXACTFU_S_EDGE;
typedef struct regnode tregnode_EXACTL;
+typedef struct regnode tregnode_EXACT_NF;
+typedef struct regnode tregnode_EXACT_NF_REQ8;
typedef struct regnode tregnode_EXACT_REQ8;
typedef struct regnode_2 tregnode_GOSUB;
typedef struct regnode tregnode_GPOS;
@@ -127,8 +129,8 @@ typedef struct regnode tregnode_WHILEM;
/* Regops and State definitions */
-#define REGNODE_MAX 111
-#define REGMATCH_STATE_MAX 155
+#define REGNODE_MAX 113
+#define REGMATCH_STATE_MAX 157
/* -- For regexec.c to switch on target being utf8 (t8) or not (tb, b='byte'); */
#define with_t_UTF8ness(op, t_utf8) (((op) << 1) + (cBOOL(t_utf8)))
@@ -600,7 +602,10 @@ typedef struct regnode tregnode_WHILEM;
#define BRANCH_t8_p8 ((BRANCH) * 4 + 3)
/* 0x2b : 43
- EXACT - Match this string (flags field is the length). */
+ EXACT - Match this string (flags field is the length). The text is matched
+ exactly as is, without folding. Nodes of this type can only be safely
+ merged with other EXACT nodes or with EXACT_NF, but not with any folding
+ types like EXACTFU. */
#define EXACT (BRANCH + 1)
#define EXACT_tb ((EXACT) * 2)
#define EXACT_t8 ((EXACT) * 2 + 1)
@@ -631,9 +636,35 @@ typedef struct regnode tregnode_WHILEM;
#define EXACTL_t8_p8 ((EXACTL) * 4 + 3)
/* 0x2e : 46
+ EXACT_NF - Match this string of non-folding codepoints, meaning codepoints
+ which do not change under any folding function (flags field is the length).
+ For example, the '.' character is non-folding. This node type is for the
+ most part handled just like EXACT nodes, but EXACT_NF nodes have the
+ additional special property that they may be safely merged with any other
+ node type, and provided the result ends up with the other node's type then
+ it will still match correctly. */
+#define EXACT_NF (EXACTL + 1)
+#define EXACT_NF_tb ((EXACT_NF) * 2)
+#define EXACT_NF_t8 ((EXACT_NF) * 2 + 1)
+#define EXACT_NF_tb_pb ((EXACT_NF) * 4)
+#define EXACT_NF_tb_p8 ((EXACT_NF) * 4 + 1)
+#define EXACT_NF_t8_pb ((EXACT_NF) * 4 + 2)
+#define EXACT_NF_t8_p8 ((EXACT_NF) * 4 + 3)
+
+/* 0x2f : 47
+ EXACT_NF_REQ8 - Like EXACT_NF, but only UTF-8 encoded targets can match */
+#define EXACT_NF_REQ8 (EXACT_NF + 1)
+#define EXACT_NF_REQ8_tb ((EXACT_NF_REQ8) * 2)
+#define EXACT_NF_REQ8_t8 ((EXACT_NF_REQ8) * 2 + 1)
+#define EXACT_NF_REQ8_tb_pb ((EXACT_NF_REQ8) * 4)
+#define EXACT_NF_REQ8_tb_p8 ((EXACT_NF_REQ8) * 4 + 1)
+#define EXACT_NF_REQ8_t8_pb ((EXACT_NF_REQ8) * 4 + 2)
+#define EXACT_NF_REQ8_t8_p8 ((EXACT_NF_REQ8) * 4 + 3)
+
+/* 0x30 : 48
EXACTF - Like EXACT, but match using /id rules; (string not UTF-8, ASCII
folded; non-ASCII not) */
-#define EXACTF (EXACTL + 1)
+#define EXACTF (EXACT_NF_REQ8 + 1)
#define EXACTF_tb ((EXACTF) * 2)
#define EXACTF_t8 ((EXACTF) * 2 + 1)
#define EXACTF_tb_pb ((EXACTF) * 4)
@@ -641,7 +672,7 @@ typedef struct regnode tregnode_WHILEM;
#define EXACTF_t8_pb ((EXACTF) * 4 + 2)
#define EXACTF_t8_p8 ((EXACTF) * 4 + 3)
-/* 0x2f : 47
+/* 0x31 : 49
EXACTFL - Like EXACT, but match using /il rules; (string not likely to be
folded) */
#define EXACTFL (EXACTF + 1)
@@ -652,7 +683,7 @@ typedef struct regnode tregnode_WHILEM;
#define EXACTFL_t8_pb ((EXACTFL) * 4 + 2)
#define EXACTFL_t8_p8 ((EXACTFL) * 4 + 3)
-/* 0x30 : 48
+/* 0x32 : 50
EXACTFU - Like EXACT, but match using /iu rules; (string folded) */
#define EXACTFU (EXACTFL + 1)
#define EXACTFU_tb ((EXACTFU) * 2)
@@ -662,7 +693,7 @@ typedef struct regnode tregnode_WHILEM;
#define EXACTFU_t8_pb ((EXACTFU) * 4 + 2)
#define EXACTFU_t8_p8 ((EXACTFU) * 4 + 3)
-/* 0x31 : 49
+/* 0x33 : 51
EXACTFAA - Like EXACT, but match using /iaa rules; (string folded except
MICRO in non-UTF8 patterns; doesn't contain SHARP S unless UTF-8; folded
length <= unfolded) */
@@ -674,7 +705,7 @@ typedef struct regnode tregnode_WHILEM;
#define EXACTFAA_t8_pb ((EXACTFAA) * 4 + 2)
#define EXACTFAA_t8_p8 ((EXACTFAA) * 4 + 3)
-/* 0x32 : 50
+/* 0x34 : 52
EXACTFAA_NO_TRIE - Like EXACTFAA, (string not UTF-8, folded except: MICRO,
SHARP S; folded length <= unfolded, not currently trie-able) */
#define EXACTFAA_NO_TRIE (EXACTFAA + 1)
@@ -685,7 +716,7 @@ typedef struct regnode tregnode_WHILEM;
#define EXACTFAA_NO_TRIE_t8_pb ((EXACTFAA_NO_TRIE) * 4 + 2)
#define EXACTFAA_NO_TRIE_t8_p8 ((EXACTFAA_NO_TRIE) * 4 + 3)
-/* 0x33 : 51
+/* 0x35 : 53
EXACTFUP - Like EXACT, but match using /iu rules; (string not UTF-8, folded
except MICRO: hence Problematic) */
#define EXACTFUP (EXACTFAA_NO_TRIE + 1)
@@ -696,7 +727,7 @@ typedef struct regnode tregnode_WHILEM;
#define EXACTFUP_t8_pb ((EXACTFUP) * 4 + 2)
#define EXACTFUP_t8_p8 ((EXACTFUP) * 4 + 3)
-/* 0x34 : 52
+/* 0x36 : 54
EXACTFLU8 - Like EXACTFU, but use /il, UTF-8, (string is folded, and
everything in it is above 255 */
#define EXACTFLU8 (EXACTFUP + 1)
@@ -707,7 +738,7 @@ typedef struct regnode tregnode_WHILEM;
#define EXACTFLU8_t8_pb ((EXACTFLU8) * 4 + 2)
#define EXACTFLU8_t8_p8 ((EXACTFLU8) * 4 + 3)
-/* 0x35 : 53
+/* 0x37 : 55
EXACT_REQ8 - Like EXACT, but only UTF-8 encoded targets can match */
#define EXACT_REQ8 (EXACTFLU8 + 1)
#define EXACT_REQ8_tb ((EXACT_REQ8) * 2)
@@ -717,7 +748,7 @@ typedef struct regnode tregnode_WHILEM;
#define EXACT_REQ8_t8_pb ((EXACT_REQ8) * 4 + 2)
#define EXACT_REQ8_t8_p8 ((EXACT_REQ8) * 4 + 3)
-/* 0x36 : 54
+/* 0x38 : 56
LEXACT_REQ8 - Like LEXACT, but only UTF-8 encoded targets can match */
#define LEXACT_REQ8 (EXACT_REQ8 + 1)
#define LEXACT_REQ8_tb ((LEXACT_REQ8) * 2)
@@ -727,7 +758,7 @@ typedef struct regnode tregnode_WHILEM;
#define LEXACT_REQ8_t8_pb ((LEXACT_REQ8) * 4 + 2)
#define LEXACT_REQ8_t8_p8 ((LEXACT_REQ8) * 4 + 3)
-/* 0x37 : 55
+/* 0x39 : 57
EXACTFU_REQ8 - Like EXACTFU, but only UTF-8 encoded targets can match */
#define EXACTFU_REQ8 (LEXACT_REQ8 + 1)
#define EXACTFU_REQ8_tb ((EXACTFU_REQ8) * 2)
@@ -737,7 +768,7 @@ typedef struct regnode tregnode_WHILEM;
#define EXACTFU_REQ8_t8_pb ((EXACTFU_REQ8) * 4 + 2)
#define EXACTFU_REQ8_t8_p8 ((EXACTFU_REQ8) * 4 + 3)
-/* 0x38 : 56
+/* 0x3a : 58
EXACTFU_S_EDGE - /di rules, but nothing in it precludes /ui, except begins
and/or ends with [Ss]; (string not UTF-8; compile-time only) */
#define EXACTFU_S_EDGE (EXACTFU_REQ8 + 1)
@@ -748,7 +779,7 @@ typedef struct regnode tregnode_WHILEM;
#define EXACTFU_S_EDGE_t8_pb ((EXACTFU_S_EDGE) * 4 + 2)
#define EXACTFU_S_EDGE_t8_p8 ((EXACTFU_S_EDGE) * 4 + 3)
-/* 0x39 : 57
+/* 0x3b : 59
LNBREAK - generic newline pattern */
#define LNBREAK (EXACTFU_S_EDGE + 1)
#define LNBREAK_tb ((LNBREAK) * 2)
@@ -758,7 +789,7 @@ typedef struct regnode tregnode_WHILEM;
#define LNBREAK_t8_pb ((LNBREAK) * 4 + 2)
#define LNBREAK_t8_p8 ((LNBREAK) * 4 + 3)
-/* 0x3a : 58
+/* 0x3c : 60
TRIE - Match many EXACT(F[ALU]?)? at once. flags==type */
#define TRIE (LNBREAK + 1)
#define TRIE_tb ((TRIE) * 2)
@@ -768,7 +799,7 @@ typedef struct regnode tregnode_WHILEM;
#define TRIE_t8_pb ((TRIE) * 4 + 2)
#define TRIE_t8_p8 ((TRIE) * 4 + 3)
-/* 0x3b : 59
+/* 0x3d : 61
AHOCORASICK - Aho Corasick stclass. flags==type */
#define AHOCORASICK (TRIE + 1)
#define AHOCORASICK_tb ((AHOCORASICK) * 2)
@@ -778,7 +809,7 @@ typedef struct regnode tregnode_WHILEM;
#define AHOCORASICK_t8_pb ((AHOCORASICK) * 4 + 2)
#define AHOCORASICK_t8_p8 ((AHOCORASICK) * 4 + 3)
-/* 0x3c : 60
+/* 0x3e : 62
LTRIE - Same as TRIE, but with longjump support */
#define LTRIE (AHOCORASICK + 1)
#define LTRIE_tb ((LTRIE) * 2)
@@ -788,7 +819,7 @@ typedef struct regnode tregnode_WHILEM;
#define LTRIE_t8_pb ((LTRIE) * 4 + 2)
#define LTRIE_t8_p8 ((LTRIE) * 4 + 3)
-/* 0x3d : 61
+/* 0x3f : 63
NOTHING - Match empty string. */
#define NOTHING (LTRIE + 1)
#define NOTHING_tb ((NOTHING) * 2)
@@ -798,7 +829,7 @@ typedef struct regnode tregnode_WHILEM;
#define NOTHING_t8_pb ((NOTHING) * 4 + 2)
#define NOTHING_t8_p8 ((NOTHING) * 4 + 3)
-/* 0x3e : 62
+/* 0x40 : 64
TAIL - Match empty string. Can jump here from outside. */
#define TAIL (NOTHING + 1)
#define TAIL_tb ((TAIL) * 2)
@@ -808,7 +839,7 @@ typedef struct regnode tregnode_WHILEM;
#define TAIL_t8_pb ((TAIL) * 4 + 2)
#define TAIL_t8_p8 ((TAIL) * 4 + 3)
-/* 0x3f : 63
+/* 0x41 : 65
OPTIMIZED - This is not really a node, but an optimized away piece of a
"long" node. To simplify debugging output, we mark it as if it were a node */
#define OPTIMIZED (TAIL + 1)
@@ -819,7 +850,7 @@ typedef struct regnode tregnode_WHILEM;
#define OPTIMIZED_t8_pb ((OPTIMIZED) * 4 + 2)
#define OPTIMIZED_t8_p8 ((OPTIMIZED) * 4 + 3)
-/* 0x40 : 64
+/* 0x42 : 66
STAR - Match this (simple) thing 0 or more times: /A{0,}B/ where A is width
1 char */
#define STAR (OPTIMIZED + 1)
@@ -830,7 +861,7 @@ typedef struct regnode tregnode_WHILEM;
#define STAR_t8_pb ((STAR) * 4 + 2)
#define STAR_t8_p8 ((STAR) * 4 + 3)
-/* 0x41 : 65
+/* 0x43 : 67
PLUS - Match this (simple) thing 1 or more times: /A{1,}B/ where A is width
1 char */
#define PLUS (STAR + 1)
@@ -841,7 +872,7 @@ typedef struct regnode tregnode_WHILEM;
#define PLUS_t8_pb ((PLUS) * 4 + 2)
#define PLUS_t8_p8 ((PLUS) * 4 + 3)
-/* 0x42 : 66
+/* 0x44 : 68
CURLY - Match this (simple) thing {n,m} times: /A{m,n}B/ where A is width 1
char */
#define CURLY (PLUS + 1)
@@ -852,7 +883,7 @@ typedef struct regnode tregnode_WHILEM;
#define CURLY_t8_pb ((CURLY) * 4 + 2)
#define CURLY_t8_p8 ((CURLY) * 4 + 3)
-/* 0x43 : 67
+/* 0x45 : 69
CURLYN - Capture next-after-this simple thing: /(A){m,n}B/ where A is width
1 char */
#define CURLYN (CURLY + 1)
@@ -863,7 +894,7 @@ typedef struct regnode tregnode_WHILEM;
#define CURLYN_t8_pb ((CURLYN) * 4 + 2)
#define CURLYN_t8_p8 ((CURLYN) * 4 + 3)
-/* 0x44 : 68
+/* 0x46 : 70
CURLYM - Capture this medium-complex thing {n,m} times: /(A){m,n}B/ where A
is fixed-length */
#define CURLYM (CURLYN + 1)
@@ -874,7 +905,7 @@ typedef struct regnode tregnode_WHILEM;
#define CURLYM_t8_pb ((CURLYM) * 4 + 2)
#define CURLYM_t8_p8 ((CURLYM) * 4 + 3)
-/* 0x45 : 69
+/* 0x47 : 71
CURLYX - Match/Capture this complex thing {n,m} times. */
#define CURLYX (CURLYM + 1)
#define CURLYX_tb ((CURLYX) * 2)
@@ -884,7 +915,7 @@ typedef struct regnode tregnode_WHILEM;
#define CURLYX_t8_pb ((CURLYX) * 4 + 2)
#define CURLYX_t8_p8 ((CURLYX) * 4 + 3)
-/* 0x46 : 70
+/* 0x48 : 72
WHILEM - Do curly processing and see if rest matches. */
#define WHILEM (CURLYX + 1)
#define WHILEM_tb ((WHILEM) * 2)
@@ -894,7 +925,7 @@ typedef struct regnode tregnode_WHILEM;
#define WHILEM_t8_pb ((WHILEM) * 4 + 2)
#define WHILEM_t8_p8 ((WHILEM) * 4 + 3)
-/* 0x47 : 71
+/* 0x49 : 73
OPEN - Mark this point in input as start of #n. */
#define OPEN (WHILEM + 1)
#define OPEN_tb ((OPEN) * 2)
@@ -904,7 +935,7 @@ typedef struct regnode tregnode_WHILEM;
#define OPEN_t8_pb ((OPEN) * 4 + 2)
#define OPEN_t8_p8 ((OPEN) * 4 + 3)
-/* 0x48 : 72
+/* 0x4a : 74
CLOSE - Close corresponding OPEN of #n. */
#define CLOSE (OPEN + 1)
#define CLOSE_tb ((CLOSE) * 2)
@@ -914,7 +945,7 @@ typedef struct regnode tregnode_WHILEM;
#define CLOSE_t8_pb ((CLOSE) * 4 + 2)
#define CLOSE_t8_p8 ((CLOSE) * 4 + 3)
-/* 0x49 : 73
+/* 0x4b : 75
SROPEN - Start a script run */
#define SROPEN (CLOSE + 1)
#define SROPEN_tb ((SROPEN) * 2)
@@ -924,7 +955,7 @@ typedef struct regnode tregnode_WHILEM;
#define SROPEN_t8_pb ((SROPEN) * 4 + 2)
#define SROPEN_t8_p8 ((SROPEN) * 4 + 3)
-/* 0x4a : 74
+/* 0x4c : 76
SRCLOSE - */
#define SRCLOSE (SROPEN + 1)
#define SRCLOSE_tb ((SRCLOSE) * 2)
@@ -934,7 +965,7 @@ typedef struct regnode tregnode_WHILEM;
#define SRCLOSE_t8_pb ((SRCLOSE) * 4 + 2)
#define SRCLOSE_t8_p8 ((SRCLOSE) * 4 + 3)
-/* 0x4b : 75
+/* 0x4d : 77
REF - Match some already matched string */
#define REF (SRCLOSE + 1)
#define REF_tb ((REF) * 2)
@@ -944,7 +975,7 @@ typedef struct regnode tregnode_WHILEM;
#define REF_t8_pb ((REF) * 4 + 2)
#define REF_t8_p8 ((REF) * 4 + 3)
-/* 0x4c : 76
+/* 0x4e : 78
REFF - Match already matched string, using /di rules. */
#define REFF (REF + 1)
#define REFF_tb ((REFF) * 2)
@@ -954,7 +985,7 @@ typedef struct regnode tregnode_WHILEM;
#define REFF_t8_pb ((REFF) * 4 + 2)
#define REFF_t8_p8 ((REFF) * 4 + 3)
-/* 0x4d : 77
+/* 0x4f : 79
REFFL - Match already matched string, using /li rules. */
#define REFFL (REFF + 1)
#define REFFL_tb ((REFFL) * 2)
@@ -964,7 +995,7 @@ typedef struct regnode tregnode_WHILEM;
#define REFFL_t8_pb ((REFFL) * 4 + 2)
#define REFFL_t8_p8 ((REFFL) * 4 + 3)
-/* 0x4e : 78
+/* 0x50 : 80
REFFU - Match already matched string, using /ui. */
#define REFFU (REFFL + 1)
#define REFFU_tb ((REFFU) * 2)
@@ -974,7 +1005,7 @@ typedef struct regnode tregnode_WHILEM;
#define REFFU_t8_pb ((REFFU) * 4 + 2)
#define REFFU_t8_p8 ((REFFU) * 4 + 3)
-/* 0x4f : 79
+/* 0x51 : 81
REFFA - Match already matched string, using /aai rules. */
#define REFFA (REFFU + 1)
#define REFFA_tb ((REFFA) * 2)
@@ -984,7 +1015,7 @@ typedef struct regnode tregnode_WHILEM;
#define REFFA_t8_pb ((REFFA) * 4 + 2)
#define REFFA_t8_p8 ((REFFA) * 4 + 3)
-/* 0x50 : 80
+/* 0x52 : 82
REFN - Match some already matched string */
#define REFN (REFFA + 1)
#define REFN_tb ((REFN) * 2)
@@ -994,7 +1025,7 @@ typedef struct regnode tregnode_WHILEM;
#define REFN_t8_pb ((REFN) * 4 + 2)
#define REFN_t8_p8 ((REFN) * 4 + 3)
-/* 0x51 : 81
+/* 0x53 : 83
REFFN - Match already matched string, using /di rules. */
#define REFFN (REFN + 1)
#define REFFN_tb ((REFFN) * 2)
@@ -1004,7 +1035,7 @@ typedef struct regnode tregnode_WHILEM;
#define REFFN_t8_pb ((REFFN) * 4 + 2)
#define REFFN_t8_p8 ((REFFN) * 4 + 3)
-/* 0x52 : 82
+/* 0x54 : 84
REFFLN - Match already matched string, using /li rules. */
#define REFFLN (REFFN + 1)
#define REFFLN_tb ((REFFLN) * 2)
@@ -1014,7 +1045,7 @@ typedef struct regnode tregnode_WHILEM;
#define REFFLN_t8_pb ((REFFLN) * 4 + 2)
#define REFFLN_t8_p8 ((REFFLN) * 4 + 3)
-/* 0x53 : 83
+/* 0x55 : 85
REFFUN - Match already matched string, using /ui rules. */
#define REFFUN (REFFLN + 1)
#define REFFUN_tb ((REFFUN) * 2)
@@ -1024,7 +1055,7 @@ typedef struct regnode tregnode_WHILEM;
#define REFFUN_t8_pb ((REFFUN) * 4 + 2)
#define REFFUN_t8_p8 ((REFFUN) * 4 + 3)
-/* 0x54 : 84
+/* 0x56 : 86
REFFAN - Match already matched string, using /aai rules. */
#define REFFAN (REFFUN + 1)
#define REFFAN_tb ((REFFAN) * 2)
@@ -1034,7 +1065,7 @@ typedef struct regnode tregnode_WHILEM;
#define REFFAN_t8_pb ((REFFAN) * 4 + 2)
#define REFFAN_t8_p8 ((REFFAN) * 4 + 3)
-/* 0x55 : 85
+/* 0x57 : 87
BRANCHJ - BRANCH with long offset. */
#define BRANCHJ (REFFAN + 1)
#define BRANCHJ_tb ((BRANCHJ) * 2)
@@ -1044,7 +1075,7 @@ typedef struct regnode tregnode_WHILEM;
#define BRANCHJ_t8_pb ((BRANCHJ) * 4 + 2)
#define BRANCHJ_t8_p8 ((BRANCHJ) * 4 + 3)
-/* 0x56 : 86
+/* 0x58 : 88
IFMATCH - Succeeds if the following matches; non-zero flags "f", next_off
"o" means lookbehind assertion starting "f..(f-o)" characters before
current */
@@ -1056,7 +1087,7 @@ typedef struct regnode tregnode_WHILEM;
#define IFMATCH_t8_pb ((IFMATCH) * 4 + 2)
#define IFMATCH_t8_p8 ((IFMATCH) * 4 + 3)
-/* 0x57 : 87
+/* 0x59 : 89
UNLESSM - Fails if the following matches; non-zero flags "f", next_off "o"
means lookbehind assertion starting "f..(f-o)" characters before current */
#define UNLESSM (IFMATCH + 1)
@@ -1067,7 +1098,7 @@ typedef struct regnode tregnode_WHILEM;
#define UNLESSM_t8_pb ((UNLESSM) * 4 + 2)
#define UNLESSM_t8_p8 ((UNLESSM) * 4 + 3)
-/* 0x58 : 88
+/* 0x5a : 90
SUSPEND - "Independent" sub-RE. */
#define SUSPEND (UNLESSM + 1)
#define SUSPEND_tb ((SUSPEND) * 2)
@@ -1077,7 +1108,7 @@ typedef struct regnode tregnode_WHILEM;
#define SUSPEND_t8_pb ((SUSPEND) * 4 + 2)
#define SUSPEND_t8_p8 ((SUSPEND) * 4 + 3)
-/* 0x59 : 89
+/* 0x5b : 91
IFTHEN - Switch, should be preceded by switcher. */
#define IFTHEN (SUSPEND + 1)
#define IFTHEN_tb ((IFTHEN) * 2)
@@ -1087,7 +1118,7 @@ typedef struct regnode tregnode_WHILEM;
#define IFTHEN_t8_pb ((IFTHEN) * 4 + 2)
#define IFTHEN_t8_p8 ((IFTHEN) * 4 + 3)
-/* 0x5a : 90
+/* 0x5c : 92
RENUM - Group with independently numbered parens. Not used yet. */
#define RENUM (IFTHEN + 1)
#define RENUM_tb ((RENUM) * 2)
@@ -1097,7 +1128,7 @@ typedef struct regnode tregnode_WHILEM;
#define RENUM_t8_pb ((RENUM) * 4 + 2)
#define RENUM_t8_p8 ((RENUM) * 4 + 3)
-/* 0x5b : 91
+/* 0x5d : 93
LONGJMP - Jump far away. */
#define LONGJMP (RENUM + 1)
#define LONGJMP_tb ((LONGJMP) * 2)
@@ -1107,7 +1138,7 @@ typedef struct regnode tregnode_WHILEM;
#define LONGJMP_t8_pb ((LONGJMP) * 4 + 2)
#define LONGJMP_t8_p8 ((LONGJMP) * 4 + 3)
-/* 0x5c : 92
+/* 0x5e : 94
MINMOD - Next operator is not greedy. */
#define MINMOD (LONGJMP + 1)
#define MINMOD_tb ((MINMOD) * 2)
@@ -1117,7 +1148,7 @@ typedef struct regnode tregnode_WHILEM;
#define MINMOD_t8_pb ((MINMOD) * 4 + 2)
#define MINMOD_t8_p8 ((MINMOD) * 4 + 3)
-/* 0x5d : 93
+/* 0x5f : 95
LOGICAL - Next opcode should set the flag only. */
#define LOGICAL (MINMOD + 1)
#define LOGICAL_tb ((LOGICAL) * 2)
@@ -1127,7 +1158,7 @@ typedef struct regnode tregnode_WHILEM;
#define LOGICAL_t8_pb ((LOGICAL) * 4 + 2)
#define LOGICAL_t8_p8 ((LOGICAL) * 4 + 3)
-/* 0x5e : 94
+/* 0x60 : 96
EVAL - Execute some Perl code. Used by other opcodes in some cases */
#define EVAL (LOGICAL + 1)
#define EVAL_tb ((EVAL) * 2)
@@ -1137,7 +1168,7 @@ typedef struct regnode tregnode_WHILEM;
#define EVAL_t8_pb ((EVAL) * 4 + 2)
#define EVAL_t8_p8 ((EVAL) * 4 + 3)
-/* 0x5f : 95
+/* 0x61 : 97
GOSUB - recurse to paren arg1 at (signed) ofs arg2 */
#define GOSUB (EVAL + 1)
#define GOSUB_tb ((GOSUB) * 2)
@@ -1147,7 +1178,7 @@ typedef struct regnode tregnode_WHILEM;
#define GOSUB_t8_pb ((GOSUB) * 4 + 2)
#define GOSUB_t8_p8 ((GOSUB) * 4 + 3)
-/* 0x60 : 96
+/* 0x62 : 98
GROUPP - Whether the group matched. */
#define GROUPP (GOSUB + 1)
#define GROUPP_tb ((GROUPP) * 2)
@@ -1157,7 +1188,7 @@ typedef struct regnode tregnode_WHILEM;
#define GROUPP_t8_pb ((GROUPP) * 4 + 2)
#define GROUPP_t8_p8 ((GROUPP) * 4 + 3)
-/* 0x61 : 97
+/* 0x63 : 99
GROUPPN - Whether the named group matched. */
#define GROUPPN (GROUPP + 1)
#define GROUPPN_tb ((GROUPPN) * 2)
@@ -1167,7 +1198,7 @@ typedef struct regnode tregnode_WHILEM;
#define GROUPPN_t8_pb ((GROUPPN) * 4 + 2)
#define GROUPPN_t8_p8 ((GROUPPN) * 4 + 3)
-/* 0x62 : 98
+/* 0x64 : 100
INSUBP - Whether we are in a specific recurse. */
#define INSUBP (GROUPPN + 1)
#define INSUBP_tb ((INSUBP) * 2)
@@ -1177,7 +1208,7 @@ typedef struct regnode tregnode_WHILEM;
#define INSUBP_t8_pb ((INSUBP) * 4 + 2)
#define INSUBP_t8_p8 ((INSUBP) * 4 + 3)
-/* 0x63 : 99
+/* 0x65 : 101
DEFINEP - Define regex subroutines. Contents never executed directly,
disallows 'no' branch in conditional. */
#define DEFINEP (INSUBP + 1)
@@ -1188,7 +1219,7 @@ typedef struct regnode tregnode_WHILEM;
#define DEFINEP_t8_pb ((DEFINEP) * 4 + 2)
#define DEFINEP_t8_p8 ((DEFINEP) * 4 + 3)
-/* 0x64 : 100
+/* 0x66 : 102
ENDLIKE - Used only for the type field of verbs */
#define ENDLIKE (DEFINEP + 1)
#define ENDLIKE_tb ((ENDLIKE) * 2)
@@ -1198,7 +1229,7 @@ typedef struct regnode tregnode_WHILEM;
#define ENDLIKE_t8_pb ((ENDLIKE) * 4 + 2)
#define ENDLIKE_t8_p8 ((ENDLIKE) * 4 + 3)
-/* 0x65 : 101
+/* 0x67 : 103
OPFAIL - Same as (?!), but with verb arg */
#define OPFAIL (ENDLIKE + 1)
#define OPFAIL_tb ((OPFAIL) * 2)
@@ -1208,7 +1239,7 @@ typedef struct regnode tregnode_WHILEM;
#define OPFAIL_t8_pb ((OPFAIL) * 4 + 2)
#define OPFAIL_t8_p8 ((OPFAIL) * 4 + 3)
-/* 0x66 : 102
+/* 0x68 : 104
ACCEPT - Accepts the current matched string, with verbar */
#define ACCEPT (OPFAIL + 1)
#define ACCEPT_tb ((ACCEPT) * 2)
@@ -1218,7 +1249,7 @@ typedef struct regnode tregnode_WHILEM;
#define ACCEPT_t8_pb ((ACCEPT) * 4 + 2)
#define ACCEPT_t8_p8 ((ACCEPT) * 4 + 3)
-/* 0x67 : 103
+/* 0x69 : 105
VERB - Used only for the type field of verbs */
#define VERB (ACCEPT + 1)
#define VERB_tb ((VERB) * 2)
@@ -1228,7 +1259,7 @@ typedef struct regnode tregnode_WHILEM;
#define VERB_t8_pb ((VERB) * 4 + 2)
#define VERB_t8_p8 ((VERB) * 4 + 3)
-/* 0x68 : 104
+/* 0x6a : 106
PRUNE - Pattern fails at this startpoint if no-backtracking through this */
#define PRUNE (VERB + 1)
#define PRUNE_tb ((PRUNE) * 2)
@@ -1238,7 +1269,7 @@ typedef struct regnode tregnode_WHILEM;
#define PRUNE_t8_pb ((PRUNE) * 4 + 2)
#define PRUNE_t8_p8 ((PRUNE) * 4 + 3)
-/* 0x69 : 105
+/* 0x6b : 107
MARKPOINT - Push the current location for rollback by cut. */
#define MARKPOINT (PRUNE + 1)
#define MARKPOINT_tb ((MARKPOINT) * 2)
@@ -1248,7 +1279,7 @@ typedef struct regnode tregnode_WHILEM;
#define MARKPOINT_t8_pb ((MARKPOINT) * 4 + 2)
#define MARKPOINT_t8_p8 ((MARKPOINT) * 4 + 3)
-/* 0x6a : 106
+/* 0x6c : 108
SKIP - On failure skip forward (to the mark) before retrying */
#define SKIP (MARKPOINT + 1)
#define SKIP_tb ((SKIP) * 2)
@@ -1258,7 +1289,7 @@ typedef struct regnode tregnode_WHILEM;
#define SKIP_t8_pb ((SKIP) * 4 + 2)
#define SKIP_t8_p8 ((SKIP) * 4 + 3)
-/* 0x6b : 107
+/* 0x6d : 109
COMMIT - Pattern fails outright if backtracking through this */
#define COMMIT (SKIP + 1)
#define COMMIT_tb ((COMMIT) * 2)
@@ -1268,7 +1299,7 @@ typedef struct regnode tregnode_WHILEM;
#define COMMIT_t8_pb ((COMMIT) * 4 + 2)
#define COMMIT_t8_p8 ((COMMIT) * 4 + 3)
-/* 0x6c : 108
+/* 0x6e : 110
CUTGROUP - On failure go to the next alternation in the group */
#define CUTGROUP (COMMIT + 1)
#define CUTGROUP_tb ((CUTGROUP) * 2)
@@ -1278,7 +1309,7 @@ typedef struct regnode tregnode_WHILEM;
#define CUTGROUP_t8_pb ((CUTGROUP) * 4 + 2)
#define CUTGROUP_t8_p8 ((CUTGROUP) * 4 + 3)
-/* 0x6d : 109
+/* 0x6f : 111
KEEPS - $& begins here. */
#define KEEPS (CUTGROUP + 1)
#define KEEPS_tb ((KEEPS) * 2)
@@ -1288,7 +1319,7 @@ typedef struct regnode tregnode_WHILEM;
#define KEEPS_t8_pb ((KEEPS) * 4 + 2)
#define KEEPS_t8_p8 ((KEEPS) * 4 + 3)
-/* 0x6e : 110
+/* 0x70 : 112
PSEUDO - Pseudo opcode for internal use. */
#define PSEUDO (KEEPS + 1)
#define PSEUDO_tb ((PSEUDO) * 2)
@@ -1298,7 +1329,7 @@ typedef struct regnode tregnode_WHILEM;
#define PSEUDO_t8_pb ((PSEUDO) * 4 + 2)
#define PSEUDO_t8_p8 ((PSEUDO) * 4 + 3)
-/* 0x6f : 111
+/* 0x71 : 113
REGEX_SET - Regex set, temporary node used in pre-optimization compilation */
#define REGEX_SET (PSEUDO + 1)
#define REGEX_SET_tb ((REGEX_SET) * 2)
@@ -1309,7 +1340,7 @@ typedef struct regnode tregnode_WHILEM;
#define REGEX_SET_t8_p8 ((REGEX_SET) * 4 + 3)
/* ------------ States ------------- */
-/* 0x70 : 112
+/* 0x72 : 114
TRIE_next - state for TRIE */
#define TRIE_next (REGNODE_MAX + 1)
#define TRIE_next_tb ((TRIE_next) * 2)
@@ -1319,7 +1350,7 @@ typedef struct regnode tregnode_WHILEM;
#define TRIE_next_t8_pb ((TRIE_next) * 4 + 2)
#define TRIE_next_t8_p8 ((TRIE_next) * 4 + 3)
-/* 0x71 : 113
+/* 0x73 : 115
TRIE_next_fail - state for TRIE */
#define TRIE_next_fail (TRIE_next + 1)
#define TRIE_next_fail_tb ((TRIE_next_fail) * 2)
@@ -1329,7 +1360,7 @@ typedef struct regnode tregnode_WHILEM;
#define TRIE_next_fail_t8_pb ((TRIE_next_fail) * 4 + 2)
#define TRIE_next_fail_t8_p8 ((TRIE_next_fail) * 4 + 3)
-/* 0x72 : 114
+/* 0x74 : 116
EVAL_B - state for EVAL */
#define EVAL_B (TRIE_next_fail + 1)
#define EVAL_B_tb ((EVAL_B) * 2)
@@ -1339,7 +1370,7 @@ typedef struct regnode tregnode_WHILEM;
#define EVAL_B_t8_pb ((EVAL_B) * 4 + 2)
#define EVAL_B_t8_p8 ((EVAL_B) * 4 + 3)
-/* 0x73 : 115
+/* 0x75 : 117
EVAL_B_fail - state for EVAL */
#define EVAL_B_fail (EVAL_B + 1)
#define EVAL_B_fail_tb ((EVAL_B_fail) * 2)
@@ -1349,7 +1380,7 @@ typedef struct regnode tregnode_WHILEM;
#define EVAL_B_fail_t8_pb ((EVAL_B_fail) * 4 + 2)
#define EVAL_B_fail_t8_p8 ((EVAL_B_fail) * 4 + 3)
-/* 0x74 : 116
+/* 0x76 : 118
EVAL_postponed_A - state for EVAL */
#define EVAL_postponed_A (EVAL_B_fail + 1)
#define EVAL_postponed_A_tb ((EVAL_postponed_A) * 2)
@@ -1359,7 +1390,7 @@ typedef struct regnode tregnode_WHILEM;
#define EVAL_postponed_A_t8_pb ((EVAL_postponed_A) * 4 + 2)
#define EVAL_postponed_A_t8_p8 ((EVAL_postponed_A) * 4 + 3)
-/* 0x75 : 117
+/* 0x77 : 119
EVAL_postponed_A_fail - state for EVAL */
#define EVAL_postponed_A_fail (EVAL_postponed_A + 1)
#define EVAL_postponed_A_fail_tb ((EVAL_postponed_A_fail) * 2)
@@ -1369,7 +1400,7 @@ typedef struct regnode tregnode_WHILEM;
#define EVAL_postponed_A_fail_t8_pb ((EVAL_postponed_A_fail) * 4 + 2)
#define EVAL_postponed_A_fail_t8_p8 ((EVAL_postponed_A_fail) * 4 + 3)
-/* 0x76 : 118
+/* 0x78 : 120
EVAL_postponed_B - state for EVAL */
#define EVAL_postponed_B (EVAL_postponed_A_fail + 1)
#define EVAL_postponed_B_tb ((EVAL_postponed_B) * 2)
@@ -1379,7 +1410,7 @@ typedef struct regnode tregnode_WHILEM;
#define EVAL_postponed_B_t8_pb ((EVAL_postponed_B) * 4 + 2)
#define EVAL_postponed_B_t8_p8 ((EVAL_postponed_B) * 4 + 3)
-/* 0x77 : 119
+/* 0x79 : 121
EVAL_postponed_B_fail - state for EVAL */
#define EVAL_postponed_B_fail (EVAL_postponed_B + 1)
#define EVAL_postponed_B_fail_tb ((EVAL_postponed_B_fail) * 2)
@@ -1389,7 +1420,7 @@ typedef struct regnode tregnode_WHILEM;
#define EVAL_postponed_B_fail_t8_pb ((EVAL_postponed_B_fail) * 4 + 2)
#define EVAL_postponed_B_fail_t8_p8 ((EVAL_postponed_B_fail) * 4 + 3)
-/* 0x78 : 120
+/* 0x7a : 122
CURLYX_end - state for CURLYX */
#define CURLYX_end (EVAL_postponed_B_fail + 1)
#define CURLYX_end_tb ((CURLYX_end) * 2)
@@ -1399,7 +1430,7 @@ typedef struct regnode tregnode_WHILEM;
#define CURLYX_end_t8_pb ((CURLYX_end) * 4 + 2)
#define CURLYX_end_t8_p8 ((CURLYX_end) * 4 + 3)
-/* 0x79 : 121
+/* 0x7b : 123
CURLYX_end_fail - state for CURLYX */
#define CURLYX_end_fail (CURLYX_end + 1)
#define CURLYX_end_fail_tb ((CURLYX_end_fail) * 2)
@@ -1409,7 +1440,7 @@ typedef struct regnode tregnode_WHILEM;
#define CURLYX_end_fail_t8_pb ((CURLYX_end_fail) * 4 + 2)
#define CURLYX_end_fail_t8_p8 ((CURLYX_end_fail) * 4 + 3)
-/* 0x7a : 122
+/* 0x7c : 124
WHILEM_A_pre - state for WHILEM */
#define WHILEM_A_pre (CURLYX_end_fail + 1)
#define WHILEM_A_pre_tb ((WHILEM_A_pre) * 2)
@@ -1419,7 +1450,7 @@ typedef struct regnode tregnode_WHILEM;
#define WHILEM_A_pre_t8_pb ((WHILEM_A_pre) * 4 + 2)
#define WHILEM_A_pre_t8_p8 ((WHILEM_A_pre) * 4 + 3)
-/* 0x7b : 123
+/* 0x7d : 125
WHILEM_A_pre_fail - state for WHILEM */
#define WHILEM_A_pre_fail (WHILEM_A_pre + 1)
#define WHILEM_A_pre_fail_tb ((WHILEM_A_pre_fail) * 2)
@@ -1429,7 +1460,7 @@ typedef struct regnode tregnode_WHILEM;
#define WHILEM_A_pre_fail_t8_pb ((WHILEM_A_pre_fail) * 4 + 2)
#define WHILEM_A_pre_fail_t8_p8 ((WHILEM_A_pre_fail) * 4 + 3)
-/* 0x7c : 124
+/* 0x7e : 126
WHILEM_A_min - state for WHILEM */
#define WHILEM_A_min (WHILEM_A_pre_fail + 1)
#define WHILEM_A_min_tb ((WHILEM_A_min) * 2)
@@ -1439,7 +1470,7 @@ typedef struct regnode tregnode_WHILEM;
#define WHILEM_A_min_t8_pb ((WHILEM_A_min) * 4 + 2)
#define WHILEM_A_min_t8_p8 ((WHILEM_A_min) * 4 + 3)
-/* 0x7d : 125
+/* 0x7f : 127
WHILEM_A_min_fail - state for WHILEM */
#define WHILEM_A_min_fail (WHILEM_A_min + 1)
#define WHILEM_A_min_fail_tb ((WHILEM_A_min_fail) * 2)
@@ -1449,7 +1480,7 @@ typedef struct regnode tregnode_WHILEM;
#define WHILEM_A_min_fail_t8_pb ((WHILEM_A_min_fail) * 4 + 2)
#define WHILEM_A_min_fail_t8_p8 ((WHILEM_A_min_fail) * 4 + 3)
-/* 0x7e : 126
+/* 0x80 : 128
WHILEM_A_max - state for WHILEM */
#define WHILEM_A_max (WHILEM_A_min_fail + 1)
#define WHILEM_A_max_tb ((WHILEM_A_max) * 2)
@@ -1459,7 +1490,7 @@ typedef struct regnode tregnode_WHILEM;
#define WHILEM_A_max_t8_pb ((WHILEM_A_max) * 4 + 2)
#define WHILEM_A_max_t8_p8 ((WHILEM_A_max) * 4 + 3)
-/* 0x7f : 127
+/* 0x81 : 129
WHILEM_A_max_fail - state for WHILEM */
#define WHILEM_A_max_fail (WHILEM_A_max + 1)
#define WHILEM_A_max_fail_tb ((WHILEM_A_max_fail) * 2)
@@ -1469,7 +1500,7 @@ typedef struct regnode tregnode_WHILEM;
#define WHILEM_A_max_fail_t8_pb ((WHILEM_A_max_fail) * 4 + 2)
#define WHILEM_A_max_fail_t8_p8 ((WHILEM_A_max_fail) * 4 + 3)
-/* 0x80 : 128
+/* 0x82 : 130
WHILEM_B_min - state for WHILEM */
#define WHILEM_B_min (WHILEM_A_max_fail + 1)
#define WHILEM_B_min_tb ((WHILEM_B_min) * 2)
@@ -1479,7 +1510,7 @@ typedef struct regnode tregnode_WHILEM;
#define WHILEM_B_min_t8_pb ((WHILEM_B_min) * 4 + 2)
#define WHILEM_B_min_t8_p8 ((WHILEM_B_min) * 4 + 3)
-/* 0x81 : 129
+/* 0x83 : 131
WHILEM_B_min_fail - state for WHILEM */
#define WHILEM_B_min_fail (WHILEM_B_min + 1)
#define WHILEM_B_min_fail_tb ((WHILEM_B_min_fail) * 2)
@@ -1489,7 +1520,7 @@ typedef struct regnode tregnode_WHILEM;
#define WHILEM_B_min_fail_t8_pb ((WHILEM_B_min_fail) * 4 + 2)
#define WHILEM_B_min_fail_t8_p8 ((WHILEM_B_min_fail) * 4 + 3)
-/* 0x82 : 130
+/* 0x84 : 132
WHILEM_B_max - state for WHILEM */
#define WHILEM_B_max (WHILEM_B_min_fail + 1)
#define WHILEM_B_max_tb ((WHILEM_B_max) * 2)
@@ -1499,7 +1530,7 @@ typedef struct regnode tregnode_WHILEM;
#define WHILEM_B_max_t8_pb ((WHILEM_B_max) * 4 + 2)
#define WHILEM_B_max_t8_p8 ((WHILEM_B_max) * 4 + 3)
-/* 0x83 : 131
+/* 0x85 : 133
WHILEM_B_max_fail - state for WHILEM */
#define WHILEM_B_max_fail (WHILEM_B_max + 1)
#define WHILEM_B_max_fail_tb ((WHILEM_B_max_fail) * 2)
@@ -1509,7 +1540,7 @@ typedef struct regnode tregnode_WHILEM;
#define WHILEM_B_max_fail_t8_pb ((WHILEM_B_max_fail) * 4 + 2)
#define WHILEM_B_max_fail_t8_p8 ((WHILEM_B_max_fail) * 4 + 3)
-/* 0x84 : 132
+/* 0x86 : 134
BRANCH_next - state for BRANCH */
#define BRANCH_next (WHILEM_B_max_fail + 1)
#define BRANCH_next_tb ((BRANCH_next) * 2)
@@ -1519,7 +1550,7 @@ typedef struct regnode tregnode_WHILEM;
#define BRANCH_next_t8_pb ((BRANCH_next) * 4 + 2)
#define BRANCH_next_t8_p8 ((BRANCH_next) * 4 + 3)
-/* 0x85 : 133
+/* 0x87 : 135
BRANCH_next_fail - state for BRANCH */
#define BRANCH_next_fail (BRANCH_next + 1)
#define BRANCH_next_fail_tb ((BRANCH_next_fail) * 2)
@@ -1529,7 +1560,7 @@ typedef struct regnode tregnode_WHILEM;
#define BRANCH_next_fail_t8_pb ((BRANCH_next_fail) * 4 + 2)
#define BRANCH_next_fail_t8_p8 ((BRANCH_next_fail) * 4 + 3)
-/* 0x86 : 134
+/* 0x88 : 136
CURLYM_A - state for CURLYM */
#define CURLYM_A (BRANCH_next_fail + 1)
#define CURLYM_A_tb ((CURLYM_A) * 2)
@@ -1539,7 +1570,7 @@ typedef struct regnode tregnode_WHILEM;
#define CURLYM_A_t8_pb ((CURLYM_A) * 4 + 2)
#define CURLYM_A_t8_p8 ((CURLYM_A) * 4 + 3)
-/* 0x87 : 135
+/* 0x89 : 137
CURLYM_A_fail - state for CURLYM */
#define CURLYM_A_fail (CURLYM_A + 1)
#define CURLYM_A_fail_tb ((CURLYM_A_fail) * 2)
@@ -1549,7 +1580,7 @@ typedef struct regnode tregnode_WHILEM;
#define CURLYM_A_fail_t8_pb ((CURLYM_A_fail) * 4 + 2)
#define CURLYM_A_fail_t8_p8 ((CURLYM_A_fail) * 4 + 3)
-/* 0x88 : 136
+/* 0x8a : 138
CURLYM_B - state for CURLYM */
#define CURLYM_B (CURLYM_A_fail + 1)
#define CURLYM_B_tb ((CURLYM_B) * 2)
@@ -1559,7 +1590,7 @@ typedef struct regnode tregnode_WHILEM;
#define CURLYM_B_t8_pb ((CURLYM_B) * 4 + 2)
#define CURLYM_B_t8_p8 ((CURLYM_B) * 4 + 3)
-/* 0x89 : 137
+/* 0x8b : 139
CURLYM_B_fail - state for CURLYM */
#define CURLYM_B_fail (CURLYM_B + 1)
#define CURLYM_B_fail_tb ((CURLYM_B_fail) * 2)
@@ -1569,7 +1600,7 @@ typedef struct regnode tregnode_WHILEM;
#define CURLYM_B_fail_t8_pb ((CURLYM_B_fail) * 4 + 2)
#define CURLYM_B_fail_t8_p8 ((CURLYM_B_fail) * 4 + 3)
-/* 0x8a : 138
+/* 0x8c : 140
IFMATCH_A - state for IFMATCH */
#define IFMATCH_A (CURLYM_B_fail + 1)
#define IFMATCH_A_tb ((IFMATCH_A) * 2)
@@ -1579,7 +1610,7 @@ typedef struct regnode tregnode_WHILEM;
#define IFMATCH_A_t8_pb ((IFMATCH_A) * 4 + 2)
#define IFMATCH_A_t8_p8 ((IFMATCH_A) * 4 + 3)
-/* 0x8b : 139
+/* 0x8d : 141
IFMATCH_A_fail - state for IFMATCH */
#define IFMATCH_A_fail (IFMATCH_A + 1)
#define IFMATCH_A_fail_tb ((IFMATCH_A_fail) * 2)
@@ -1589,7 +1620,7 @@ typedef struct regnode tregnode_WHILEM;
#define IFMATCH_A_fail_t8_pb ((IFMATCH_A_fail) * 4 + 2)
#define IFMATCH_A_fail_t8_p8 ((IFMATCH_A_fail) * 4 + 3)
-/* 0x8c : 140
+/* 0x8e : 142
CURLY_B_min - state for CURLY */
#define CURLY_B_min (IFMATCH_A_fail + 1)
#define CURLY_B_min_tb ((CURLY_B_min) * 2)
@@ -1599,7 +1630,7 @@ typedef struct regnode tregnode_WHILEM;
#define CURLY_B_min_t8_pb ((CURLY_B_min) * 4 + 2)
#define CURLY_B_min_t8_p8 ((CURLY_B_min) * 4 + 3)
-/* 0x8d : 141
+/* 0x8f : 143
CURLY_B_min_fail - state for CURLY */
#define CURLY_B_min_fail (CURLY_B_min + 1)
#define CURLY_B_min_fail_tb ((CURLY_B_min_fail) * 2)
@@ -1609,7 +1640,7 @@ typedef struct regnode tregnode_WHILEM;
#define CURLY_B_min_fail_t8_pb ((CURLY_B_min_fail) * 4 + 2)
#define CURLY_B_min_fail_t8_p8 ((CURLY_B_min_fail) * 4 + 3)
-/* 0x8e : 142
+/* 0x90 : 144
CURLY_B_max - state for CURLY */
#define CURLY_B_max (CURLY_B_min_fail + 1)
#define CURLY_B_max_tb ((CURLY_B_max) * 2)
@@ -1619,7 +1650,7 @@ typedef struct regnode tregnode_WHILEM;
#define CURLY_B_max_t8_pb ((CURLY_B_max) * 4 + 2)
#define CURLY_B_max_t8_p8 ((CURLY_B_max) * 4 + 3)
-/* 0x8f : 143
+/* 0x91 : 145
CURLY_B_max_fail - state for CURLY */
#define CURLY_B_max_fail (CURLY_B_max + 1)
#define CURLY_B_max_fail_tb ((CURLY_B_max_fail) * 2)
@@ -1629,7 +1660,7 @@ typedef struct regnode tregnode_WHILEM;
#define CURLY_B_max_fail_t8_pb ((CURLY_B_max_fail) * 4 + 2)
#define CURLY_B_max_fail_t8_p8 ((CURLY_B_max_fail) * 4 + 3)
-/* 0x90 : 144
+/* 0x92 : 146
COMMIT_next - state for COMMIT */
#define COMMIT_next (CURLY_B_max_fail + 1)
#define COMMIT_next_tb ((COMMIT_next) * 2)
@@ -1639,7 +1670,7 @@ typedef struct regnode tregnode_WHILEM;
#define COMMIT_next_t8_pb ((COMMIT_next) * 4 + 2)
#define COMMIT_next_t8_p8 ((COMMIT_next) * 4 + 3)
-/* 0x91 : 145
+/* 0x93 : 147
COMMIT_next_fail - state for COMMIT */
#define COMMIT_next_fail (COMMIT_next + 1)
#define COMMIT_next_fail_tb ((COMMIT_next_fail) * 2)
@@ -1649,7 +1680,7 @@ typedef struct regnode tregnode_WHILEM;
#define COMMIT_next_fail_t8_pb ((COMMIT_next_fail) * 4 + 2)
#define COMMIT_next_fail_t8_p8 ((COMMIT_next_fail) * 4 + 3)
-/* 0x92 : 146
+/* 0x94 : 148
MARKPOINT_next - state for MARKPOINT */
#define MARKPOINT_next (COMMIT_next_fail + 1)
#define MARKPOINT_next_tb ((MARKPOINT_next) * 2)
@@ -1659,7 +1690,7 @@ typedef struct regnode tregnode_WHILEM;
#define MARKPOINT_next_t8_pb ((MARKPOINT_next) * 4 + 2)
#define MARKPOINT_next_t8_p8 ((MARKPOINT_next) * 4 + 3)
-/* 0x93 : 147
+/* 0x95 : 149
MARKPOINT_next_fail - state for MARKPOINT */
#define MARKPOINT_next_fail (MARKPOINT_next + 1)
#define MARKPOINT_next_fail_tb ((MARKPOINT_next_fail) * 2)
@@ -1669,7 +1700,7 @@ typedef struct regnode tregnode_WHILEM;
#define MARKPOINT_next_fail_t8_pb ((MARKPOINT_next_fail) * 4 + 2)
#define MARKPOINT_next_fail_t8_p8 ((MARKPOINT_next_fail) * 4 + 3)
-/* 0x94 : 148
+/* 0x96 : 150
SKIP_next - state for SKIP */
#define SKIP_next (MARKPOINT_next_fail + 1)
#define SKIP_next_tb ((SKIP_next) * 2)
@@ -1679,7 +1710,7 @@ typedef struct regnode tregnode_WHILEM;
#define SKIP_next_t8_pb ((SKIP_next) * 4 + 2)
#define SKIP_next_t8_p8 ((SKIP_next) * 4 + 3)
-/* 0x95 : 149
+/* 0x97 : 151
SKIP_next_fail - state for SKIP */
#define SKIP_next_fail (SKIP_next + 1)
#define SKIP_next_fail_tb ((SKIP_next_fail) * 2)
@@ -1689,7 +1720,7 @@ typedef struct regnode tregnode_WHILEM;
#define SKIP_next_fail_t8_pb ((SKIP_next_fail) * 4 + 2)
#define SKIP_next_fail_t8_p8 ((SKIP_next_fail) * 4 + 3)
-/* 0x96 : 150
+/* 0x98 : 152
CUTGROUP_next - state for CUTGROUP */
#define CUTGROUP_next (SKIP_next_fail + 1)
#define CUTGROUP_next_tb ((CUTGROUP_next) * 2)
@@ -1699,7 +1730,7 @@ typedef struct regnode tregnode_WHILEM;
#define CUTGROUP_next_t8_pb ((CUTGROUP_next) * 4 + 2)
#define CUTGROUP_next_t8_p8 ((CUTGROUP_next) * 4 + 3)
-/* 0x97 : 151
+/* 0x99 : 153
CUTGROUP_next_fail - state for CUTGROUP */
#define CUTGROUP_next_fail (CUTGROUP_next + 1)
#define CUTGROUP_next_fail_tb ((CUTGROUP_next_fail) * 2)
@@ -1709,7 +1740,7 @@ typedef struct regnode tregnode_WHILEM;
#define CUTGROUP_next_fail_t8_pb ((CUTGROUP_next_fail) * 4 + 2)
#define CUTGROUP_next_fail_t8_p8 ((CUTGROUP_next_fail) * 4 + 3)
-/* 0x98 : 152
+/* 0x9a : 154
KEEPS_next - state for KEEPS */
#define KEEPS_next (CUTGROUP_next_fail + 1)
#define KEEPS_next_tb ((KEEPS_next) * 2)
@@ -1719,7 +1750,7 @@ typedef struct regnode tregnode_WHILEM;
#define KEEPS_next_t8_pb ((KEEPS_next) * 4 + 2)
#define KEEPS_next_t8_p8 ((KEEPS_next) * 4 + 3)
-/* 0x99 : 153
+/* 0x9b : 155
KEEPS_next_fail - state for KEEPS */
#define KEEPS_next_fail (KEEPS_next + 1)
#define KEEPS_next_fail_tb ((KEEPS_next_fail) * 2)
@@ -1729,7 +1760,7 @@ typedef struct regnode tregnode_WHILEM;
#define KEEPS_next_fail_t8_pb ((KEEPS_next_fail) * 4 + 2)
#define KEEPS_next_fail_t8_p8 ((KEEPS_next_fail) * 4 + 3)
-/* 0x9a : 154
+/* 0x9c : 156
REF_next - state for REF */
#define REF_next (KEEPS_next_fail + 1)
#define REF_next_tb ((REF_next) * 2)
@@ -1739,7 +1770,7 @@ typedef struct regnode tregnode_WHILEM;
#define REF_next_t8_pb ((REF_next) * 4 + 2)
#define REF_next_t8_p8 ((REF_next) * 4 + 3)
-/* 0x9b : 155
+/* 0x9d : 157
REF_next_fail - state for REF */
#define REF_next_fail (REF_next + 1)
#define REF_next_fail_tb ((REF_next_fail) * 2)
@@ -1799,72 +1830,74 @@ EXTCONST char * const PL_regnode_name[] INIT( {
"EXACT", /* 0x2b */
"LEXACT", /* 0x2c */
"EXACTL", /* 0x2d */
- "EXACTF", /* 0x2e */
- "EXACTFL", /* 0x2f */
- "EXACTFU", /* 0x30 */
- "EXACTFAA", /* 0x31 */
- "EXACTFAA_NO_TRIE", /* 0x32 */
- "EXACTFUP", /* 0x33 */
- "EXACTFLU8", /* 0x34 */
- "EXACT_REQ8", /* 0x35 */
- "LEXACT_REQ8", /* 0x36 */
- "EXACTFU_REQ8", /* 0x37 */
- "EXACTFU_S_EDGE", /* 0x38 */
- "LNBREAK", /* 0x39 */
- "TRIE", /* 0x3a */
- "AHOCORASICK", /* 0x3b */
- "LTRIE", /* 0x3c */
- "NOTHING", /* 0x3d */
- "TAIL", /* 0x3e */
- "OPTIMIZED", /* 0x3f */
- "STAR", /* 0x40 */
- "PLUS", /* 0x41 */
- "CURLY", /* 0x42 */
- "CURLYN", /* 0x43 */
- "CURLYM", /* 0x44 */
- "CURLYX", /* 0x45 */
- "WHILEM", /* 0x46 */
- "OPEN", /* 0x47 */
- "CLOSE", /* 0x48 */
- "SROPEN", /* 0x49 */
- "SRCLOSE", /* 0x4a */
- "REF", /* 0x4b */
- "REFF", /* 0x4c */
- "REFFL", /* 0x4d */
- "REFFU", /* 0x4e */
- "REFFA", /* 0x4f */
- "REFN", /* 0x50 */
- "REFFN", /* 0x51 */
- "REFFLN", /* 0x52 */
- "REFFUN", /* 0x53 */
- "REFFAN", /* 0x54 */
- "BRANCHJ", /* 0x55 */
- "IFMATCH", /* 0x56 */
- "UNLESSM", /* 0x57 */
- "SUSPEND", /* 0x58 */
- "IFTHEN", /* 0x59 */
- "RENUM", /* 0x5a */
- "LONGJMP", /* 0x5b */
- "MINMOD", /* 0x5c */
- "LOGICAL", /* 0x5d */
- "EVAL", /* 0x5e */
- "GOSUB", /* 0x5f */
- "GROUPP", /* 0x60 */
- "GROUPPN", /* 0x61 */
- "INSUBP", /* 0x62 */
- "DEFINEP", /* 0x63 */
- "ENDLIKE", /* 0x64 */
- "OPFAIL", /* 0x65 */
- "ACCEPT", /* 0x66 */
- "VERB", /* 0x67 */
- "PRUNE", /* 0x68 */
- "MARKPOINT", /* 0x69 */
- "SKIP", /* 0x6a */
- "COMMIT", /* 0x6b */
- "CUTGROUP", /* 0x6c */
- "KEEPS", /* 0x6d */
- "PSEUDO", /* 0x6e */
- "REGEX_SET", /* 0x6f */
+ "EXACT_NF", /* 0x2e */
+ "EXACT_NF_REQ8", /* 0x2f */
+ "EXACTF", /* 0x30 */
+ "EXACTFL", /* 0x31 */
+ "EXACTFU", /* 0x32 */
+ "EXACTFAA", /* 0x33 */
+ "EXACTFAA_NO_TRIE", /* 0x34 */
+ "EXACTFUP", /* 0x35 */
+ "EXACTFLU8", /* 0x36 */
+ "EXACT_REQ8", /* 0x37 */
+ "LEXACT_REQ8", /* 0x38 */
+ "EXACTFU_REQ8", /* 0x39 */
+ "EXACTFU_S_EDGE", /* 0x3a */
+ "LNBREAK", /* 0x3b */
+ "TRIE", /* 0x3c */
+ "AHOCORASICK", /* 0x3d */
+ "LTRIE", /* 0x3e */
+ "NOTHING", /* 0x3f */
+ "TAIL", /* 0x40 */
+ "OPTIMIZED", /* 0x41 */
+ "STAR", /* 0x42 */
+ "PLUS", /* 0x43 */
+ "CURLY", /* 0x44 */
+ "CURLYN", /* 0x45 */
+ "CURLYM", /* 0x46 */
+ "CURLYX", /* 0x47 */
+ "WHILEM", /* 0x48 */
+ "OPEN", /* 0x49 */
+ "CLOSE", /* 0x4a */
+ "SROPEN", /* 0x4b */
+ "SRCLOSE", /* 0x4c */
+ "REF", /* 0x4d */
+ "REFF", /* 0x4e */
+ "REFFL", /* 0x4f */
+ "REFFU", /* 0x50 */
+ "REFFA", /* 0x51 */
+ "REFN", /* 0x52 */
+ "REFFN", /* 0x53 */
+ "REFFLN", /* 0x54 */
+ "REFFUN", /* 0x55 */
+ "REFFAN", /* 0x56 */
+ "BRANCHJ", /* 0x57 */
+ "IFMATCH", /* 0x58 */
+ "UNLESSM", /* 0x59 */
+ "SUSPEND", /* 0x5a */
+ "IFTHEN", /* 0x5b */
+ "RENUM", /* 0x5c */
+ "LONGJMP", /* 0x5d */
+ "MINMOD", /* 0x5e */
+ "LOGICAL", /* 0x5f */
+ "EVAL", /* 0x60 */
+ "GOSUB", /* 0x61 */
+ "GROUPP", /* 0x62 */
+ "GROUPPN", /* 0x63 */
+ "INSUBP", /* 0x64 */
+ "DEFINEP", /* 0x65 */
+ "ENDLIKE", /* 0x66 */
+ "OPFAIL", /* 0x67 */
+ "ACCEPT", /* 0x68 */
+ "VERB", /* 0x69 */
+ "PRUNE", /* 0x6a */
+ "MARKPOINT", /* 0x6b */
+ "SKIP", /* 0x6c */
+ "COMMIT", /* 0x6d */
+ "CUTGROUP", /* 0x6e */
+ "KEEPS", /* 0x6f */
+ "PSEUDO", /* 0x70 */
+ "REGEX_SET", /* 0x71 */
/* ------------ States ------------- */
"TRIE_next", /* REGNODE_MAX +0x01 */
"TRIE_next_fail", /* REGNODE_MAX +0x02 */
@@ -2239,770 +2272,784 @@ EXTCONST struct regnode_meta PL_regnode_info[] INIT( {
.off_by_arg = 0
},
{
- /* #46 op EXACTF */
+ /* #46 op EXACT_NF */
+ .type = EXACT,
+ .arg_len = 0,
+ .arg_len_varies = 1,
+ .off_by_arg = 0
+ },
+ {
+ /* #47 op EXACT_NF_REQ8 */
+ .type = EXACT,
+ .arg_len = 0,
+ .arg_len_varies = 1,
+ .off_by_arg = 0
+ },
+ {
+ /* #48 op EXACTF */
.type = EXACT,
.arg_len = 0,
.arg_len_varies = 1,
.off_by_arg = 0
},
{
- /* #47 op EXACTFL */
+ /* #49 op EXACTFL */
.type = EXACT,
.arg_len = 0,
.arg_len_varies = 1,
.off_by_arg = 0
},
{
- /* #48 op EXACTFU */
+ /* #50 op EXACTFU */
.type = EXACT,
.arg_len = 0,
.arg_len_varies = 1,
.off_by_arg = 0
},
{
- /* #49 op EXACTFAA */
+ /* #51 op EXACTFAA */
.type = EXACT,
.arg_len = 0,
.arg_len_varies = 1,
.off_by_arg = 0
},
{
- /* #50 op EXACTFAA_NO_TRIE */
+ /* #52 op EXACTFAA_NO_TRIE */
.type = EXACT,
.arg_len = 0,
.arg_len_varies = 1,
.off_by_arg = 0
},
{
- /* #51 op EXACTFUP */
+ /* #53 op EXACTFUP */
.type = EXACT,
.arg_len = 0,
.arg_len_varies = 1,
.off_by_arg = 0
},
{
- /* #52 op EXACTFLU8 */
+ /* #54 op EXACTFLU8 */
.type = EXACT,
.arg_len = 0,
.arg_len_varies = 1,
.off_by_arg = 0
},
{
- /* #53 op EXACT_REQ8 */
+ /* #55 op EXACT_REQ8 */
.type = EXACT,
.arg_len = 0,
.arg_len_varies = 1,
.off_by_arg = 0
},
{
- /* #54 op LEXACT_REQ8 */
+ /* #56 op LEXACT_REQ8 */
.type = EXACT,
.arg_len = EXTRA_SIZE(tregnode_LEXACT_REQ8),
.arg_len_varies = 1,
.off_by_arg = 0
},
{
- /* #55 op EXACTFU_REQ8 */
+ /* #57 op EXACTFU_REQ8 */
.type = EXACT,
.arg_len = 0,
.arg_len_varies = 1,
.off_by_arg = 0
},
{
- /* #56 op EXACTFU_S_EDGE */
+ /* #58 op EXACTFU_S_EDGE */
.type = EXACT,
.arg_len = 0,
.arg_len_varies = 1,
.off_by_arg = 0
},
{
- /* #57 op LNBREAK */
+ /* #59 op LNBREAK */
.type = LNBREAK,
.arg_len = 0,
.arg_len_varies = 0,
.off_by_arg = 0
},
{
- /* #58 op TRIE */
+ /* #60 op TRIE */
.type = TRIE,
.arg_len = EXTRA_SIZE(tregnode_TRIE),
.arg_len_varies = 0,
.off_by_arg = 0
},
{
- /* #59 op AHOCORASICK */
+ /* #61 op AHOCORASICK */
.type = TRIE,
.arg_len = EXTRA_SIZE(tregnode_AHOCORASICK),
.arg_len_varies = 0,
.off_by_arg = 0
},
{
- /* #60 op LTRIE */
+ /* #62 op LTRIE */
.type = TRIE,
.arg_len = EXTRA_SIZE(tregnode_LTRIE),
.arg_len_varies = 0,
.off_by_arg = 0
},
{
- /* #61 op NOTHING */
+ /* #63 op NOTHING */
.type = NOTHING,
.arg_len = 0,
.arg_len_varies = 0,
.off_by_arg = 0
},
{
- /* #62 op TAIL */
+ /* #64 op TAIL */
.type = NOTHING,
.arg_len = 0,
.arg_len_varies = 0,
.off_by_arg = 0
},
{
- /* #63 op OPTIMIZED */
+ /* #65 op OPTIMIZED */
.type = NOTHING,
.arg_len = 0,
.arg_len_varies = 0,
.off_by_arg = 0
},
{
- /* #64 op STAR */
+ /* #66 op STAR */
.type = STAR,
.arg_len = 0,
.arg_len_varies = 0,
.off_by_arg = 0
},
{
- /* #65 op PLUS */
+ /* #67 op PLUS */
.type = PLUS,
.arg_len = 0,
.arg_len_varies = 0,
.off_by_arg = 0
},
{
- /* #66 op CURLY */
+ /* #68 op CURLY */
.type = CURLY,
.arg_len = EXTRA_SIZE(tregnode_CURLY),
.arg_len_varies = 0,
.off_by_arg = 0
},
{
- /* #67 op CURLYN */
+ /* #69 op CURLYN */
.type = CURLY,
.arg_len = EXTRA_SIZE(tregnode_CURLYN),
.arg_len_varies = 0,
.off_by_arg = 0
},
{
- /* #68 op CURLYM */
+ /* #70 op CURLYM */
.type = CURLY,
.arg_len = EXTRA_SIZE(tregnode_CURLYM),
.arg_len_varies = 0,
.off_by_arg = 0
},
{
- /* #69 op CURLYX */
+ /* #71 op CURLYX */
.type = CURLY,
.arg_len = EXTRA_SIZE(tregnode_CURLYX),
.arg_len_varies = 0,
.off_by_arg = 0
},
{
- /* #70 op WHILEM */
+ /* #72 op WHILEM */
.type = WHILEM,
.arg_len = 0,
.arg_len_varies = 0,
.off_by_arg = 0
},
{
- /* #71 op OPEN */
+ /* #73 op OPEN */
.type = OPEN,
.arg_len = EXTRA_SIZE(tregnode_OPEN),
.arg_len_varies = 0,
.off_by_arg = 0
},
{
- /* #72 op CLOSE */
+ /* #74 op CLOSE */
.type = CLOSE,
.arg_len = EXTRA_SIZE(tregnode_CLOSE),
.arg_len_varies = 0,
.off_by_arg = 0
},
{
- /* #73 op SROPEN */
+ /* #75 op SROPEN */
.type = SROPEN,
.arg_len = 0,
.arg_len_varies = 0,
.off_by_arg = 0
},
{
- /* #74 op SRCLOSE */
+ /* #76 op SRCLOSE */
.type = SRCLOSE,
.arg_len = 0,
.arg_len_varies = 0,
.off_by_arg = 0
},
{
- /* #75 op REF */
+ /* #77 op REF */
.type = REF,
.arg_len = EXTRA_SIZE(tregnode_REF),
.arg_len_varies = 0,
.off_by_arg = 0
},
{
- /* #76 op REFF */
+ /* #78 op REFF */
.type = REF,
.arg_len = EXTRA_SIZE(tregnode_REFF),
.arg_len_varies = 0,
.off_by_arg = 0
},
{
- /* #77 op REFFL */
+ /* #79 op REFFL */
.type = REF,
.arg_len = EXTRA_SIZE(tregnode_REFFL),
.arg_len_varies = 0,
.off_by_arg = 0
},
{
- /* #78 op REFFU */
+ /* #80 op REFFU */
.type = REF,
.arg_len = EXTRA_SIZE(tregnode_REFFU),
.arg_len_varies = 0,
.off_by_arg = 0
},
{
- /* #79 op REFFA */
+ /* #81 op REFFA */
.type = REF,
.arg_len = EXTRA_SIZE(tregnode_REFFA),
.arg_len_varies = 0,
.off_by_arg = 0
},
{
- /* #80 op REFN */
+ /* #82 op REFN */
.type = REF,
.arg_len = EXTRA_SIZE(tregnode_REFN),
.arg_len_varies = 0,
.off_by_arg = 0
},
{
- /* #81 op REFFN */
+ /* #83 op REFFN */
.type = REF,
.arg_len = EXTRA_SIZE(tregnode_REFFN),
.arg_len_varies = 0,
.off_by_arg = 0
},
{
- /* #82 op REFFLN */
+ /* #84 op REFFLN */
.type = REF,
.arg_len = EXTRA_SIZE(tregnode_REFFLN),
.arg_len_varies = 0,
.off_by_arg = 0
},
{
- /* #83 op REFFUN */
+ /* #85 op REFFUN */
.type = REF,
.arg_len = EXTRA_SIZE(tregnode_REFFUN),
.arg_len_varies = 0,
.off_by_arg = 0
},
{
- /* #84 op REFFAN */
+ /* #86 op REFFAN */
.type = REF,
.arg_len = EXTRA_SIZE(tregnode_REFFAN),
.arg_len_varies = 0,
.off_by_arg = 0
},
{
- /* #85 op BRANCHJ */
+ /* #87 op BRANCHJ */
.type = BRANCHJ,
.arg_len = EXTRA_SIZE(tregnode_BRANCHJ),
.arg_len_varies = 0,
.off_by_arg = 1
},
{
- /* #86 op IFMATCH */
+ /* #88 op IFMATCH */
.type = BRANCHJ,
.arg_len = EXTRA_SIZE(tregnode_IFMATCH),
.arg_len_varies = 0,
.off_by_arg = 1
},
{
- /* #87 op UNLESSM */
+ /* #89 op UNLESSM */
.type = BRANCHJ,
.arg_len = EXTRA_SIZE(tregnode_UNLESSM),
.arg_len_varies = 0,
.off_by_arg = 1
},
{
- /* #88 op SUSPEND */
+ /* #90 op SUSPEND */
.type = BRANCHJ,
.arg_len = EXTRA_SIZE(tregnode_SUSPEND),
.arg_len_varies = 0,
.off_by_arg = 1
},
{
- /* #89 op IFTHEN */
+ /* #91 op IFTHEN */
.type = BRANCHJ,
.arg_len = EXTRA_SIZE(tregnode_IFTHEN),
.arg_len_varies = 0,
.off_by_arg = 1
},
{
- /* #90 op RENUM */
+ /* #92 op RENUM */
.type = BRANCHJ,
.arg_len = EXTRA_SIZE(tregnode_RENUM),
.arg_len_varies = 0,
.off_by_arg = 1
},
{
- /* #91 op LONGJMP */
+ /* #93 op LONGJMP */
.type = LONGJMP,
.arg_len = EXTRA_SIZE(tregnode_LONGJMP),
.arg_len_varies = 0,
.off_by_arg = 1
},
{
- /* #92 op MINMOD */
+ /* #94 op MINMOD */
.type = MINMOD,
.arg_len = 0,
.arg_len_varies = 0,
.off_by_arg = 0
},
{
- /* #93 op LOGICAL */
+ /* #95 op LOGICAL */
.type = LOGICAL,
.arg_len = 0,
.arg_len_varies = 0,
.off_by_arg = 0
},
{
- /* #94 op EVAL */
+ /* #96 op EVAL */
.type = EVAL,
.arg_len = EXTRA_SIZE(tregnode_EVAL),
.arg_len_varies = 0,
.off_by_arg = 0
},
{
- /* #95 op GOSUB */
+ /* #97 op GOSUB */
.type = GOSUB,
.arg_len = EXTRA_SIZE(tregnode_GOSUB),
.arg_len_varies = 0,
.off_by_arg = 0
},
{
- /* #96 op GROUPP */
+ /* #98 op GROUPP */
.type = GROUPP,
.arg_len = EXTRA_SIZE(tregnode_GROUPP),
.arg_len_varies = 0,
.off_by_arg = 0
},
{
- /* #97 op GROUPPN */
+ /* #99 op GROUPPN */
.type = GROUPPN,
.arg_len = EXTRA_SIZE(tregnode_GROUPPN),
.arg_len_varies = 0,
.off_by_arg = 0
},
{
- /* #98 op INSUBP */
+ /* #100 op INSUBP */
.type = INSUBP,
.arg_len = EXTRA_SIZE(tregnode_INSUBP),
.arg_len_varies = 0,
.off_by_arg = 0
},
{
- /* #99 op DEFINEP */
+ /* #101 op DEFINEP */
.type = DEFINEP,
.arg_len = EXTRA_SIZE(tregnode_DEFINEP),
.arg_len_varies = 0,
.off_by_arg = 0
},
{
- /* #100 op ENDLIKE */
+ /* #102 op ENDLIKE */
.type = ENDLIKE,
.arg_len = 0,
.arg_len_varies = 0,
.off_by_arg = 0
},
{
- /* #101 op OPFAIL */
+ /* #103 op OPFAIL */
.type = ENDLIKE,
.arg_len = EXTRA_SIZE(tregnode_OPFAIL),
.arg_len_varies = 0,
.off_by_arg = 0
},
{
- /* #102 op ACCEPT */
+ /* #104 op ACCEPT */
.type = ENDLIKE,
.arg_len = EXTRA_SIZE(tregnode_ACCEPT),
.arg_len_varies = 0,
.off_by_arg = 0
},
{
- /* #103 op VERB */
+ /* #105 op VERB */
.type = VERB,
.arg_len = EXTRA_SIZE(tregnode_VERB),
.arg_len_varies = 0,
.off_by_arg = 0
},
{
- /* #104 op PRUNE */
+ /* #106 op PRUNE */
.type = VERB,
.arg_len = EXTRA_SIZE(tregnode_PRUNE),
.arg_len_varies = 0,
.off_by_arg = 0
},
{
- /* #105 op MARKPOINT */
+ /* #107 op MARKPOINT */
.type = VERB,
.arg_len = EXTRA_SIZE(tregnode_MARKPOINT),
.arg_len_varies = 0,
.off_by_arg = 0
},
{
- /* #106 op SKIP */
+ /* #108 op SKIP */
.type = VERB,
.arg_len = EXTRA_SIZE(tregnode_SKIP),
.arg_len_varies = 0,
.off_by_arg = 0
},
{
- /* #107 op COMMIT */
+ /* #109 op COMMIT */
.type = VERB,
.arg_len = EXTRA_SIZE(tregnode_COMMIT),
.arg_len_varies = 0,
.off_by_arg = 0
},
{
- /* #108 op CUTGROUP */
+ /* #110 op CUTGROUP */
.type = VERB,
.arg_len = EXTRA_SIZE(tregnode_CUTGROUP),
.arg_len_varies = 0,
.off_by_arg = 0
},
{
- /* #109 op KEEPS */
+ /* #111 op KEEPS */
.type = KEEPS,
.arg_len = 0,
.arg_len_varies = 0,
.off_by_arg = 0
},
{
- /* #110 op PSEUDO */
+ /* #112 op PSEUDO */
.type = PSEUDO,
.arg_len = 0,
.arg_len_varies = 0,
.off_by_arg = 0
},
{
- /* #111 op REGEX_SET */
+ /* #113 op REGEX_SET */
.type = REGEX_SET,
.arg_len = EXTRA_SIZE(tregnode_REGEX_SET),
.arg_len_varies = 0,
.off_by_arg = 0
},
{
- /* #112 state TRIE_next */
+ /* #114 state TRIE_next */
.type = TRIE,
.arg_len = 0,
.arg_len_varies = 0,
.off_by_arg = 0
},
{
- /* #113 state TRIE_next_fail */
+ /* #115 state TRIE_next_fail */
.type = TRIE,
.arg_len = 0,
.arg_len_varies = 0,
.off_by_arg = 0
},
{
- /* #114 state EVAL_B */
+ /* #116 state EVAL_B */
.type = EVAL,
.arg_len = 0,
.arg_len_varies = 0,
.off_by_arg = 0
},
{
- /* #115 state EVAL_B_fail */
+ /* #117 state EVAL_B_fail */
.type = EVAL,
.arg_len = 0,
.arg_len_varies = 0,
.off_by_arg = 0
},
{
- /* #116 state EVAL_postponed_A */
+ /* #118 state EVAL_postponed_A */
.type = EVAL,
.arg_len = 0,
.arg_len_varies = 0,
.off_by_arg = 0
},
{
- /* #117 state EVAL_postponed_A_fail */
+ /* #119 state EVAL_postponed_A_fail */
.type = EVAL,
.arg_len = 0,
.arg_len_varies = 0,
.off_by_arg = 0
},
{
- /* #118 state EVAL_postponed_B */
+ /* #120 state EVAL_postponed_B */
.type = EVAL,
.arg_len = 0,
.arg_len_varies = 0,
.off_by_arg = 0
},
{
- /* #119 state EVAL_postponed_B_fail */
+ /* #121 state EVAL_postponed_B_fail */
.type = EVAL,
.arg_len = 0,
.arg_len_varies = 0,
.off_by_arg = 0
},
{
- /* #120 state CURLYX_end */
+ /* #122 state CURLYX_end */
.type = CURLYX,
.arg_len = 0,
.arg_len_varies = 0,
.off_by_arg = 0
},
{
- /* #121 state CURLYX_end_fail */
+ /* #123 state CURLYX_end_fail */
.type = CURLYX,
.arg_len = 0,
.arg_len_varies = 0,
.off_by_arg = 0
},
{
- /* #122 state WHILEM_A_pre */
+ /* #124 state WHILEM_A_pre */
.type = WHILEM,
.arg_len = 0,
.arg_len_varies = 0,
.off_by_arg = 0
},
{
- /* #123 state WHILEM_A_pre_fail */
+ /* #125 state WHILEM_A_pre_fail */
.type = WHILEM,
.arg_len = 0,
.arg_len_varies = 0,
.off_by_arg = 0
},
{
- /* #124 state WHILEM_A_min */
+ /* #126 state WHILEM_A_min */
.type = WHILEM,
.arg_len = 0,
.arg_len_varies = 0,
.off_by_arg = 0
},
{
- /* #125 state WHILEM_A_min_fail */
+ /* #127 state WHILEM_A_min_fail */
.type = WHILEM,
.arg_len = 0,
.arg_len_varies = 0,
.off_by_arg = 0
},
{
- /* #126 state WHILEM_A_max */
+ /* #128 state WHILEM_A_max */
.type = WHILEM,
.arg_len = 0,
.arg_len_varies = 0,
.off_by_arg = 0
},
{
- /* #127 state WHILEM_A_max_fail */
+ /* #129 state WHILEM_A_max_fail */
.type = WHILEM,
.arg_len = 0,
.arg_len_varies = 0,
.off_by_arg = 0
},
{
- /* #128 state WHILEM_B_min */
+ /* #130 state WHILEM_B_min */
.type = WHILEM,
.arg_len = 0,
.arg_len_varies = 0,
.off_by_arg = 0
},
{
- /* #129 state WHILEM_B_min_fail */
+ /* #131 state WHILEM_B_min_fail */
.type = WHILEM,
.arg_len = 0,
.arg_len_varies = 0,
.off_by_arg = 0
},
{
- /* #130 state WHILEM_B_max */
+ /* #132 state WHILEM_B_max */
.type = WHILEM,
.arg_len = 0,
.arg_len_varies = 0,
.off_by_arg = 0
},
{
- /* #131 state WHILEM_B_max_fail */
+ /* #133 state WHILEM_B_max_fail */
.type = WHILEM,
.arg_len = 0,
.arg_len_varies = 0,
.off_by_arg = 0
},
{
- /* #132 state BRANCH_next */
+ /* #134 state BRANCH_next */
.type = BRANCH,
.arg_len = 0,
.arg_len_varies = 0,
.off_by_arg = 0
},
{
- /* #133 state BRANCH_next_fail */
+ /* #135 state BRANCH_next_fail */
.type = BRANCH,
.arg_len = 0,
.arg_len_varies = 0,
.off_by_arg = 0
},
{
- /* #134 state CURLYM_A */
+ /* #136 state CURLYM_A */
.type = CURLYM,
.arg_len = 0,
.arg_len_varies = 0,
.off_by_arg = 0
},
{
- /* #135 state CURLYM_A_fail */
+ /* #137 state CURLYM_A_fail */
.type = CURLYM,
.arg_len = 0,
.arg_len_varies = 0,
.off_by_arg = 0
},
{
- /* #136 state CURLYM_B */
+ /* #138 state CURLYM_B */
.type = CURLYM,
.arg_len = 0,
.arg_len_varies = 0,
.off_by_arg = 0
},
{
- /* #137 state CURLYM_B_fail */
+ /* #139 state CURLYM_B_fail */
.type = CURLYM,
.arg_len = 0,
.arg_len_varies = 0,
.off_by_arg = 0
},
{
- /* #138 state IFMATCH_A */
+ /* #140 state IFMATCH_A */
.type = IFMATCH,
.arg_len = 0,
.arg_len_varies = 0,
.off_by_arg = 0
},
{
- /* #139 state IFMATCH_A_fail */
+ /* #141 state IFMATCH_A_fail */
.type = IFMATCH,
.arg_len = 0,
.arg_len_varies = 0,
.off_by_arg = 0
},
{
- /* #140 state CURLY_B_min */
+ /* #142 state CURLY_B_min */
.type = CURLY,
.arg_len = 0,
.arg_len_varies = 0,
.off_by_arg = 0
},
{
- /* #141 state CURLY_B_min_fail */
+ /* #143 state CURLY_B_min_fail */
.type = CURLY,
.arg_len = 0,
.arg_len_varies = 0,
.off_by_arg = 0
},
{
- /* #142 state CURLY_B_max */
+ /* #144 state CURLY_B_max */
.type = CURLY,
.arg_len = 0,
.arg_len_varies = 0,
.off_by_arg = 0
},
{
- /* #143 state CURLY_B_max_fail */
+ /* #145 state CURLY_B_max_fail */
.type = CURLY,
.arg_len = 0,
.arg_len_varies = 0,
.off_by_arg = 0
},
{
- /* #144 state COMMIT_next */
+ /* #146 state COMMIT_next */
.type = COMMIT,
.arg_len = 0,
.arg_len_varies = 0,
.off_by_arg = 0
},
{
- /* #145 state COMMIT_next_fail */
+ /* #147 state COMMIT_next_fail */
.type = COMMIT,
.arg_len = 0,
.arg_len_varies = 0,
.off_by_arg = 0
},
{
- /* #146 state MARKPOINT_next */
+ /* #148 state MARKPOINT_next */
.type = MARKPOINT,
.arg_len = 0,
.arg_len_varies = 0,
.off_by_arg = 0
},
{
- /* #147 state MARKPOINT_next_fail */
+ /* #149 state MARKPOINT_next_fail */
.type = MARKPOINT,
.arg_len = 0,
.arg_len_varies = 0,
.off_by_arg = 0
},
{
- /* #148 state SKIP_next */
+ /* #150 state SKIP_next */
.type = SKIP,
.arg_len = 0,
.arg_len_varies = 0,
.off_by_arg = 0
},
{
- /* #149 state SKIP_next_fail */
+ /* #151 state SKIP_next_fail */
.type = SKIP,
.arg_len = 0,
.arg_len_varies = 0,
.off_by_arg = 0
},
{
- /* #150 state CUTGROUP_next */
+ /* #152 state CUTGROUP_next */
.type = CUTGROUP,
.arg_len = 0,
.arg_len_varies = 0,
.off_by_arg = 0
},
{
- /* #151 state CUTGROUP_next_fail */
+ /* #153 state CUTGROUP_next_fail */
.type = CUTGROUP,
.arg_len = 0,
.arg_len_varies = 0,
.off_by_arg = 0
},
{
- /* #152 state KEEPS_next */
+ /* #154 state KEEPS_next */
.type = KEEPS,
.arg_len = 0,
.arg_len_varies = 0,
.off_by_arg = 0
},
{
- /* #153 state KEEPS_next_fail */
+ /* #155 state KEEPS_next_fail */
.type = KEEPS,
.arg_len = 0,
.arg_len_varies = 0,
.off_by_arg = 0
},
{
- /* #154 state REF_next */
+ /* #156 state REF_next */
.type = REF,
.arg_len = 0,
.arg_len_varies = 0,
.off_by_arg = 0
},
{
- /* #155 state REF_next_fail */
+ /* #157 state REF_next_fail */
.type = REF,
.arg_len = 0,
.arg_len_varies = 0,
@@ -3085,8 +3132,8 @@ INIT({ CLUMP, BRANCH, STAR, PLUS, CURLY, CURLYN, CURLYM, CURLYX, WHILEM, REF,
BRANCHJ, SUSPEND, IFTHEN,
0 });
-/* varies: 0000000000000000000000000000000000000000000001100000000000000000011111111111100000111111000000110000000000000000 */
-EXTCONST U8 PL_varies_bitmask[] INIT({ 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x7F, 0xF8, 0x3F, 0x03, 0x00, 0x00 });
+/* varies: 000000000000000000000000000000000000000000000110000000000000000011111100111000011111111100001100000000000000000000000000 */
+EXTCONST U8 PL_varies_bitmask[] INIT({ 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0xFC, 0xE1, 0xFF, 0x0C, 0x00, 0x00, 0x00 });
/* The following always have a length of 1. U8 we can do strchr() on it. */
/* (Note that length 1 means "one character" under UTF8, not "one octet".) */
@@ -3099,8 +3146,8 @@ INIT({ REG_ANY, SANY, ANYOF, ANYOFD, ANYOFL, ANYOFPOSIXL, ANYOFH, ANYOFHb,
REGEX_SET,
0 });
-/* simple: 0000000000000000111111101111111111111111000000010000000000000000000000000000000000000000000000000000000010000000 */
-EXTCONST U8 PL_simple_bitmask[] INIT({ 0x00, 0x00, 0xFE, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80 });
+/* simple: 000000000000000011111110111111111111111100000001000000000000000000000000000000000000000000000000000000000000000000000010 */
+EXTCONST U8 PL_simple_bitmask[] INIT({ 0x00, 0x00, 0xFE, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02 });
/* Is 'op', known to be of type EXACT, folding? */
#define isEXACTFish(op) (assert(REGNODE_TYPE(op) == EXACT), (PL_EXACTFish_bitmask & (1U << (op - EXACT))))
@@ -3108,8 +3155,8 @@ EXTCONST U8 PL_simple_bitmask[] INIT({ 0x00, 0x00, 0xFE, 0xFF, 0xFF, 0x01, 0x00,
/* Do only UTF-8 target strings match 'op', known to be of type EXACT? */
#define isEXACT_REQ8(op) (assert(REGNODE_TYPE(op) == EXACT), (PL_EXACT_REQ8_bitmask & (1U << (op - EXACT))))
-EXTCONST U32 PL_EXACTFish_bitmask INIT(0x33F8);
-EXTCONST U32 PL_EXACT_REQ8_bitmask INIT(0x1E00);
+EXTCONST U32 PL_EXACTFish_bitmask INIT(0xCFE0);
+EXTCONST U32 PL_EXACT_REQ8_bitmask INIT(0x7810);
#endif /* defined(PERL_CORE) || defined(PERL_EXT_RE_BUILD) */
diff --git a/t/re/anyof.t b/t/re/anyof.t
index 751e946ffc..ceb338cffd 100644
--- a/t/re/anyof.t
+++ b/t/re/anyof.t
@@ -717,8 +717,8 @@ my @tests = (
'(?8)(?i)[\x{410}]' => 'EXACTFU_REQ8 <\x{430}>',
'(?8)(?i)[\x{399}]' => 'EXACTFU_REQ8 <\x{3b9}>',
'(?8)(?i)[\x{345}\x{399}\x{3B9}\x{1FBE}]' => 'EXACTFU_REQ8 <\x{3b9}>',
- '(?i)[\x{2b9}]' => 'EXACT_REQ8 <\x{2b9}>', # Doesn't participate in a fold
- '(?8)(?i)[\x{2b9}]' => 'EXACT_REQ8 <\x{2b9}>',
+ '(?i)[\x{2b9}]' => 'EXACT_NF_REQ8 <\x{2b9}>', # Doesn't participate in a fold
+ '(?8)(?i)[\x{2b9}]' => 'EXACT_NF_REQ8 <\x{2b9}>',
'(?i)[\x{2bc}]' => 'EXACTFU_REQ8 <\x{2bc}>', # Part of a multi-char fold, ASCII component
'(?i)[\x{390}]' => 'EXACTFU_REQ8 <\x{3b9}\x{308}\x{301}>', # Part of a multi-char fold, no ASCII component
@@ -735,6 +735,11 @@ my @tests = (
'(?i)[\x{FB06}]' => 'EXACTFU <st>',
'[a][b]' => 'EXACT <ab>',
+ # 0xB6 is the non-folding PILCROW SIGN on both ASCII and supported EBCDIC
+ # platforms, so this tests a non-ASCII character portably.
+ '(?i)[:][\x{b6}]' => 'EXACT_NF <:\x{b6}>',
+ '(?i)[:][\x{2029}]' => 'EXACT_NF_REQ8 <:\x{2029}>',
+ '(?i)[\x{2029}][:]' => 'EXACT_NF_REQ8 <\x{2029}:>',
'[a]\x{100}' => 'EXACT_REQ8 <a\x{100}>',
'(?8)[\x{100}]a' => 'EXACT_REQ8 <\x{100}a>',
'(?i)[b][c]' => 'EXACTFU <bc>',
@@ -842,8 +847,8 @@ for my $char (@single_chars_to_test) {
$op = ($charset eq 'l')
? 'EXACTL'
: ($cp < 256)
- ? 'EXACT'
- : 'EXACT_REQ8';
+ ? ($fold ? 'EXACT_NF' : 'EXACT')
+ : ($fold ? 'EXACT_NF_REQ8' : 'EXACT_REQ8');
}
else {
$op = ($charset eq 'aa')
diff --git a/t/re/re_tests b/t/re/re_tests
index b313b83552..42f89c2a09 100644
--- a/t/re/re_tests
+++ b/t/re/re_tests
@@ -2313,6 +2313,17 @@ a+X(*COMMIT)j aXaXj n - - - PLUS skip after (*COMMIT) [ASCII]
\A(?=(?=a)b*)[a-z]a\z aa y $& aa - zero-length body with a required nested assertion
\A(?=(?=a)b*)[a-z]a\z ba n - - - required nested assertion must still be checked
+# GH #19953: non-folding cleanup must respect scoped folding rules.
+(?:(?iaa:[\x{FB00}])(?iu:ab)|z)\z \x{FB00}ab y $& \x{FB00}ab - /aa ligature before /u folded literal
+(?:(?iaa:[\x{FB00}])(?iu:ab)|z)\z ffab n - - - /aa ligature does not fold to ASCII
+(?:(?iu:ab)(?iaa:[\x{FB00}])|z)\z ab\x{FB00} y $& ab\x{FB00} - /aa ligature after /u folded literal
+(?:(?iu:ab)(?iaa:[\x{FB00}])|z)\z abff n - - - /aa ligature does not fold after /u literal
+(?i:[\x{2029}][:])\z \x{2029}: y $& \x{2029}: - wide non-folding before narrow non-folding
+(?i:[:][\x{2029}])\z :\x{2029} y $& :\x{2029} - wide non-folding after narrow non-folding
+(?i:_\x{2029}|_#)\z _# y $& _# - a wide alternative does not make the shared prefix require UTF-8
+(?i:_\x{2029}|_#)\z _\x{2029} y $& _\x{2029} - wide non-folding trie word after shared prefix
+(?i:\x{2029}|_)\z _ y $& _ - narrow non-folding trie word alongside wide word
+
# GH #24945: captures from failed iterations of nested fixed-width quantifiers
(?:(aa){2})* aa y ${\(defined($1) ? $1 : q(undef))} undef - failed first outer iteration must not leave a capture
(?:([ab]{2}){2})* aabbaa y $&-$1 aabb-bb - failed next outer iteration must restore the last completed capture